├── .gitignore ├── AEToolbox.jsx ├── LICENSE.txt ├── README.md └── build ├── aetoolbox_advanced.js ├── aetoolbox_basic.js ├── aetoolbox_export.js ├── aetoolbox_guide.js ├── aetoolbox_image.js ├── aetoolbox_import.js ├── aetoolbox_main.js ├── aetoolbox_pip.js ├── aetoolbox_plugins.js ├── aetoolbox_rigging.js ├── aetoolbox_stereo.js ├── aetoolbox_util.js ├── build.bat └── build.command /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | 3 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The AEToolbox UI panel was developed with support from: 2 | Canada Council on the Arts 3 | Eyebeam Art + Technology Center 4 | Ontario Arts Council / Chalmers Family Fund 5 | 6 | Copyright (c) 2019 Nick Fox-Gieg 7 | http://fox-gieg.com 8 | 9 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 10 | 11 | The MIT License 12 | 13 | Permission is hereby granted, free of charge, to any person obtaining a copy 14 | of this software and associated documentation files (the "Software"), to deal 15 | in the Software without restriction, including without limitation the rights 16 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 | copies of the Software, and to permit persons to whom the Software is 18 | furnished to do so, subject to the following conditions: 19 | 20 | The above copyright notice and this permission notice shall be included in 21 | all copies or substantial portions of the Software. 22 | 23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 29 | THE SOFTWARE. 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | AEToolbox UI panel
2 | The AEToolbox UI panel was developed with support from:
3 |     Canada Council on the Arts
4 |     Eyebeam Art + Technology Center
5 |     Ontario Arts Council / Chalmers Family Fund
6 |
7 | Copyright (c) 2019 Nick Fox-Gieg
8 | http://fox-gieg.com
9 |
10 | To install, drop the AEToolbox.jsx file into your After Effects ScriptUI Panels directory. After restarting After Effects, you can access the AEToolbox panel from the Window menu, just like your other panels. By default, this is:
11 | ``` 12 | // Mac: 13 | /Applications/AFTER_EFFECTS_VERSION/Scripts/ScriptUI Panels/ 14 | 15 | // Windows: 16 | C:\Program Files\AFTER_EFFECTS_VERSION\Scripts\ScriptUI Panels\ 17 | ``` 18 |
19 | List of Features:
20 |
21 | 1. BASIC
22 | 1.1. Nulls for Pins (layer selection): Creates a controller null for each puppet pin on a layer.
23 | 1.2. Parent Chain (layer selection): Parent a chain of layers one to another.
24 | 1.3. Locator Null...
25 |     (layer selection): Creates a new null at the location of each selected layer.
26 |     (no selection): Creates a new null in the center of the comp.
27 | 1.4. Move to Position (layer selection): Moves all layers to the location of the last selected layer.
28 | 1.5. Make Loop...
29 |     (layer selection): Puts a cycle expression on Time Remap.
30 |     (property selection): Puts a cycle expression on the selected properties.
31 | 1.6. Random Position (layer selection): Randomizes a layer's position.
32 | 1.7. Graph Audio (layer selection): Converts audio to keyframes and enables the graph view.
33 | 1.8. Isolate Color (layer selection): Keys out everything but selected color.
34 |
35 | 2. ADVANCED
36 | 2.1. Bake Keyframes (layer selection): Bakes expressions and puppet pins to keyframes.
37 | 2.2. Lock Y Rotation (layer selection): Forces a layer to always face the camera.
38 | 2.3. Auto Z Rotation (layer selection): Smart 2D auto-rotation.
39 | 2.4. Parentable Null (layer selection): Creates a null with expressions that solve certain parenting problems.
40 | 2.5. Sine Generator (layer selection): Applies sine-wave motion controls to a layer.
41 | 2.6. Crossfade (comp selection): Fades a layer into a duplicate of itself for a seamless loop.
42 | 2.7. Motion Blur Twos* (layer selection): *Reelsmart Motion Blur* for animation on twos.
43 |
44 | 3. RIGGING
45 | 3.1. Blink Rig (comp selection): Turns a blink layer inside the comp on and off.
46 | 3.2. Jaw Rig (comp selection): Rigs a jaw layer inside the comp for audio control of rotation or position.
47 | 3.3. Snake Rig (layer selection): Rigs a puppet-pin layer for automated snake-like movement.
48 | 3.4. Beam Rig (no selection): Creates a 3D laser effect with start and end nulls.
49 | 3.5. Particle Rig* (no selection): *Particular* null controller for particles.
50 | 3.6. Camera Rig (no selection): Creates a camera rigged for point-of-interest and DoF control.
51 | 3.7. MoSketch Rig (no selection): Creates a null with 3D controls for use with Motion Sketch.
52 | 3.8. Photo Rig (layer selection): Creates precomps that each display one frame from a sequence.
53 |
54 | 4. DEPTH
55 | 4.1. Split s3D Pair (layer selection): Splits a stereo 3D pair video into two left and right comps.
56 | 4.2. Merge s3D Pair (layer selection): Merges two left and right comps into a stereo 3D pair comp.
57 | 4.3. s3D Dispmap...
58 |     (one layer selected): Creates an s3D pair from the selected layer, using it as a displacement map.
59 |     (two layers selected): Creates an s3D pair from the first layer, using the second layer for displacement.
60 | 4.4. Depth Fill (layer selection): Creates a grayscale depth fill based on distance to camera.
61 | 4.5. Depth Sort (layer selection): Sorts layers based on Z depth.
62 | 4.6. Stereo Controller (comp selection): Creates a stereo controller null for a single camera.
63 | 4.7. Vive Recording (layer selection): Splits a quad Vive recording into separate layers.
64 | 4.8. 4K Stereo 360 (layer selection): Creates a standard 4K OU 360 stereo comp.
65 | 4.9. Holoflix 720p (layer selection): Splits a Holoflix 720p clip into RGB and depth comps.
66 |
67 | 5. REFORMAT
68 | 5.1. Vive Recording
69 | 5.2. Holoflix
70 | 5.3. RGBD Toolkit
71 | 5.4. InstaGrid
72 | 5.5. 4K Stereo 360
73 |
74 | 6. IMAGE
75 | 6.1. Soften 1
76 | 6.2. Soften 2
77 | 6.3. High Pass
78 |
79 | 7. GUIDE
80 | 7.1. Onion Skin (no selection): Creates an adjustment layer that applies an onion skin effect.
81 | 7.2. Skeleton View (layer selection): View connections between parent and child layers.
82 |
83 | 8. EXPORT
84 | 8.1. Camera to Maya (layer selection): Export camera to Maya.
85 | 8.2. Unity Anim (layer selection): Export keyframes to Unity anim.
86 | 8.3. JSON Export (layer selection): Export keyframes to JSON.
87 | 8.4. XML Export (layer selection): Export keyframes to XML.
88 |
89 | 9. IMPORT
90 | 9.1. GML to Position (comp selection): Import position keyframes from GML.
91 |
92 | 10. PLUGIN
93 | 10.1. RSMB Twos
94 | 10.2. Particular Rig
95 | 10.3. Freeform Pro Rig
96 | -------------------------------------------------------------------------------- /build/aetoolbox_advanced.js: -------------------------------------------------------------------------------- 1 | // Notes: apply process to any number of layers or properties 2 | function bakePinKeyframes() { 3 | app.beginUndoGroup("Bake Pin Keyframes"); 4 | 5 | var theComp = app.project.activeItem; 6 | 7 | if (theComp == null || !(theComp instanceof CompItem)) { 8 | alert(errorNoCompSelected); 9 | } else { 10 | var theLayers = theComp.selectedLayers; 11 | if (theLayers.length==0) { 12 | alert(errorNoLayerSelected); 13 | } else { 14 | for (var i = 0; i < theLayers.length; i++) { 15 | var curLayer = theLayers[i]; 16 | if (curLayer.matchName == "ADBE AV Layer") { 17 | if (curLayer.effect.puppet != null) { 18 | var wherePins = curLayer.property("Effects").property("Puppet").property("arap").property("Mesh").property("Mesh 1").property("Deform"); 19 | var pinCount = wherePins.numProperties; 20 | for (var n = 1; n <= pinCount; n++) { 21 | // Get position of puppet pin 22 | var pin = curLayer.effect("Puppet").arap.mesh("Mesh 1").deform(n).position; 23 | try { 24 | convertToKeyframes(pin); 25 | } catch(err) {} 26 | } 27 | } 28 | 29 | var curProperty; 30 | try { 31 | curProperty = curLayer.property("position"); 32 | convertToKeyframes(curProperty); 33 | } catch(err) {} 34 | try { 35 | curProperty = curLayer.property("anchorPoint"); 36 | convertToKeyframes(curProperty); 37 | } catch(err) {} 38 | try { 39 | curProperty = curLayer.property("rotation"); 40 | convertToKeyframes(curProperty); 41 | } catch(err) {} 42 | try { 43 | curProperty = curLayer.property("scale"); 44 | convertToKeyframes(curProperty); 45 | } catch(err) {} 46 | try { 47 | curProperty = curLayer.property("opacity"); 48 | convertToKeyframes(curProperty); 49 | } catch(err) {} 50 | //~~ 51 | try { 52 | curProperty = curLayer.property("pointOfInterest"); 53 | convertToKeyframes(curProperty); 54 | } catch(err) {} 55 | try { 56 | curProperty = curLayer.property("focusDistance"); 57 | convertToKeyframes(curProperty); 58 | } catch(err) {} 59 | } else { 60 | alert("Only works on footage layers."); 61 | } 62 | } 63 | } 64 | } 65 | 66 | app.endUndoGroup(); 67 | } 68 | 69 | /////////////////////////////////////////////////////////////////////////////////////////// 70 | 71 | // Notes: apply process to any number of layers 72 | function lockRotation() { 73 | app.beginUndoGroup("Apply Y Rotation Lock"); 74 | 75 | var theComp = app.project.activeItem; 76 | 77 | if (theComp == null || !(theComp instanceof CompItem)) { 78 | alert(errorNoCompSelected); 79 | } else { 80 | var theLayers = theComp.selectedLayers; 81 | 82 | if (theLayers.length==0) { 83 | alert(errorNoLayerSelected); 84 | } else { 85 | for (var i = 0; i < theLayers.length; i++) { 86 | var curLayer = theLayers[i]; 87 | 88 | curLayer.threeDLayer = true; 89 | 90 | var expr = "var delta = toWorld(anchorPoint) - thisComp.activeCamera.toWorld([0,0,0]);" + "\r" + 91 | "radiansToDegrees(Math.atan2(delta[0],delta[2]));" 92 | 93 | curLayer.transform.yRotation.expression = expr; 94 | } 95 | } 96 | } 97 | } 98 | 99 | /////////////////////////////////////////////////////////////////////////////////////////// 100 | 101 | // Notes: apply process to any number of layers 102 | function autoOrientZ() { 103 | app.beginUndoGroup("Apply Auto-Orient Z"); 104 | 105 | var theComp = app.project.activeItem; 106 | 107 | if (theComp == null || !(theComp instanceof CompItem)) { 108 | alert(errorNoCompSelected); 109 | } else { 110 | var theLayers = theComp.selectedLayers; 111 | 112 | if (theLayers.length==0) { 113 | alert(errorNoLayerSelected); 114 | } else { 115 | for (var i = 0; i < theLayers.length; i++) { 116 | var curLayer = theLayers[i]; 117 | 118 | var easeSlider = curLayer.property("Effects").addProperty("Slider Control"); 119 | easeSlider.name = "corner ease"; 120 | easeSlider.property("Slider").setValue(3); 121 | 122 | var expr = "var cornerEase = effect(\"corner ease\")(\"Slider\");" + "\r" + 123 | "var pre = position.valueAtTime(time-thisComp.frameDuration*cornerEase);" + "\r" + 124 | "var post = position.valueAtTime(time+thisComp.frameDuration*cornerEase);" + "\r" + 125 | "var delta = post - pre;" + "\r" + 126 | "if (delta[0]==0 && delta[1]==0) {" + "\r" + // if no change in vector, maintain current heading 127 | " rotation;" + "\r" + 128 | "} else { " + "\r" + // use the vector direction to orient. Flip Y to account for cartesian Y being up and AE Y being down 129 | " radiansToDegrees(Math.atan2(delta[0],-delta[1]));" + "\r" + 130 | "}"; 131 | if (curLayer.threeDLayer) { 132 | curLayer.transform.zRotation.expression = expr; 133 | } else { 134 | curLayer.transform.rotation.expression = expr; 135 | } 136 | } 137 | } 138 | } 139 | 140 | app.endUndoGroup(); 141 | } 142 | 143 | /////////////////////////////////////////////////////////////////////////////////////////// 144 | 145 | // Notes: Generate null for things with weird coordinate spaces 146 | function parentableNull() { 147 | app.beginUndoGroup("Create Parentable Null"); 148 | 149 | var theComp = app.project.activeItem; 150 | 151 | if (theComp == null || !(theComp instanceof CompItem)) { 152 | alert(errorNoCompSelected); 153 | } else { 154 | var theLayers = theComp.selectedLayers; 155 | if (theLayers.length==0) { 156 | alert(errorNoLayerSelected); 157 | } else { 158 | for (var i = 0; i < theLayers.length; i++) { 159 | var curLayer = theLayers[i]; 160 | 161 | if (curLayer.matchName == "ADBE AV Layer") { 162 | var solid = theComp.layers.addNull(); 163 | solid.name = curLayer.name + "_ctl"; 164 | var expr = "var L = thisComp.layer(\"" + curLayer.name + "\");" + "\r" + 165 | "L.toComp(L.transform.anchorPoint);"; 166 | solid.property("position").expression = expr; 167 | } else { 168 | alert(errorFootageOnly); 169 | } 170 | } 171 | } 172 | } 173 | 174 | app.endUndoGroup(); 175 | } 176 | 177 | /////////////////////////////////////////////////////////////////////////////////////////// 178 | 179 | // Notes: process for any number of layers--applies sine wave controllers 180 | function sineWave() { 181 | app.beginUndoGroup("Apply Sine Wave Controls"); 182 | 183 | var theComp = app.project.activeItem; 184 | 185 | if (theComp == null || !(theComp instanceof CompItem)) { 186 | alert(errorNoCompSelected); 187 | } else { 188 | var theLayers = theComp.selectedLayers; 189 | if (theLayers.length==0) { 190 | alert(errorNoLayerSelected); 191 | } else { 192 | for (var i = 0; i < theLayers.length; i++) { 193 | var curLayer = theLayers[i]; 194 | 195 | var angleSlider = curLayer.property("Effects").addProperty("Angle Control"); 196 | angleSlider.name = "angle"; 197 | var velSlider = curLayer.property("Effects").addProperty("Slider Control"); 198 | velSlider.name = "velocity"; 199 | 200 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 201 | var expr = "var a = degreesToRadians((effect(\"angle\")(\"Angle\"))-90);" + "\r" + 202 | "var x1 = Math.cos(a);" + "\r" + 203 | "var y1 = Math.sin(a);" + "\r" + 204 | "var v = effect(\"velocity\")(\"Slider\")*(1/thisComp.frameDuration);" + "\r" + 205 | "var x2 = transform.position[0] + (time - inPoint) * v * x1;" + "\r" + 206 | "var y2 = transform.position[1] + (time - inPoint) * v * y1;" + "\r"; 207 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 208 | 209 | var ampSlider = curLayer.property("Effects").addProperty("Slider Control"); 210 | ampSlider.name = "amp"; 211 | var freqSlider = curLayer.property("Effects").addProperty("Slider Control"); 212 | freqSlider.name = "freq"; 213 | //~~ 214 | var xAxis = curLayer.property("Effects").addProperty("Checkbox Control"); 215 | xAxis.name = "x axis"; 216 | xAxis.property("Checkbox").setValue(0); 217 | var yAxis = curLayer.property("Effects").addProperty("Checkbox Control"); 218 | yAxis.name = "y axis"; 219 | yAxis.property("Checkbox").setValue(1); 220 | var zAxis = curLayer.property("Effects").addProperty("Checkbox Control"); 221 | zAxis.name = "z axis"; 222 | zAxis.property("Checkbox").setValue(0); 223 | //~~ 224 | var xOffset = curLayer.property("Effects").addProperty("Slider Control"); 225 | xOffset.name = "x offset"; 226 | var yOffset = curLayer.property("Effects").addProperty("Slider Control"); 227 | yOffset.name = "y offset"; 228 | var zOffset = curLayer.property("Effects").addProperty("Slider Control"); 229 | zOffset.name = "z offset"; 230 | //~~ 231 | expr += "var x = x2;" + "\r" + 232 | "var y = y2;" + "\r"; 233 | 234 | if(curLayer.threeDLayer) { 235 | expr += "var z = transform.position[2];" + "\r"; 236 | } else { 237 | expr += "var z = 0;" + "\r"; 238 | } 239 | 240 | expr += "var amp = effect(\"amp\")(\"Slider\");" + "\r" + 241 | "var freq = effect(\"freq\")(\"Slider\");" + "\r" + 242 | "var ox = effect(\"x offset\")(\"Slider\");" + "\r" + 243 | "var oy = effect(\"y offset\")(\"Slider\");" + "\r" + 244 | "var oz = effect(\"z offset\")(\"Slider\");" + "\r" + 245 | "var sx = amp * Math.sin(freq * (time + ox));" + "\r" + 246 | "var sy = amp * Math.sin(freq * (time + oy));" + "\r" + 247 | "var sz = amp * Math.sin(freq * (time + oz));" + "\r" + 248 | "if (effect(\"x axis\")(\"Checkbox\") == 1) x += sx;" + "\r" + 249 | "if (effect(\"y axis\")(\"Checkbox\") == 1) y += sy;" + "\r" + 250 | "if (effect(\"z axis\")(\"Checkbox\") == 1) z += sz;" + "\r" + 251 | "[x, y, z];"; 252 | 253 | curLayer.property("Position").expression = expr; 254 | } 255 | } 256 | } 257 | 258 | app.endUndoGroup(); 259 | } 260 | 261 | /////////////////////////////////////////////////////////////////////////////////////////// 262 | 263 | // Notes: apply process to any number of layers 264 | function crossfader() { 265 | app.beginUndoGroup("Crossfade Layers"); 266 | 267 | var theComp = app.project.activeItem; 268 | 269 | if (theComp == null || !(theComp instanceof CompItem)) { 270 | alert(errorNoCompSelected); 271 | } else { 272 | var theLayers = theComp.selectedLayers; 273 | 274 | if (theLayers.length==0) { 275 | alert(errorNoLayerSelected); 276 | } else { 277 | for (var i = 0; i < theLayers.length; i++) { 278 | app.executeCommand(app.findMenuCommandId("Duplicate")); 279 | var curLayer1 = theComp.selectedLayers[0]; 280 | app.executeCommand(app.findMenuCommandId("Split Layer")); 281 | var curLayer2 = theComp.selectedLayers[0]; 282 | 283 | curLayer1.property("Opacity").setValueAtTime(curLayer1.inPoint,0); 284 | curLayer1.property("Opacity").setValueAtTime(curLayer1.outPoint,100); 285 | curLayer2.property("Opacity").setValueAtTime(curLayer2.inPoint,100); 286 | curLayer2.property("Opacity").setValueAtTime(curLayer2.outPoint,0); 287 | 288 | curLayer2.startTime = -1 * (curLayer1.outPoint-curLayer1.inPoint); 289 | curLayer1.startTime = curLayer2.outPoint-curLayer2.inPoint; 290 | 291 | curLayer1.selected=true; 292 | curLayer2.selected=true; 293 | theLayers[i].selected=true; 294 | } 295 | } 296 | } 297 | 298 | app.endUndoGroup(); 299 | } 300 | 301 | /////////////////////////////////////////////////////////////////////////////////////////// 302 | /////////////////////////////////////////////////////////////////////////////////////////// 303 | -------------------------------------------------------------------------------- /build/aetoolbox_basic.js: -------------------------------------------------------------------------------- 1 | // Notes: process for any number of layers or properties 2 | function nullsForPins() { 3 | app.beginUndoGroup("Create Nulls for Pins"); 4 | 5 | var theComp = app.project.activeItem; 6 | 7 | if (theComp == null || !(theComp instanceof CompItem)) { 8 | alert(errorNoCompSelected); 9 | } else { 10 | var theLayers = theComp.selectedLayers; 11 | 12 | if (theLayers.length==0) { 13 | alert(errorNoLayerSelected); 14 | } else { 15 | for (var i = 0; i < theLayers.length; i++) { 16 | var curLayer = theLayers[i]; 17 | // condition 1: must be a footage layer 18 | if (curLayer.matchName == "ADBE AV Layer") { 19 | //condition 2: must be a 2D layer 20 | if (!curLayer.threeDLayer) { 21 | //condition 3: must have puppet pins applied 22 | if (curLayer.effect.puppet != null) { 23 | var wherePins = curLayer.property("Effects").property("Puppet").property("arap").property("Mesh").property("Mesh 1").property("Deform"); 24 | var pinCount = wherePins.numProperties; 25 | 26 | for (var n = 1; n <= pinCount; n++) { 27 | var pin = curLayer.effect("Puppet").arap.mesh("Mesh 1").deform(n); 28 | //var solid = theComp.layers.addSolid([1.0, 1.0, 0], nullName, 50, 50, 1); 29 | var solid = theComp.layers.addNull(); 30 | //solid.name = pin.name + "_ctl"; 31 | solid.name = curLayer.name + "_" + pin.name; 32 | 33 | var p = pin.position.value; 34 | 35 | //scaled from layer coords to world coords 36 | solid.property("position").setValue(harvestPoint(p, curLayer, solid, "toComp")); 37 | 38 | // Position of puppet pin (Standard, Advanced) 39 | try { 40 | var pinExpr = "fromComp(thisComp.layer(\""+solid.name+"\").toComp(thisComp.layer(\""+solid.name+"\").anchorPoint));"; 41 | pin.position.expression = pinExpr; 42 | } catch(err) {} 43 | 44 | // Rotation of puppet pin (Bend, Advanced) 45 | try { 46 | var pinExpr = "thisComp.layer(\""+solid.name+"\").transform.rotation - 0;"; 47 | pin.rotation.expression = pinExpr; 48 | } catch(err) {} 49 | 50 | // Scale of puppet pin (Bend, Advanced) 51 | try { 52 | var pinExpr = "thisComp.layer(\""+solid.name+"\").transform.scale[0];"; 53 | pin.scale.expression = pinExpr; 54 | } catch(err) {} 55 | } 56 | 57 | curLayer.property("Effects").property("Puppet").property("On Transparent").setValue(1); 58 | curLayer.locked = true; 59 | } else { 60 | alert("Layer must have puppet pins."); 61 | } 62 | } else { 63 | alert("Layer must be 2D."); 64 | } 65 | } else { 66 | alert(errorFootageOnly); 67 | } 68 | } 69 | } 70 | } 71 | 72 | app.endUndoGroup(); 73 | } 74 | 75 | /////////////////////////////////////////////////////////////////////////////////////////// 76 | 77 | // Notes: apply process to any number of layers 78 | function parentChain() { 79 | app.beginUndoGroup("Parent Chain of Layers"); 80 | 81 | var theComp = app.project.activeItem; 82 | 83 | if (theComp == null || !(theComp instanceof CompItem)) { 84 | alert(errorNoCompSelected); 85 | } else { 86 | var theLayers = theComp.selectedLayers; 87 | 88 | if (theLayers.length==0) { 89 | alert(errorNoLayerSelected); 90 | } else { 91 | for (var i = 0; i < theLayers.length; i++) { 92 | if (i == 0) { 93 | for (var j = 0; j < theLayers.length; j++) { 94 | if(theLayers[i].parent==theLayers[j]) theLayers[i].parent=null; 95 | } 96 | } else { 97 | theLayers[i].parent = null; 98 | theLayers[i].parent = theLayers[i-1]; 99 | } 100 | } 101 | 102 | var doSkeleview = confirm("Create skeleton guide layer?"); 103 | if (doSkeleview) { 104 | skeleView(false); 105 | } 106 | } 107 | } 108 | 109 | app.endUndoGroup(); 110 | } 111 | 112 | /////////////////////////////////////////////////////////////////////////////////////////// 113 | 114 | // Notes: process for any number of layers or properties 115 | function locatorNull() { 116 | app.beginUndoGroup("Create Locator Nulls for Selected Layers"); 117 | 118 | var theComp = app.project.activeItem; 119 | 120 | if (theComp == null || !(theComp instanceof CompItem)) { 121 | alert(errorNoCompSelected); 122 | } else { 123 | var theLayers = theComp.selectedLayers; 124 | if (theLayers.length==0) { 125 | theComp.layers.addNull(); 126 | } else { 127 | for (var i = 0; i < theLayers.length; i++) { 128 | var curLayer = theLayers[i]; 129 | var mama; 130 | if(curLayer.parent) { 131 | mama = curLayer.parent; 132 | curLayer.parent = null; 133 | } 134 | var p = curLayer.property("position").value; 135 | var solid = theComp.layers.addNull(); 136 | solid.name = curLayer.name + "_loc"; 137 | 138 | if(curLayer.threeDLayer) solid.threeDLayer = true; 139 | 140 | solid.property("position").setValue(p); 141 | try { 142 | curLayer.parent = mama; 143 | } catch(err) {} 144 | } 145 | } 146 | } 147 | 148 | app.endUndoGroup(); 149 | } 150 | 151 | /////////////////////////////////////////////////////////////////////////////////////////// 152 | 153 | // Notes: process for any number of layers or properties 154 | function moveToPos() { 155 | app.beginUndoGroup("Move to Last Selected Layer's Position"); 156 | 157 | var theComp = app.project.activeItem; 158 | 159 | if (theComp == null || !(theComp instanceof CompItem)) { 160 | alert(errorNoCompSelected); 161 | } else { 162 | var theLayers = theComp.selectedLayers; 163 | if (theLayers.length <= 1) { 164 | alert("Select at least two Layers."); 165 | } else { 166 | for (var i = 0; i < theLayers.length-1; i++) { 167 | var lastLayer = theLayers[theLayers.length-1]; 168 | 169 | var curLayer = theLayers[i]; 170 | var mama; //holds parent if we need to temporary disable it 171 | var papa; 172 | if(curLayer.parent) { 173 | mama = curLayer.parent; 174 | curLayer.parent = null; 175 | } 176 | if(lastLayer.parent) { 177 | papa = lastLayer.parent; 178 | lastLayer.parent = null; 179 | } 180 | //~~~~ 181 | var lp = lastLayer.property("Position"); 182 | var cp = curLayer.property("Position"); 183 | if (lp.numKeys <= 0 && cp.numKeys <= 0) { // neither source nor dest has keys 184 | cp.setValue(lp.value); 185 | } else if (lp.numKeys > 0 && cp.numKeys <= 0) { // source has keys but dest doesn"t 186 | cp.setValue(lp.value); 187 | } else { // either source or dest has keys 188 | cp.setValueAtTime(theComp.time, lp.value); 189 | } 190 | 191 | //~~~~ 192 | try { 193 | curLayer.parent = mama; 194 | } catch(err) {} 195 | try { 196 | lastLayer.parent = papa; 197 | } catch(err) {} 198 | } 199 | } 200 | } 201 | 202 | app.endUndoGroup(); 203 | } 204 | 205 | /////////////////////////////////////////////////////////////////////////////////////////// 206 | 207 | // Notes: process for any number of layers--enables time remap and applies a loop script 208 | function makeLoop() { 209 | app.beginUndoGroup("Apply Loop Expression"); 210 | 211 | var theComp = app.project.activeItem; 212 | 213 | if (theComp == null || !(theComp instanceof CompItem)) { 214 | alert(errorNoCompSelected); 215 | } else { 216 | var theLayers = theComp.selectedLayers; 217 | if (theLayers.length==0) { 218 | alert(errorNoLayerSelected); 219 | } else { 220 | for (var i = 0; i < theLayers.length; i++) { 221 | var curLayer = theLayers[i]; 222 | 223 | var curProperties = curLayer.selectedProperties; 224 | if (curProperties.length == 0) { 225 | //alert("Please select some properties and run the script again."); 226 | //*** Running this on a selected layer does a time remap... *** 227 | if (curLayer.matchName == "ADBE AV Layer") { 228 | curLayer.timeRemapEnabled = true; 229 | var expr = "loopOut(\"cycle\");"; 230 | curLayer.timeRemap.expression = expr; 231 | //~~~~ 232 | //now we have to move the end keyframe one frame sooner--by default you get a glitch. 233 | var tr = curLayer.property("Time Remap"); 234 | var trEndTime = tr.keyTime(2); 235 | var trEndVal = tr.keyValue(2); 236 | //alert("key time: " + trEndTime + " key value: " + trEndVal); 237 | tr.removeKey(2); 238 | tr.setValueAtTime(trEndTime-theComp.frameDuration,trEndVal-theComp.frameDuration); //minus one frame 239 | tr.setValueAtTime(trEndTime,0); //force loop at end. 240 | //~~~~ 241 | } else { 242 | alert(errorFootageOnly); 243 | } 244 | } else { 245 | //*** Running this on selected properties cycles keyframes *** 246 | for (var j = 0; j 0) doIt=true; 250 | } catch(err) {} 251 | if (doIt) { 252 | var expr = "loopOut(\"cycle\");"; 253 | curProperties[j].expression = expr; 254 | } else { 255 | alert("Can't apply this expression to a property with no keyframes.") 256 | } 257 | } 258 | } 259 | } 260 | } 261 | } 262 | 263 | app.endUndoGroup(); 264 | } 265 | 266 | /////////////////////////////////////////////////////////////////////////////////////////// 267 | 268 | // Notes: apply process to any number of layers 269 | function randomPos() { 270 | app.beginUndoGroup("Randomize Position"); 271 | 272 | var theComp = app.project.activeItem; 273 | 274 | if (theComp == null || !(theComp instanceof CompItem)) { 275 | alert(errorNoCompSelected); 276 | } else { 277 | var theLayers = theComp.selectedLayers; 278 | var allLayers = theComp.layers; 279 | var compDepth = 2000; 280 | 281 | if (theLayers.length==0) { 282 | alert(errorNoLayerSelected); 283 | } else { 284 | for (var i = 0; i < theLayers.length; i++) { 285 | var curLayer = theLayers[i]; 286 | var p = curLayer.property("Position"); 287 | var x = Math.random() * theComp.width; 288 | var y = Math.random() * theComp.height; 289 | var z = Math.random() * compDepth; 290 | 291 | if (p.numKeys > 0) { 292 | p.setValueAtTime(theComp.time, [x, y, z]); 293 | } else { 294 | p.setValue([x, y, z]); 295 | } 296 | } 297 | } 298 | } 299 | 300 | app.endUndoGroup(); 301 | } 302 | 303 | /////////////////////////////////////////////////////////////////////////////////////////// 304 | 305 | // Notes: apply process to any number of layers 306 | function graphAudio() { 307 | app.beginUndoGroup("Graph Audio"); 308 | 309 | var theComp = app.project.activeItem; 310 | 311 | if (theComp == null || !(theComp instanceof CompItem)) { 312 | alert(errorNoCompSelected); 313 | } else { 314 | var theLayers = theComp.selectedLayers; 315 | if (theLayers.length==0) { 316 | alert(errorNoLayerSelected); 317 | } else { 318 | for (var i = 0; i < theLayers.length; i++) { 319 | var curLayer = theLayers[i]; 320 | if (curLayer.matchName == "ADBE AV Layer" && curLayer.hasAudio) { 321 | convertAudioToKeyframes(curLayer); 322 | var allLayers = theComp.layers; 323 | var aud = allLayers[1]; 324 | aud.name = curLayer.name + " Audio Amplitude"; 325 | var theProperty = aud.effect("Both Channels")("Slider"); 326 | theProperty.selected = true; 327 | } else { 328 | alert("Only works on layers with audio."); 329 | } 330 | } 331 | } 332 | } 333 | 334 | app.endUndoGroup(); 335 | } 336 | 337 | /////////////////////////////////////////////////////////////////////////////////////////// 338 | 339 | // Notes: apply process to any number of layers. 340 | function isolateColor() { 341 | app.beginUndoGroup("Isolate Color"); 342 | 343 | var theComp = app.project.activeItem; 344 | 345 | if (theComp == null || !(theComp instanceof CompItem)) { 346 | alert(errorNoCompSelected); 347 | } else { 348 | var theLayers = theComp.selectedLayers; 349 | if (theLayers.length==0) { 350 | alert(errorNoLayerSelected); 351 | } else { 352 | for (var i = 0; i < theLayers.length; i++) { 353 | var curLayer = theLayers[i]; 354 | if (curLayer.matchName == "ADBE AV Layer") { 355 | var setMatte = curLayer.property("Effects").addProperty("Set Matte"); 356 | setMatte.property("Take Matte From Layer").setValue(0); 357 | setMatte.enabled = false; 358 | var colorKey = curLayer.property("Effects").addProperty("Linear Color Key"); 359 | colorKey.property("Key Operation").setValue(2); 360 | var simpleChoker = curLayer.property("Effects").addProperty("Simple Choker"); 361 | } else { 362 | alert(errorFootageOnly); 363 | } 364 | } 365 | } 366 | } 367 | 368 | app.endUndoGroup(); 369 | } 370 | 371 | /////////////////////////////////////////////////////////////////////////////////////////// 372 | /////////////////////////////////////////////////////////////////////////////////////////// 373 | -------------------------------------------------------------------------------- /build/aetoolbox_export.js: -------------------------------------------------------------------------------- 1 | // Export 2 | function unityAnim() { //start script 3 | app.beginUndoGroup("Export Unity Anim"); 4 | 5 | var theComp = app.project.activeItem; //only selected 6 | 7 | // check if comp is selected 8 | if (theComp == null || !(theComp instanceof CompItem)) { 9 | // if no comp selected, display an alert 10 | alert("Please establish a comp as the active item and run the script again."); 11 | } else { 12 | var theLayers = theComp.selectedLayers; 13 | var allLayers = theComp.layers; 14 | 15 | if (theLayers.length==0) { 16 | alert("Please select some layers and run the script again."); 17 | } else { 18 | 19 | //~~~~~~~~~~~~~~~~~~ 20 | 21 | var unityMainHeader = "%YAML 1.1" + "\r" + 22 | "%TAG !u! tag:unity3d.com,2011:" + "\r" + 23 | "--- !u!74 &7400000"; 24 | 25 | var unityMainFooter = ""; 26 | 27 | var scaleFactor = 5.0; 28 | 29 | //~~~~~~~~~~~~~~~~~~ 30 | for(var i = 0; i < theLayers.length; i++) { 31 | // ...then loop through each layer in the selected comp 32 | // define the layer in the loop we're currently looking at 33 | var curLayer = theLayers[i]; 34 | var fileName = theComp.name + "_" + curLayer.name; 35 | var unityLayerHeader = "AnimationClip:" + "\r" + 36 | " m_ObjectHideFlags: 0" + "\r" + 37 | " m_PrefabParentObject: {fileID: 0}" + "\r" + 38 | " m_PrefabInternal: {fileID: 0}" + "\r" + 39 | " m_Name: " + fileName + "\r" + 40 | " serializedVersion: 4" + "\r" + 41 | " m_AnimationType: 2" + "\r" + 42 | " m_Compressed: 0" + "\r" + 43 | " m_UseHighQualityCurve: 1" + "\r" + 44 | " m_RotationCurves: []" + "\r" + 45 | " m_CompressedRotationCurves: []" + "\r" + 46 | " m_PositionCurves:" + "\r" + 47 | " - curve:" + "\r" + 48 | " serializedVersion: 2" + "\r" + 49 | " m_Curve:"; 50 | var unityLayerFooter = ""; 51 | 52 | var myFile = File.saveDialog("Save your file", ".anim", ""); 53 | var fileOK = myFile.open("w","TEXT","????"); 54 | 55 | myFile.writeln(unityMainHeader); 56 | myFile.writeln(unityLayerHeader); 57 | 58 | var p = curLayer.property("Position"); 59 | for(var j = 0; j < p.numKeys; j++) { 60 | var pp = p.keyValue(j+1); 61 | 62 | pp[0] = ( (pp[0]-(theComp.width/2)) / theComp.width ) * scaleFactor; 63 | pp[1] = ( -1 * (pp[1]-(theComp.height/2)) / theComp.height) * scaleFactor; 64 | pp[2] = ( pp[2] / ((theComp.width+theComp.height)/2) ) * scaleFactor; 65 | 66 | var unityKeyPos = " - time: " + p.keyTime(j+1) + "\r" + 67 | " value: {x: " + pp[0] + ", y: " + pp[1] + ", z: " + pp[2] + "}" + "\r" + 68 | " inSlope: {x: 0, y: 0, z: 0}" + "\r" + 69 | " outSlope: {x: 0, y: 0, z: 0}" + "\r" + 70 | " tangentMode: 0"; 71 | 72 | myFile.writeln(unityKeyPos); 73 | 74 | } 75 | // not using a footer presently 76 | //myFile.writeln(unityLayerFooter); 77 | //myFile.writeln(unityMainFooter); 78 | myFile.close; 79 | } 80 | } 81 | } 82 | 83 | app.endUndoGroup(); 84 | } //end script 85 | 86 | /////////////////////////////////////////////////////////////////////////////////////////// 87 | 88 | // Notes: apply process to any number of layers 89 | function writeExample() { 90 | app.beginUndoGroup("Export Example File"); 91 | 92 | var theComp = app.project.activeItem; 93 | 94 | if (theComp == null || !(theComp instanceof CompItem)) { 95 | alert(errorNoCompSelected); 96 | } else { 97 | var theLayers = theComp.selectedLayers; 98 | var allLayers = theComp.layers; 99 | 100 | if (theLayers.length==0) { 101 | alert(errorNoLayerSelected); 102 | } else { 103 | //~~~~~~~~~~~~~~~~~~ 104 | var fileMainHeader = "Sample Main Header" + "\r"; 105 | var fileMainFooter = "Sample Main Footer" + "\r"; 106 | var scaleFactor = 1.0; 107 | 108 | var myFile = File.saveDialog("Save your file", ".txt", ""); 109 | var fileOK = myFile.open("w","TEXT","????"); 110 | 111 | myFile.writeln(fileMainHeader); 112 | //~~~~~~~~~~~~~~~~~~ 113 | for (var i = 0; i < theLayers.length; i++) { 114 | // ...then loop through each layer in the selected comp 115 | var curLayer = theLayers[i]; 116 | var fileName = theComp.name + "_" + curLayer.name; 117 | var fileLayerHeader = "Sample Layer Header" + "\r"; 118 | var fileLayerFooter = "Sample Layer Footer" + "\r"; 119 | 120 | myFile.writeln(fileLayerHeader); 121 | 122 | var p = curLayer.property("Position"); 123 | for(var j = 0; j < p.numKeys; j++) { 124 | var pp = p.keyValue(j+1); 125 | 126 | pp[0] = ( (pp[0]-(theComp.width/2)) / theComp.width ) * scaleFactor; 127 | pp[1] = ( -1 * (pp[1]-(theComp.height/2)) / theComp.height) * scaleFactor; 128 | pp[2] = ( pp[2] / ((theComp.width+theComp.height)/2) ) * scaleFactor; 129 | 130 | var fileKeyPos = "time: " + p.keyTime(j+1) + ", x: " + pp[0] + ", y: " + pp[1] + ", z: " + pp[2] + "\r"; 131 | 132 | myFile.writeln(fileKeyPos); 133 | 134 | } 135 | myFile.writeln(fileLayerFooter); 136 | } 137 | myFile.writeln(fileMainFooter); 138 | myFile.close; 139 | } 140 | } 141 | 142 | app.endUndoGroup(); 143 | } 144 | 145 | // Notes: apply process to any number of layers or properties 146 | function xmlExport() { 147 | app.beginUndoGroup("Export to XML"); 148 | app.endUndoGroup(); 149 | } 150 | 151 | /////////////////////////////////////////////////////////////////////////////////////////// 152 | 153 | // Notes: apply process to any number of layers or properties 154 | function jsonExport() { 155 | app.beginUndoGroup("Export to JSON"); 156 | 157 | var theComp = app.project.activeItem; 158 | 159 | if (theComp == null || !(theComp instanceof CompItem)) { 160 | alert(errorNoCompSelected); 161 | } else { 162 | var theLayers = theComp.selectedLayers; 163 | if (theLayers.length==0) { 164 | alert(errorNoLayerSelected); 165 | } else { 166 | for (var i = 0; i < theLayers.length; i++) { 167 | var curLayer = theLayers[i]; 168 | if (curLayer.matchName == "ADBE AV Layer") { 169 | var curProperty; 170 | try { 171 | curProperty = curLayer.property("position"); 172 | convertToKeyframes(curProperty); 173 | } catch(err) {} 174 | try { 175 | curProperty = curLayer.property("anchorPoint"); 176 | convertToKeyframes(curProperty); 177 | } catch(err) {} 178 | try { 179 | curProperty = curLayer.property("rotation"); 180 | convertToKeyframes(curProperty); 181 | } catch(err) {} 182 | try { 183 | curProperty = curLayer.property("scale"); 184 | convertToKeyframes(curProperty); 185 | } catch(err) {} 186 | try { 187 | curProperty = curLayer.property("opacity"); 188 | convertToKeyframes(curProperty); 189 | } catch(err) {} 190 | //~~ 191 | try { 192 | curProperty = curLayer.property("pointOfInterest"); 193 | convertToKeyframes(curProperty); 194 | } catch(err) {} 195 | try { 196 | curProperty = curLayer.property("focusDistance"); 197 | convertToKeyframes(curProperty); 198 | } catch(err) {} 199 | } else { 200 | alert("Only works on footage layers."); 201 | } 202 | } 203 | } 204 | } 205 | 206 | app.endUndoGroup(); 207 | } 208 | 209 | /////////////////////////////////////////////////////////////////////////////////////////// 210 | 211 | // Notes: apply process to any number of layers or properties 212 | function cameraToMaya() { 213 | app.beginUndoGroup("Export Camera to Maya"); 214 | 215 | //****************************** MAIN 216 | 217 | // AE_CameraToMaya v1.1n 218 | // by Ryan Gilmore, 2008 219 | // www.urbanspaceman.net 220 | // contact@urbanspaceman.net 221 | 222 | // Select the camera in After Effects you want to send to Maya, and this script will create an .ma file with a copy of the camera in it, with 223 | // correct position, rotation, and focal length. Should work for any AE camera, no matter how it is animated, without any restrictions. 224 | 225 | // fixed for CS6 by Nick Fox-Gieg, 2012 226 | // null export by Nick Fox-Gieg, 2014 227 | 228 | //****************************** GLOBALS 229 | 230 | var f = 0; 231 | 232 | var theComp = app.project.activeItem; 233 | var theLayers = theComp.layers; 234 | var allLayers = theComp.layers; 235 | 236 | var compWidth = theComp.width; 237 | var compHeight = theComp.height; 238 | var selectedLayers = theComp.selectedLayers; 239 | var numLayers = selectedLayers.length; 240 | var theComplength = theComp.duration; //in seconds 241 | var totalFrames=Math.round(theComp.duration * theComp.frameRate) + 1; 242 | var aeCompRate = theComp.frameRate; 243 | var compRate = Math.round(aeCompRate); 244 | var frameDuration = theComp.frameDuration; 245 | 246 | var worldScale = 100; 247 | var worldCenter = [compWidth / 2, compHeight / 2]; 248 | 249 | var aspect = theComp.pixelAspect; 250 | // these are more accurate video PARs, that AE rounds off 251 | // [00] D2 NTSC 0.8592 252 | // [01] D1 NTSC 0.9 253 | // [02] D4 Stan 0.9481481 254 | // [03] SQUARE 1 255 | // [04] D2 PAL 1.0186 256 | // [05] D1 PAL 1.0667 257 | // [06] D1 NTSC wide 1.2 258 | // [07] HDV 1.333 259 | // [08] D1 PAL wide 1.4222 260 | // [09] DVCPROHD 1.5 261 | // [10] D4 Ana 1.8962962 262 | // [11] Ana2:1 2 263 | var ratio= [0.8592, 0.9, 0.9481481, 1.0, 1.0186, 1.0667, 1.2, 1.333, 1.4222, 1.5, 1.8962962, 2]; 264 | if (aspect == 0.86) { aspect =ratio[0] } 265 | else if (aspect == 0.95) {aspect =ratio[2]} 266 | else if (aspect == 1.02) {aspect =ratio[4]} 267 | else if (aspect == 1.07) {aspect =ratio[5]} 268 | else if (aspect == 1.33) {aspect =ratio[7]} 269 | else if (aspect == 1.42) {aspect =ratio[8]} 270 | else if (aspect == 1.9) {aspect =ratio[10]}; 271 | 272 | var frameAspect = (compWidth*aspect)/compHeight; 273 | 274 | mayaFBHeight = 1; // in inches 275 | mayaFilmBack = frameAspect*mayaFBHeight; // in inches 276 | 277 | // fps presets for Maya 278 | /* 279 | if (compRate == 30) {fps = "ntsc"} 280 | else {} 281 | if (compRate == 25) {fps = "pal"} 282 | else {} 283 | if (compRate == 24) {fps = "film"} 284 | else {} 285 | if (compRate == 15) {fps = "game"} 286 | else {} 287 | if (compRate == 48) {fps = "show"} 288 | else {} 289 | if (compRate == 60) {fps = "ntscf"} 290 | else {} 291 | if (compRate == 50) {fps = "palf"} 292 | else {} 293 | */ 294 | if (compRate == 60) fps = "ntscf"; 295 | if (compRate == 50) fps = "palf"; 296 | if (compRate == 48) fps = "show"; 297 | if (compRate == 30) fps = "ntsc"; 298 | if (compRate == 25) fps = "pal"; 299 | if (compRate <= 24 && compRate % 2 == 0) fps = "film"; 300 | if (compRate == 15) fps = "game"; 301 | 302 | //****************************** STEP 1: create free ZYX camera in After Effects 303 | 304 | DeselectProjectWindowItems(); 305 | 306 | // error check: is the comp the active timeline window? 307 | if (app.project.activeItem!=null) { 308 | theComp = app.project.activeItem; 309 | 310 | // error check: is camera selected? 311 | if (theComp.selectedLayers!="") { 312 | theCamera = theComp.selectedLayers; 313 | 314 | // error check: is more than one layer selected? 315 | if (theCamera.length<2) { 316 | CameraName = theCamera[0].name; 317 | 318 | // error check: is it a camera selected? 319 | if (theCamera[0].zoom!=null) { 320 | 321 | theCamera[0].moveToEnd(); //null layers won"t all be counted unless camera is on the bottom 322 | 323 | CamIn=theCamera[0].inPoint; 324 | CamOut=theCamera[0].outPoint; 325 | 326 | // if camera has a parent that uses a scale value other than 100, this will affect rotation and zoom calculations. 327 | // NB: if the scale does not have equal XYZ values, this script won"t work. That"s because this will stretch, 328 | // distort, and skew the camera, and since the first step of this script is to output a free camera, it can"t be done since 329 | // a skewed free camera is impossible in After Effects. 330 | // if their is a parent, the unit value in the rotation matrix is scale/100 331 | // otherwise the unit value is 1. 332 | if (theCamera[0].parent!=null) { 333 | CamMaster=theCamera[0].parent; 334 | CamMasterExpression="this_comp.layer("+"\""+CamMaster.name+"\""+").scale/100"; 335 | } else { 336 | CamMasterExpression="[1,1,1]"; 337 | }; 338 | 339 | // make new camera. This will inherit the Y and X rotations. 340 | theComp.layers.addCamera("CamCopy_yRot_xRot",[0,0]).startTime=0; 341 | CamCopy01=theComp.layer(1); 342 | CamCopy01.inPoint=CamIn; 343 | CamCopy01.outPoint=CamOut; 344 | CamCopy01.pointOfInterest.expression="position"; 345 | CamCopy01.position.setValue([theComp.width/2, theComp.height/2, 0]); 346 | // make camera parent. This is needed to reverse the rotation order. This null will inherit the position and Z rotation. 347 | theComp.layers.addNull(theComp.duration).name="CamCopy_zRot_pos"; 348 | CamParent01=theComp.layer(1); 349 | setNull(CamParent01,CamIn,CamOut,theComp); 350 | // attach child camera to parent 351 | CamCopy01.parent=CamParent01; 352 | 353 | // translate the data from the original camera with expressions 354 | CamParent01.position.expression="L=thisComp.layer("+"\""+CameraName+"\""+");L.toWorld([0,0,0])"; 355 | CamParent01.rotation.expression="L=this_comp.layer("+"\""+CameraName+"\""+");unit="+CamMasterExpression+";u=L.toWorldVec([unit[0],0,0]);v=L.toWorldVec([0,unit[1],0]);w=L.toWorldVec([0,0,unit[2]]);hLock=clamp(u[2],-1,1);h=Math.asin(-hLock);cosH=Math.cos(h);if (Math.abs(cosH) > 0.0005) {p=Math.atan2(v[2], w[2]);b=Math.atan2(u[1],u[0]/thisComp.pixelAspect);} else { b=Math.atan2(w[1], v[1]);p=0;}BHP = [ radiansToDegrees(b), radiansToDegrees(h), radiansToDegrees(p) ];BHP[0]"; 356 | CamCopy01.orientation.expression="L=this_comp.layer("+"\""+CameraName+"\""+");unit="+CamMasterExpression+";u=L.toWorldVec([unit[0],0,0]);v=L.toWorldVec([0,unit[1],0]);w=L.toWorldVec([0,0,unit[2]]);hLock=clamp(u[2],-1,1);h=Math.asin(-hLock);cosH=Math.cos(h);if (Math.abs(cosH) > 0.0005) {p=Math.atan2(v[2], w[2]);b=Math.atan2(u[1],u[0]/thisComp.pixelAspect);} else { b=Math.atan2(w[1], v[1]);p=0;}BHP = [ radiansToDegrees(b), radiansToDegrees(h), radiansToDegrees(p) ];[ 0, BHP[1], 0 ]"; 357 | CamCopy01.rotationX.expression="L=this_comp.layer("+"\""+CameraName+"\""+");unit="+CamMasterExpression+";u=L.toWorldVec([unit[0],0,0]);v=L.toWorldVec([0,unit[1],0]);w=L.toWorldVec([0,0,unit[2]]);hLock=clamp(u[2],-1,1);h=Math.asin(-hLock);cosH=Math.cos(h);if (Math.abs(cosH) > 0.0005) {p=Math.atan2(v[2], w[2]);b=Math.atan2(u[1],u[0]/thisComp.pixelAspect);} else { b=Math.atan2(w[1], v[1]);p=0;}BHP = [ radiansToDegrees(b), radiansToDegrees(h), radiansToDegrees(p) ];BHP[2]"; 358 | CamCopy01.zoom.expression="unit="+CamMasterExpression+";this_comp.layer("+"\""+CameraName+"\""+").zoom*1/unit[0]"; 359 | 360 | // Make a second copy of the camera, this time it will be baked 361 | ShortCamName=removeForbiddenCharacters(CameraName); 362 | theComp.layers.addCamera("<"+ShortCamName+">",[0,0]).startTime=0; 363 | CamCopy02=theComp.layer(1); 364 | CamCopy02.inPoint=CamIn; 365 | CamCopy02.outPoint=CamOut; 366 | CamCopy02.pointOfInterest.expression="position"; 367 | CamCopy02.position.setValue([theComp.width/2, theComp.height/2, 0]); 368 | // make seconcd camera parent. 369 | theComp.layers.addNull(theComp.duration).name="<"+ShortCamName+"Parent"+">"; 370 | CamParent02=theComp.layer(1); 371 | setNull(CamParent02,CamIn,CamOut,theComp); 372 | // attach child camera to parent 373 | CamCopy02.parent=CamParent02; 374 | 375 | Bake(theComp, theComp.layer(3).position, CamParent02.position); 376 | Bake(theComp, theComp.layer(3).rotation, CamParent02.rotation); 377 | Bake(theComp, theComp.layer(4).orientation, CamCopy02.orientation); 378 | Bake(theComp, theComp.layer(4).rotationX, CamCopy02.rotationX); 379 | Bake(theComp, theComp.layer(4).zoom, CamCopy02.zoom); 380 | 381 | //remove the expression camera and its parent 382 | theComp.layer(4).remove(); 383 | theComp.layer(3).remove(); 384 | 385 | } else { alert("ERROR!!\r"+ 386 | "Please select a camera. ")}; 387 | } else { alert("ERROR!!\r"+ 388 | "Please select only one layer at a time. ")}; 389 | } else { alert("ERROR!!\r"+ 390 | "A camera must be highlighted, and its timeline must be the active window.")}; 391 | } else { alert("ERROR!!\r"+ 392 | "A camera must be highlighted, and its timeline must be the active window.")}; 393 | 394 | //****************************** STEP 2: create Maya scene file 395 | 396 | var CamName = removeForbiddenCharacters(CameraName); 397 | 398 | // create text file 399 | var myFile = File.saveDialog("Save your file", CamName + ".ma", ""); 400 | var fileOK = myFile.open("w","TEXT","????"); 401 | 402 | // Maya scene file header 403 | myFile.writeln("//Maya ASCII 6.0 scene"); 404 | myFile.writeln("//Name: " + CamName + "_export.ma"); 405 | myFile.writeln("//Last modified:"); 406 | myFile.writeln("requires maya \"6.0\";"); 407 | myFile.writeln("currentUnit -l centimeter -a degree -t " + fps + ";"); 408 | myFile.writeln(""); 409 | 410 | // make camera nodes 411 | 412 | // transform node 413 | myFile.writeln("createNode transform -n \"" + CamName + "\";"); 414 | 415 | // shape node, that will have film back 416 | myFile.writeln("createNode camera -n \"" + CamName + "Shape\" -p \"" + CamName + "\";"); //is parented to the transform node 417 | myFile.writeln(" setAttr -k off \".v\";"); 418 | myFile.writeln(" setAttr \".rnd\" yes;");// renderable 419 | myFile.writeln(" setAttr \".ow\" 10.0;"); 420 | myFile.writeln(" setAttr \".dof\" no;");// depth of field 421 | myFile.writeln(" setAttr \".s\" no;"); 422 | myFile.writeln(" setAttr \".eo\" 1.0;"); 423 | myFile.writeln(" setAttr \".ff\" 1;"); // film fit. 1 = horizontal (FOV measured on the horizontal) 424 | myFile.writeln(" setAttr \".cap\" -type \"double2\" " + mayaFilmBack + " " + mayaFBHeight + ";"); // Camera Aperature 425 | myFile.writeln(" setAttr \".col\" -type \"float3\" 0.0 0.0 0.0 ;"); 426 | myFile.writeln(" setAttr \".imn\" -type \"string\" \"" + CamName + "\";"); 427 | myFile.writeln(" setAttr \".den\" -type \"string\" \"" + CamName + "_Depth\";"); 428 | myFile.writeln(" setAttr \".man\" -type \"string\" \"" + CamName + "_Mask\";"); 429 | //~~~ 430 | /* 431 | var aeZoom = theComp.layer(2).zoom.valueAtTime(0, false); 432 | var HFOV=Math.atan( (compWidth*aspect*0.5) /aeZoom);//half the FOV, in radians 433 | var fLength=( (mayaFilmBack*0.5) / Math.tan(HFOV) ) * 25.4; //in inches, converted to mm 434 | myFile.writeln(" setAttr \".fl\" " + fLength + " ;"); 435 | */ 436 | //~~~ 437 | myFile.writeln(""); 438 | 439 | // X position 440 | myFile.writeln("createNode animCurveTL -n \"" + CamName + "_TranslateX\";"); 441 | myFile.writeln(" setAttr \".tan\" 9;"); 442 | myFile.writeln(" setAttr \".wgt\" no;"); 443 | myFile.write(" setAttr -s " + totalFrames + " \".ktv[1:" + totalFrames + "]\""); 444 | 445 | for (var i=1;i<=totalFrames;i++) { 446 | f=(i-1)*frameDuration; 447 | pos=theComp.layer(1).position.valueAtTime(f, false); 448 | Xpos=(pos[0]-worldCenter[0])/worldScale; 449 | myFile.write(" " + i + " " + Xpos); 450 | } 451 | 452 | myFile.write(";"); 453 | myFile.writeln(""); 454 | myFile.writeln(""); 455 | 456 | // Y position 457 | myFile.writeln("createNode animCurveTL -n \"" + CamName + "_TranslateY\";") 458 | myFile.writeln(" setAttr \".tan\" 9;"); 459 | myFile.writeln(" setAttr \".wgt\" no;"); 460 | myFile.write(" setAttr -s " + totalFrames + " \".ktv[1:" + totalFrames + "]\""); 461 | 462 | for (var i=1;i<=totalFrames;i++) { 463 | f=(i-1)*frameDuration; 464 | pos=theComp.layer(1).position.valueAtTime(f, false); 465 | Ypos=-((pos[1]-worldCenter[1])/worldScale); 466 | myFile.write(" " + i + " " + Ypos); 467 | } 468 | 469 | myFile.write(";"); 470 | myFile.writeln(""); 471 | myFile.writeln(""); 472 | 473 | // Z position 474 | myFile.writeln("createNode animCurveTL -n \"" + CamName + "_TranslateZ\";"); 475 | myFile.writeln(" setAttr \".tan\" 9;"); 476 | myFile.writeln(" setAttr \".wgt\" no;"); 477 | myFile.write(" setAttr -s " + totalFrames + " \".ktv[1:" + totalFrames + "]\""); 478 | 479 | for (var i=1;i<=totalFrames;i++) { 480 | f=(i-1)*frameDuration; 481 | pos=theComp.layer(1).position.valueAtTime(f, false); 482 | Zpos=-(pos[2]/worldScale); 483 | myFile.write(" " + i + " " + Zpos); 484 | } 485 | 486 | myFile.write(";"); 487 | myFile.writeln(""); 488 | myFile.writeln(""); 489 | 490 | // Pitch (X rotation) 491 | myFile.writeln("createNode animCurveTA -n \"" + CamName + "_RotateX\";"); 492 | myFile.writeln(" setAttr \".tan\" 9;"); 493 | myFile.writeln(" setAttr \".wgt\" no;"); 494 | myFile.write(" setAttr -s " + totalFrames + " \".ktv[1:" + totalFrames + "]\""); 495 | 496 | for (var i=1;i<=totalFrames;i++) { 497 | f=(i-1)*frameDuration; 498 | rotX=theComp.layer(2).rotationX.valueAtTime(f, false); 499 | Xrot=rotX; 500 | myFile.write(" " + i + " " + Xrot); 501 | } 502 | 503 | myFile.write(";"); 504 | myFile.writeln(""); 505 | myFile.writeln(""); 506 | 507 | // Heading (Y rotation) 508 | myFile.writeln("createNode animCurveTA -n \"" + CamName + "_RotateY\";"); 509 | myFile.writeln(" setAttr \".tan\" 9;"); 510 | myFile.writeln(" setAttr \".wgt\" no;"); 511 | myFile.write(" setAttr -s " + totalFrames + " \".ktv[1:" + totalFrames + "]\""); 512 | 513 | for (var i=1;i<=totalFrames;i++) { 514 | f=(i-1)*frameDuration; 515 | rotY=theComp.layer(2).orientation.valueAtTime(f, false); 516 | Yrot=-(rotY[1]); 517 | myFile.write(" " + i + " " + Yrot); 518 | } 519 | 520 | myFile.write(";"); 521 | myFile.writeln(""); 522 | myFile.writeln(""); 523 | 524 | // Bank (Z rotation) 525 | myFile.writeln("createNode animCurveTA -n \"" + CamName + "_RotateZ\";"); 526 | myFile.writeln(" setAttr \".tan\" 9;"); 527 | myFile.writeln(" setAttr \".wgt\" no;"); 528 | myFile.write(" setAttr -s " + totalFrames + " \".ktv[1:" + totalFrames + "]\""); 529 | 530 | for (var i=1;i<=totalFrames;i++) { 531 | f=(i-1)*frameDuration; 532 | rotZ=theComp.layer(1).rotation.valueAtTime(f, false); 533 | Zrot=-(rotZ); 534 | myFile.write(" " + i + " " + Zrot); 535 | } 536 | 537 | myFile.write(";"); 538 | myFile.writeln(""); 539 | myFile.writeln(""); 540 | 541 | // Focal length 542 | myFile.writeln("createNode animCurveTU -n \"" + CamName + "Shape_FocalLength\";"); 543 | myFile.writeln(" setAttr \".tan\" 9;"); 544 | myFile.writeln(" setAttr \".wgt\" no;"); 545 | myFile.write(" setAttr -s " + totalFrames + " \".ktv[1:" + totalFrames + "]\""); 546 | 547 | for (var i=1;i<=totalFrames;i++) { 548 | f=(i-1)*frameDuration; 549 | aeZoom = theComp.layer(2).zoom.valueAtTime(f, false); 550 | HFOV=Math.atan( (compWidth*aspect*0.5) /aeZoom);//half the FOV, in radians 551 | fLength=( (mayaFilmBack*0.5) / Math.tan(HFOV) ) * 25.4; //in inches, converted to mm 552 | myFile.write(" " + i + " " + fLength); 553 | } 554 | 555 | myFile.write(";"); 556 | myFile.writeln(""); 557 | myFile.writeln(""); 558 | 559 | // Render size settings 560 | myFile.writeln("select -ne :time1;"); 561 | myFile.writeln(" setAttr \".o\" 1;"); 562 | myFile.writeln("select -ne :defaultResolution;"); 563 | myFile.writeln(" setAttr \".w\" " + compWidth + ";"); 564 | myFile.writeln(" setAttr \".h\" " + compHeight + ";"); 565 | myFile.writeln(" setAttr \".dar\" " + frameAspect + ";"); 566 | myFile.writeln(""); 567 | 568 | // connect the nodes together 569 | myFile.writeln("connectAttr \"" + CamName + "_TranslateX.o\" \"" + CamName + ".tx\";"); 570 | myFile.writeln("connectAttr \"" + CamName + "_TranslateY.o\" \"" + CamName + ".ty\";"); 571 | myFile.writeln("connectAttr \"" + CamName + "_TranslateZ.o\" \"" + CamName + ".tz\";"); 572 | myFile.writeln(""); 573 | myFile.writeln("connectAttr \"" + CamName + "_RotateX.o\" \"" + CamName + ".rx\";"); 574 | myFile.writeln("connectAttr \"" + CamName + "_RotateY.o\" \"" + CamName + ".ry\";"); 575 | myFile.writeln("connectAttr \"" + CamName + "_RotateZ.o\" \"" + CamName + ".rz\";"); 576 | myFile.writeln(""); 577 | myFile.writeln("connectAttr \"" + CamName + "Shape_FocalLength.o\"\"" + CamName + "Shape.fl\";"); 578 | myFile.writeln(""); 579 | 580 | 581 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 582 | // modifications by Nick Fox-Gieg 583 | var allLayers = theComp.layers; 584 | for (var i=1; i < allLayers.length; i++) { 585 | var curLayer = allLayers[i]; 586 | var curLayerName = curLayer.name.replace(/[^a-zA-Z0-9]+/g,""); 587 | if (curLayer.matchName != "ADBE Camera Layer" && curLayerName != CamName + "Parent") { 588 | //alert(curLayerName); 589 | 590 | var pos = curLayer.property("Position").valueAtTime(0,false); 591 | var Xpos=(pos[0]-worldCenter[0])/worldScale; 592 | var Ypos=-((pos[1]-worldCenter[1])/worldScale); 593 | var Zpos=-(pos[2]/worldScale); 594 | 595 | /* 596 | var Xrot=curLayer.rotationX.valueAtTime(0, false); 597 | var Yrot=curLayer.orientation.valueAtTime(0, false); 598 | var Zrot=curLayer.rotationZ.valueAtTime(0, false); 599 | 600 | var scale=curLayer.scale.valueAtTime(0, false); 601 | var Xscale=scale[0]/100; 602 | var Yscale=scale[1]/100; 603 | var Zscale=scale[2]/100; 604 | */ 605 | 606 | myFile.writeln("createNode transform -n \"" + curLayerName +"\";"); 607 | myFile.writeln("setAttr \".t\" -type \"double3\" " + Xpos + " " + Ypos + " " + Zpos + " ;"); 608 | myFile.writeln("setAttr -av \".tx\";"); 609 | myFile.writeln("setAttr -av \".ty\";"); 610 | myFile.writeln("setAttr -av \".tz\";"); 611 | myFile.writeln(""); 612 | 613 | /* 614 | myFile.writeln("setAttr \".r\" -type \"double3\" " + Xrot + " " + Yrot + " " + Zrot + " ;"); 615 | myFile.writeln("setAttr -av \".rx\";"); 616 | myFile.writeln("setAttr -av \".ry\";"); 617 | myFile.writeln("setAttr -av \".rz\";"); 618 | myFile.writeln(""); 619 | 620 | myFile.writeln("setAttr \".s\" -type \"double3\" " + Xscale + " " + Yscale + " " + Zscale + " ;"); 621 | myFile.writeln("setAttr -av \".sx\";"); 622 | myFile.writeln("setAttr -av \".sy\";"); 623 | myFile.writeln("setAttr -av \".sz\";"); 624 | myFile.writeln(""); 625 | */ 626 | 627 | myFile.writeln("createNode locator -n \"locatorShape"+ i +"\" -p \"" + curLayerName +"\";"); 628 | myFile.writeln("setAttr -k off \".v\";"); 629 | 630 | myFile.writeln(""); 631 | myFile.writeln("connectAttr \"" + curLayerName + "_visibility.o\" \"" + curLayerName + ".v\";"); 632 | myFile.writeln(""); 633 | 634 | //1-3 TRANSLATE 635 | // X position 636 | myFile.writeln("createNode animCurveTL -n \"" + curLayerName + "_TranslateX\";"); 637 | myFile.writeln(" setAttr \".tan\" 9;"); 638 | myFile.writeln(" setAttr \".wgt\" no;"); 639 | myFile.write(" setAttr -s " + totalFrames + " \".ktv[1:" + totalFrames + "]\""); 640 | 641 | var counter = 1; // why does this only work with a while loop? 642 | while (counter <= totalFrames) { 643 | var f=(counter-1)*frameDuration; 644 | var pos=curLayer.position.valueAtTime(f, false); 645 | var Xpos=(pos[0]-worldCenter[0])/worldScale; 646 | myFile.write(" " + counter + " " + Xpos); 647 | counter++; 648 | } 649 | 650 | myFile.write(";"); 651 | myFile.writeln(""); 652 | myFile.writeln(""); 653 | 654 | // Y position 655 | myFile.writeln("createNode animCurveTL -n \"" + curLayerName + "_TranslateY\";") 656 | myFile.writeln(" setAttr \".tan\" 9;"); 657 | myFile.writeln(" setAttr \".wgt\" no;"); 658 | myFile.write(" setAttr -s " + totalFrames + " \".ktv[1:" + totalFrames + "]\""); 659 | 660 | var counter = 1; // why does this only work with a while loop? 661 | while (counter <= totalFrames) { 662 | var f=(counter-1)*frameDuration; 663 | var pos=curLayer.position.valueAtTime(f, false); 664 | var Ypos=-((pos[1]-worldCenter[1])/worldScale); 665 | myFile.write(" " + counter + " " + Ypos); 666 | counter++; 667 | } 668 | 669 | myFile.write(";"); 670 | myFile.writeln(""); 671 | myFile.writeln(""); 672 | 673 | // Z position 674 | myFile.writeln("createNode animCurveTL -n \"" + curLayerName + "_TranslateZ\";"); 675 | myFile.writeln(" setAttr \".tan\" 9;"); 676 | myFile.writeln(" setAttr \".wgt\" no;"); 677 | myFile.write(" setAttr -s " + totalFrames + " \".ktv[1:" + totalFrames + "]\""); 678 | 679 | var counter = 1; // why does this only work with a while loop? 680 | while (counter <= totalFrames) { 681 | var f=(counter-1)*frameDuration; 682 | var pos=curLayer.position.valueAtTime(f, false); 683 | var Zpos=-(pos[2]/worldScale); 684 | myFile.write(" " + counter + " " + Zpos); 685 | counter++; 686 | } 687 | 688 | myFile.write(";"); 689 | myFile.writeln(""); 690 | myFile.writeln(""); 691 | 692 | myFile.writeln("connectAttr \"" + curLayerName + "_TranslateX.o\" \"" + curLayerName + ".tx\";"); 693 | myFile.writeln("connectAttr \"" + curLayerName + "_TranslateY.o\" \"" + curLayerName + ".ty\";"); 694 | myFile.writeln("connectAttr \"" + curLayerName + "_TranslateZ.o\" \"" + curLayerName + ".tz\";"); 695 | 696 | myFile.writeln(""); 697 | 698 | /* 699 | //2-3 ROTATION 700 | // X rotation 701 | myFile.writeln("createNode animCurveTL -n \"" + curLayerName + "_RotateX\";"); 702 | myFile.writeln(" setAttr \".tan\" 9;"); 703 | myFile.writeln(" setAttr \".wgt\" no;"); 704 | myFile.write(" setAttr -s " + totalFrames + " \".ktv[1:" + totalFrames + "]\""); 705 | 706 | var counter = 1; // why does this only work with a while loop? 707 | while (counter <= totalFrames) { 708 | var f=(counter-1)*frameDuration; 709 | var Xrot=curLayer.rotationX.valueAtTime(f, false); 710 | myFile.write(" " + counter + " " + Xrot); 711 | counter++; 712 | } 713 | 714 | myFile.write(";"); 715 | myFile.writeln(""); 716 | myFile.writeln(""); 717 | 718 | // Y rotation 719 | myFile.writeln("createNode animCurveTL -n \"" + curLayerName + "_RotateY\";") 720 | myFile.writeln(" setAttr \".tan\" 9;"); 721 | myFile.writeln(" setAttr \".wgt\" no;"); 722 | myFile.write(" setAttr -s " + totalFrames + " \".ktv[1:" + totalFrames + "]\""); 723 | 724 | var counter = 1; // why does this only work with a while loop? 725 | while (counter <= totalFrames) { 726 | var f=(counter-1)*frameDuration; 727 | var Yrot=curLayer.orientation.valueAtTime(f, false); 728 | myFile.write(" " + counter + " " + Yrot); 729 | counter++; 730 | } 731 | 732 | myFile.write(";"); 733 | myFile.writeln(""); 734 | myFile.writeln(""); 735 | 736 | // Z rotation 737 | myFile.writeln("createNode animCurveTL -n \"" + curLayerName + "_RotateZ\";"); 738 | myFile.writeln(" setAttr \".tan\" 9;"); 739 | myFile.writeln(" setAttr \".wgt\" no;"); 740 | myFile.write(" setAttr -s " + totalFrames + " \".ktv[1:" + totalFrames + "]\""); 741 | 742 | var counter = 1; // why does this only work with a while loop? 743 | while (counter <= totalFrames) { 744 | var f=(counter-1)*frameDuration; 745 | var Zrot=curLayer.rotationZ.valueAtTime(f, false); 746 | myFile.write(" " + counter + " " + Zrot); 747 | counter++; 748 | } 749 | 750 | myFile.write(";"); 751 | myFile.writeln(""); 752 | myFile.writeln(""); 753 | 754 | myFile.writeln("connectAttr \"" + curLayerName + "_rotateX.o\" \"" + curLayerName + ".rx\";"); 755 | myFile.writeln("connectAttr \"" + curLayerName + "_rotateY.o\" \"" + curLayerName + ".ry\";"); 756 | myFile.writeln("connectAttr \"" + curLayerName + "_rotateZ.o\" \"" + curLayerName + ".rz\";"); 757 | 758 | myFile.writeln(""); 759 | 760 | //3-3 SCALE 761 | // X scale 762 | myFile.writeln("createNode animCurveTL -n \"" + curLayerName + "_ScaleX\";"); 763 | myFile.writeln(" setAttr \".tan\" 9;"); 764 | myFile.writeln(" setAttr \".wgt\" no;"); 765 | myFile.write(" setAttr -s " + totalFrames + " \".ktv[1:" + totalFrames + "]\""); 766 | 767 | var counter = 1; // why does this only work with a while loop? 768 | while (counter <= totalFrames) { 769 | var f=(counter-1)*frameDuration; 770 | var scale=curLayer.scale.valueAtTime(f, false); 771 | var Xscale=scale[0]/100; 772 | myFile.write(" " + counter + " " + Xscale); 773 | counter++; 774 | } 775 | 776 | myFile.write(";"); 777 | myFile.writeln(""); 778 | myFile.writeln(""); 779 | 780 | // Y scale 781 | myFile.writeln("createNode animCurveTL -n \"" + curLayerName + "_ScaleY\";") 782 | myFile.writeln(" setAttr \".tan\" 9;"); 783 | myFile.writeln(" setAttr \".wgt\" no;"); 784 | myFile.write(" setAttr -s " + totalFrames + " \".ktv[1:" + totalFrames + "]\""); 785 | 786 | var counter = 1; // why does this only work with a while loop? 787 | while (counter <= totalFrames) { 788 | var f=(counter-1)*frameDuration; 789 | var scale=curLayer.scale.valueAtTime(f, false); 790 | var Yscale=scale[1]/100; 791 | myFile.write(" " + counter + " " + Yscale); 792 | counter++; 793 | } 794 | 795 | myFile.write(";"); 796 | myFile.writeln(""); 797 | myFile.writeln(""); 798 | 799 | // Z scale 800 | myFile.writeln("createNode animCurveTL -n \"" + curLayerName + "_ScaleZ\";"); 801 | myFile.writeln(" setAttr \".tan\" 9;"); 802 | myFile.writeln(" setAttr \".wgt\" no;"); 803 | myFile.write(" setAttr -s " + totalFrames + " \".ktv[1:" + totalFrames + "]\""); 804 | 805 | var counter = 1; // why does this only work with a while loop? 806 | while (counter <= totalFrames) { 807 | var f=(counter-1)*frameDuration; 808 | var scale=curLayer.scale.valueAtTime(f, false); 809 | var Zscale=scale[2]/100; 810 | myFile.write(" " + counter + " " + Zscale); 811 | counter++; 812 | } 813 | 814 | myFile.write(";"); 815 | myFile.writeln(""); 816 | myFile.writeln(""); 817 | 818 | myFile.writeln("connectAttr \"" + curLayerName + "_scaleX.o\" \"" + curLayerName + ".sx\";"); 819 | myFile.writeln("connectAttr \"" + curLayerName + "_scaleY.o\" \"" + curLayerName + ".sy\";"); 820 | myFile.writeln("connectAttr \"" + curLayerName + "_scaleZ.o\" \"" + curLayerName + ".sz\";"); 821 | 822 | myFile.writeln(""); 823 | */ 824 | } 825 | } 826 | 827 | 828 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 829 | // finish it all up... 830 | 831 | // set work area 832 | myFile.writeln("createNode script -n \"sceneConfigurationScriptNode\";"); 833 | myFile.writeln(" setAttr \".b\" -type \"string\"\"playbackOptions -min 1.0 -max " + totalFrames + " -ast 1.0 -aet " + totalFrames + "\";"); 834 | myFile.writeln(" setAttr \".st\" 6;"); 835 | myFile.writeln(""); 836 | myFile.writeln("//End of " + CamName + ".ma"); 837 | 838 | myFile.close(); 839 | 840 | //erase baked camera and its parent 841 | theComp.layer(2).remove(); 842 | theComp.layer(1).remove(); 843 | 844 | app.endUndoGroup(); 845 | } 846 | 847 | /////////////////////////////////////////////////////////////////////////////////////////// 848 | /////////////////////////////////////////////////////////////////////////////////////////// 849 | -------------------------------------------------------------------------------- /build/aetoolbox_guide.js: -------------------------------------------------------------------------------- 1 | // Notes: apply process to any number of layers 2 | function skeleView(doUndoGroup) { 3 | if (doUndoGroup || doUndoGroup==undefined) app.beginUndoGroup("Skeleton View"); 4 | 5 | var theComp = app.project.activeItem; 6 | 7 | if (theComp == null || !(theComp instanceof CompItem)) { 8 | alert(errorNoCompSelected); 9 | } else { 10 | var theLayers = theComp.selectedLayers; 11 | var allLayers = theComp.layers; 12 | 13 | if (theLayers.length==0) { 14 | alert(errorNoLayerSelected); 15 | } else { 16 | var solid = theComp.layers.addSolid([0, 1.0, 1.0], "Skeleton View", theComp.width, theComp.height, 1); 17 | solid.guideLayer = true; 18 | var slider = solid.property("Effects").addProperty("Slider Control"); 19 | slider.name = "Thickness"; 20 | slider.property("Slider").setValue(8); 21 | 22 | var color = solid.property("Effects").addProperty("Color Control"); 23 | color.property("Color").setValue([0,1,0]); 24 | 25 | var firstRun = true; 26 | 27 | for (var i = 0; i < theLayers.length; i++) { 28 | var curLayer = theLayers[i]; 29 | if (curLayer.parent != null) { 30 | var beam = solid.property("Effects").addProperty("Beam"); 31 | if (firstRun) { 32 | beam.property("Composite On Original").setValue(0); 33 | firstRun = false; 34 | } else { 35 | beam.property("Composite On Original").setValue(1); 36 | } 37 | beam.property("Length").setValue(1.0); 38 | beam.property("Softness").setValue(0.0); 39 | beam.property("Starting Thickness").expression = "effect(\"Thickness\")(\"Slider\");"; 40 | beam.property("Ending Thickness").expression = "effect(\"Thickness\")(\"Slider\");"; 41 | beam.property("Inside Color").expression = "effect(\"Color Control\")(\"Color\");"; 42 | beam.property("Outside Color").expression = "effect(\"Color Control\")(\"Color\");"; 43 | 44 | var expr1 = "fromComp(thisComp.layer(\"" + curLayer.name + "\").toComp(thisComp.layer(\"" + curLayer.name + "\").anchorPoint));"; 45 | beam.property("Starting Point").expression = expr1; 46 | 47 | var expr2 = "fromComp(thisComp.layer(\"" + curLayer.parent.name + "\").toComp(thisComp.layer(\"" + curLayer.parent.name + "\").anchorPoint));"; 48 | beam.property("Ending Point").expression = expr2; 49 | } 50 | } 51 | } 52 | } 53 | solid.locked = true; 54 | 55 | if (doUndoGroup || doUndoGroup==undefined) app.endUndoGroup(); 56 | } 57 | 58 | /////////////////////////////////////////////////////////////////////////////////////////// 59 | 60 | // Notes: One-shot--create an adjustment layer with controllable onion skinning 61 | function onionSkin() { 62 | app.beginUndoGroup("Create Onion Skin Layer"); 63 | 64 | var theComp = app.project.activeItem; 65 | 66 | if (theComp == null || !(theComp instanceof CompItem)) { 67 | alert(errorNoCompSelected); 68 | } else { 69 | var solid = theComp.layers.addSolid([0, 1.0, 1.0], "Onion Skinning", theComp.width, theComp.height, 1); 70 | solid.adjustmentLayer = true; 71 | solid.guideLayer = true; 72 | 73 | var echo = solid.property("Effects").addProperty("Echo"); 74 | var slider = solid.property("Effects").addProperty("Slider Control"); 75 | slider.name = "Number of Frames"; 76 | slider.property("Slider").setValue(1); 77 | 78 | var prop1 = solid.effect("Echo")("Echo Time (seconds)"); 79 | var prop2 = solid.effect("Echo")("Number Of Echoes"); 80 | var prop3 = solid.effect("Echo")("Starting Intensity"); 81 | var prop4 = solid.effect("Echo")("Decay"); 82 | var prop5 = solid.effect("Echo")("Echo Operator"); 83 | 84 | prop1.expression = "var s = effect(\"Number of Frames\")(\"Slider\");" + "\r" + 85 | "var d = thisComp.frameDuration;" + "\r" + 86 | "var rd;" + "\r" + 87 | "if (s >= 0) {" + "\r" + 88 | " rd = -d;" + "\r" + 89 | "} else if (s < 0) {" + "\r" + 90 | " rd = d;" + "\r" + 91 | "}"; 92 | 93 | prop2.expression = "var s = effect(\"Number of Frames\")(\"Slider\");" + "\r" + 94 | "var rs;" + "\r" + 95 | "if (s > 0) {" + "\r" + 96 | " rs = s;" + "\r" + 97 | "} else if (s == 0) {" + "\r" + 98 | " rs = 0;" + "\r" + 99 | "} else if (s < 0) {" + "\r" + 100 | " rs = -s;" + "\r" + 101 | "}" + "\r" + 102 | "rs;"; 103 | prop3.expression = "var val = 0.5;" + "\r" + 104 | "var offset = 0.175;" + "\r" + 105 | "var s = effect(\"Number of Frames\")(\"Slider\");" + "\r" + 106 | "var rtn;" + "\r" + 107 | "if (s < 0) s = -s;" + "\r" + 108 | "if (s != 0) {" + "\r" + 109 | " rtn = val + (offset/s);" + "\r" + 110 | "} else { " + "\r" + 111 | " rtn = 1;" + "\r" + 112 | "}" + "\r" + 113 | "rtn;"; 114 | prop4.setValue(0.5); 115 | prop5.setValue(7); 116 | 117 | solid.locked = true; 118 | } 119 | 120 | app.endUndoGroup(); 121 | } 122 | 123 | /////////////////////////////////////////////////////////////////////////////////////////// 124 | /////////////////////////////////////////////////////////////////////////////////////////// 125 | -------------------------------------------------------------------------------- /build/aetoolbox_image.js: -------------------------------------------------------------------------------- 1 | // Notes: apply process to any number of layers 2 | function softLayeredImage1() { 3 | app.beginUndoGroup("Soften Image 1"); 4 | 5 | var theComp = app.project.activeItem; 6 | 7 | if (theComp === null || !(theComp instanceof CompItem)) { 8 | alert(errorNoCompSelected); 9 | } else { 10 | var theLayers = theComp.selectedLayers; 11 | 12 | if (theLayers.length === 0) { 13 | alert(errorNoLayerSelected); 14 | } else { 15 | for (var i = 0; i < theLayers.length; i++) { 16 | var curLayer = theLayers[i]; 17 | // condition 1: must be a footage layer 18 | if (curLayer.matchName === "ADBE AV Layer") { 19 | var newLayer2 = curLayer.duplicate(); 20 | var newLayer1 = curLayer.duplicate(); 21 | 22 | var effects1 = newLayer1.property("Effects"); 23 | var opacity1 = newLayer1.property("opacity"); 24 | var blur1 = effects1.addProperty("Gaussian Blur"); 25 | 26 | newLayer1.blendingMode = BlendingMode.MULTIPLY; 27 | newLayer1.audioEnabled = false; 28 | blur1.property("Blurriness").setValue(13); 29 | opacity1.setValue(100); 30 | 31 | var effects2 = newLayer2.property("Effects"); 32 | var opacity2 = newLayer2.property("opacity"); 33 | var blur2 = effects2.addProperty("Gaussian Blur"); 34 | 35 | newLayer2.blendingMode = BlendingMode.SCREEN; 36 | newLayer2.audioEnabled = false; 37 | blur2.property("Blurriness").setValue(7); 38 | opacity2.setValue(70); 39 | } else { 40 | alert(errorFootageOnly); 41 | } 42 | } 43 | } 44 | } 45 | 46 | app.endUndoGroup(); 47 | } 48 | 49 | /////////////////////////////////////////////////////////////////////////////////////////// 50 | 51 | // Notes: apply process to any number of layers 52 | function softLayeredImage2() { 53 | app.beginUndoGroup("Soften Image 2"); 54 | 55 | var theComp = app.project.activeItem; 56 | 57 | if (theComp === null || !(theComp instanceof CompItem)) { 58 | alert(errorNoCompSelected); 59 | } else { 60 | var theLayers = theComp.selectedLayers; 61 | 62 | if (theLayers.length === 0) { 63 | alert(errorNoLayerSelected); 64 | } else { 65 | for (var i = 0; i < theLayers.length; i++) { 66 | var curLayer = theLayers[i]; 67 | // condition 1: must be a footage layer 68 | if (curLayer.matchName === "ADBE AV Layer") { 69 | var newLayer2 = curLayer.duplicate(); 70 | var newLayer1 = curLayer.duplicate(); 71 | 72 | var effects1 = newLayer1.property("Effects"); 73 | var opacity1 = newLayer1.property("opacity"); 74 | var blur1 = effects1.addProperty("Gaussian Blur"); 75 | 76 | newLayer1.blendingMode = BlendingMode.MULTIPLY; 77 | newLayer1.audioEnabled = false; 78 | blur1.property("Blurriness").setValue(10); 79 | opacity1.setValue(70); 80 | 81 | var effects2 = newLayer2.property("Effects"); 82 | var opacity2 = newLayer2.property("opacity"); 83 | var blur2 = effects2.addProperty("Gaussian Blur"); 84 | 85 | newLayer2.blendingMode = BlendingMode.SCREEN; 86 | newLayer2.audioEnabled = false; 87 | blur2.property("Blurriness").setValue(7); 88 | opacity2.setValue(50); 89 | } else { 90 | alert(errorFootageOnly); 91 | } 92 | } 93 | } 94 | } 95 | 96 | app.endUndoGroup(); 97 | } 98 | 99 | /////////////////////////////////////////////////////////////////////////////////////////// 100 | 101 | // Notes: apply process to any number of layers 102 | function highPass() { 103 | app.beginUndoGroup("High Pass"); 104 | 105 | var theComp = app.project.activeItem; 106 | 107 | if (theComp === null || !(theComp instanceof CompItem)) { 108 | alert(errorNoCompSelected); 109 | } else { 110 | var theLayers = theComp.selectedLayers; 111 | 112 | if (theLayers.length === 0) { 113 | alert(errorNoLayerSelected); 114 | } else { 115 | for (var i = 0; i < theLayers.length; i++) { 116 | var curLayer = theLayers[i]; 117 | // condition 1: must be a footage layer 118 | if (curLayer.matchName === "ADBE AV Layer") { 119 | var newLayer = curLayer.duplicate(); 120 | var opacity = newLayer.property("opacity"); 121 | newLayer.blendingMode = BlendingMode.OVERLAY; 122 | opacity.setValue(50); 123 | newLayer.audioEnabled = false; 124 | 125 | var effects = newLayer.property("Effects"); 126 | 127 | var monochrome = effects.addProperty("Checkbox Control"); 128 | monochrome.name = "Monochrome On"; 129 | monochrome.property("Checkbox").setValue(true); 130 | 131 | var soften = effects.addProperty("Checkbox Control"); 132 | soften.name = "Soften On"; 133 | soften.property("Checkbox").setValue(true); 134 | 135 | var radius = effects.addProperty("Slider Control"); 136 | radius.name = "Radius"; 137 | radius.property("Slider").setValue(38); 138 | 139 | var invert1 = effects.addProperty("Invert"); 140 | var transform = effects.addProperty("Transform"); 141 | transform.property("Opacity").setValue(50); 142 | transform.property("Sampling").setValue(1); 143 | 144 | var blur = effects.addProperty("Gaussian Blur"); 145 | var blurExpr = "effect(\"Radius\")(\"Slider\")"; 146 | blur.property("Blurriness").expression = blurExpr; 147 | blur.property("Repeat Edge Pixels").setValue(true); 148 | 149 | var composite = effects.addProperty("CC Composite"); 150 | composite.property("Composite Original").setValue(2); 151 | composite.property("RGB Only").setValue(false); 152 | 153 | var tint = effects.addProperty("Tint"); 154 | var tintExpr = "effect(\"Monochrome On\")(\"Checkbox\")*100"; 155 | tint.property("Amount to Tint").expression = tintExpr; 156 | 157 | var levels = effects.addProperty("Levels"); 158 | levels.property("Input Black").setValue(0.249); 159 | levels.property("Input White").setValue(0.751); 160 | 161 | var invert2 = effects.addProperty("Invert"); 162 | var invert2Expr = "Math.abs((effect(\"Soften On\")(\"Checkbox\")*100)-100)"; 163 | invert2.property("Blend With Original").expression = invert2Expr; 164 | } else { 165 | alert(errorFootageOnly); 166 | } 167 | } 168 | } 169 | } 170 | 171 | app.endUndoGroup(); 172 | } 173 | 174 | /////////////////////////////////////////////////////////////////////////////////////////// 175 | /////////////////////////////////////////////////////////////////////////////////////////// 176 | -------------------------------------------------------------------------------- /build/aetoolbox_import.js: -------------------------------------------------------------------------------- 1 | // Notes: apply process to any number of layers. 2 | function gmlToPos() { 3 | app.beginUndoGroup("GML to Position"); 4 | 5 | var theComp = app.project.activeItem; 6 | 7 | if (theComp == null || !(theComp instanceof CompItem)) { 8 | alert(errorNoCompSelected); 9 | } else { 10 | var xmlFile = File.openDialog(); 11 | var file = xmlFile.open("r"); 12 | var xmlRoot; 13 | if (file) { 14 | var xmlString = xmlFile.read(); 15 | xmlRoot = new XML(xmlString); 16 | xmlFile.close(); 17 | } 18 | 19 | if (xmlRoot) { 20 | tag = xmlRoot.descendants("tag"); 21 | var header = tag.descendants("header"); 22 | var environment = header.descendants("environment"); 23 | var screenBounds = environment.descendants("screenBounds"); 24 | var dim = [ parseFloat(screenBounds.descendants("x")), parseFloat(screenBounds.descendants("y")), parseFloat(screenBounds.descendants("z")) ]; 25 | if (!dim[0]) dim[0] = 640.0; 26 | if (!dim[1]) dim[1] = 640.0; 27 | if (!dim[2]) dim[2] = 640.0; 28 | 29 | var gml = theComp.layers.addSolid([0, 0, 0], "GML", parseInt(dim[0]), parseInt(dim[1]), 1); 30 | gml.guideLayer = true; 31 | gml.threeDLayer = true; 32 | 33 | var drawing = tag.descendants("drawing"); 34 | var strokesEl = drawing.stroke; 35 | for (var i=0; i= 10.5) { 66 | var myComp = app.project.activeItem; 67 | var fileType="xml"; 68 | var myRoot; 69 | 70 | //load xml or json file 71 | var myFile = File.openDialog(); 72 | var fileOK = myFile.open("r"); 73 | if (fileOK) { 74 | var myFileString = myFile.read(); 75 | if (myFile.name.split(".").pop()=="xml") { 76 | fileType="xml"; 77 | myRoot = new XML(myFileString); 78 | } else if (myFile.name.split(".").pop()=="json") { 79 | fileType="json"; 80 | myRoot = eval("(" + myFileString + ")"); 81 | } 82 | myFile.close(); 83 | } 84 | 85 | if (fileType=="xml") { 86 | //~~~~~~~~~~~~~~~~~begin 3D XML version 87 | var compRate = parseFloat(myRoot.@fps); // comp frame rate 88 | 89 | var sW = parseFloat(myRoot.@width); 90 | var sH = parseFloat(myRoot.@height); 91 | var sD = parseFloat(myRoot.@depth); 92 | 93 | var mocap = myComp.layer("mocap"); 94 | 95 | var trackPoint = jointNamesMaster; 96 | 97 | // add joint information 98 | for (var j=0; j 6) { 13 | alert("Select 1-6 layers."); 14 | } else { 15 | for (var i=0; isMax) ss = sMax;" + "\r" + 418 | "ss;"; 419 | beam.property("Starting Thickness").expression = expr3; 420 | 421 | var expr4 = "var L = \"beam_end\";" + "\r" + 422 | "var s = thisComp.layer(\"Beam Solid\").effect(\"Base Size\")(\"Slider\");" + "\r" + 423 | "var sMax = thisComp.layer(\"Beam Solid\").effect(\"Max Size\")(\"Slider\");" + "\r" + 424 | "var sMin = thisComp.layer(\"Beam Solid\").effect(\"Min Size\")(\"Slider\");" + "\r" + 425 | "var p = thisComp.layer(L).transform.position;" + "\r" + 426 | "var ss = s + (-p[2]);" + "\r" + 427 | "if(sssMax) ss = sMax;" + "\r" + 429 | "ss;"; 430 | beam.property("Ending Thickness").expression = expr4; 431 | } else { 432 | var expr3 = "random(effect(\"Randomize\")(\"Slider\"));"; 433 | beam.property("Conductivity State").expression = expr3; 434 | } 435 | } 436 | 437 | app.endUndoGroup(); 438 | } 439 | 440 | /////////////////////////////////////////////////////////////////////////////////////////// 441 | 442 | // Notes: process for any number of layers or properties 443 | function charSnake() { 444 | app.beginUndoGroup("Snake Rig"); 445 | 446 | var theComp = app.project.activeItem; 447 | 448 | if (theComp == null || !(theComp instanceof CompItem)) { 449 | alert(errorNoCompSelected); 450 | } else { 451 | var theLayers = theComp.selectedLayers; 452 | if (theLayers.length==0) { 453 | alert(errorNoLayerSelected); 454 | } else { 455 | for (var i = 0; i < theLayers.length; i++) { 456 | var curLayer = theLayers[i]; 457 | // condition 1: must be a footage layer 458 | if (curLayer.matchName == "ADBE AV Layer") { 459 | //condition 2: must be a 2D layer 460 | if (!curLayer.threeDLayer) { 461 | //condition 3: must have puppet pins applied 462 | if(curLayer.effect.puppet != null) { 463 | var wherePins = curLayer.property("Effects").property("Puppet").property("arap").property("Mesh").property("Mesh 1").property("Deform"); 464 | var pinCount = wherePins.numProperties; 465 | 466 | var solid = theComp.layers.addNull(); 467 | solid.name = "head_ctl"; 468 | var speedSlider = solid.property("Effects").addProperty("Slider Control"); 469 | speedSlider.name = "speed"; 470 | speedSlider.property("Slider").setValue(10); 471 | 472 | for (var n = 1; n <= pinCount; n++) { 473 | var pin = curLayer.effect("Puppet").arap.mesh("Mesh 1").deform(n); 474 | 475 | if(pin.name=="head" || pin.name=="Puppet Pin 1") { 476 | if(pin.name=="Puppet Pin 1") pin.name="head"; 477 | //~~~~~ 478 | //scaled from layer coords to world coords 479 | var p = pin.position.value; 480 | solid.property("position").setValue(harvestPoint(p, curLayer, solid, "toComp")); 481 | //~~~~~~ 482 | var pinExpr = "fromComp(thisComp.layer(\""+solid.name+"\").toComp(thisComp.layer(\""+solid.name+"\").anchorPoint));"; 483 | pin.position.expression = pinExpr; 484 | } 485 | } 486 | 487 | for (var o = 1; o <= pinCount; o++) { 488 | // Get position of puppet pin 489 | var pin = curLayer.effect("Puppet").arap.mesh("Mesh 1").deform(o); 490 | //var solid = theComp.layers.addSolid([1.0, 1.0, 0], nullName, 50, 50, 1); 491 | if(pin.name=="head" || pin.name=="Puppet Pin 1") { 492 | // 493 | } else { 494 | var pinExpr = "var delayFrames = thisComp.layer(\"head_ctl\").effect(\"speed\")(\"Slider\");" + "\r" + 495 | "var p = effect(\"Puppet\").arap.mesh(\"Mesh 1\").deform(\"head\").position;" + "\r" + 496 | "var idx = parseInt(thisProperty.propertyGroup(1).name.split(\" \")[2],10)-1;" + "\r" + 497 | "var delay = idx * framesToTime(delayFrames);" + "\r" + 498 | "p.valueAtTime(time-delay)"; 499 | 500 | pin.position.expression = pinExpr; 501 | } 502 | } 503 | 504 | try { 505 | curLayer.property("Effects").property("Puppet").property("On Transparent").setValue(1); 506 | curLayer.locked = true; 507 | } catch (e) {} 508 | } else { 509 | alert("Only works on layers with puppet pins."); 510 | } 511 | } else { 512 | alert("Only works properly on 2D layers."); 513 | } 514 | } else { 515 | alert(errorFootageOnly); 516 | } 517 | } 518 | } 519 | } 520 | 521 | app.endUndoGroup(); 522 | } 523 | 524 | /////////////////////////////////////////////////////////////////////////////////////////// 525 | /////////////////////////////////////////////////////////////////////////////////////////// 526 | -------------------------------------------------------------------------------- /build/aetoolbox_stereo.js: -------------------------------------------------------------------------------- 1 | // Notes: apply process to any number of layers 2 | function doRgbToGray() { 3 | app.beginUndoGroup("Convert between rgb depth maps and grayscale"); 4 | 5 | var theComp = app.project.activeItem; 6 | 7 | if (theComp == null || !(theComp instanceof CompItem)) { 8 | alert(errorNoCompSelected); 9 | } else { 10 | var theLayers = theComp.selectedLayers; 11 | var doReverse = confirm("Reverse (RGB to Gray)?"); 12 | if (theLayers.length==0) { 13 | alert(errorNoLayerSelected); 14 | } else { 15 | for (var i=0; i 1 || theCamera[0].zoom == null) { 46 | alert(errorOneCameraOnly); 47 | } else { 48 | var solid = theComp.layers.addNull(); 49 | solid.name = getUniqueName("stereo_controller"); 50 | solid.moveToBeginning(); 51 | solid.enabled = false; 52 | 53 | var offsetSlider = solid.property("Effects").addProperty("Slider Control"); 54 | offsetSlider.name = "offset"; 55 | 56 | var expr1 = "var x = transform.pointOfInterest[0];" + "\r" + 57 | "var y = transform.pointOfInterest[1];" + "\r" + 58 | "var z = transform.pointOfInterest[2];" + "\r" + 59 | "x += thisComp.layer(\"" + solid.name + "\").effect(\"" + offsetSlider.name + "\")(\"Slider\");" + "\r" + 60 | "[x, y, z];"; 61 | theCamera[0].property("Point of Interest").expression = expr1; 62 | 63 | var expr2 = "var x = transform.position[0];" + "\r" + 64 | "var y = transform.position[1];" + "\r" + 65 | "var z = transform.position[2];" + "\r" + 66 | "x += thisComp.layer(\"" + solid.name + "\").effect(\"" + offsetSlider.name + "\")(\"Slider\");" + "\r" + 67 | "[x, y, z];"; 68 | theCamera[0].property("Position").expression = expr2; 69 | 70 | theCamera[0].locked = true; 71 | 72 | //theComp.name += "_L"; 73 | //var newComp = theComp.duplicate(); 74 | //newComp.name += "_R"; 75 | } 76 | } 77 | } 78 | 79 | app.endUndoGroup(); 80 | } 81 | 82 | /////////////////////////////////////////////////////////////////////////////////////////// 83 | 84 | // Notes: apply process to any number of layers 85 | function depthFill() { 86 | app.beginUndoGroup("Depth Fill"); 87 | 88 | var theComp = app.project.activeItem; 89 | 90 | if (theComp == null || !(theComp instanceof CompItem)) { 91 | alert(errorNoCompSelected); 92 | } else { 93 | var theLayers = theComp.selectedLayers; 94 | var allLayers = theComp.layers; 95 | 96 | if (theLayers.length==0) { 97 | alert(errorNoLayerSelected); 98 | } else { 99 | for (var i = 0; i < theLayers.length; i++) { 100 | var curLayer = theLayers[i]; 101 | 102 | if (curLayer.matchName != "ADBE Camera Layer") { 103 | var effect1 = curLayer.property("Effects").addProperty("Slider Control"); 104 | effect1.name = "Depth Offset"; 105 | effect1.property("Slider").setValue(2000); 106 | 107 | var effect2 = curLayer.property("Effects").addProperty("Fill"); 108 | 109 | var scaleexpression = "var s = effect(\"Depth Offset\")(\"Slider\");\r" + 110 | "try {\r" + 111 | " var g1 = (toWorld(anchorPoint) - thisComp.activeCamera.toWorld([0,0,0]));\r" + 112 | " var g2 = thisComp.activeCamera.toWorldVec([0,0,1]);\r" + 113 | " var find = dot(g1,g2);\r" + 114 | " value/(find/s);\r" + 115 | "} catch(err) {\r" + 116 | " value;\r" + 117 | "}"; 118 | effect2.property("Color").expression = scaleexpression; 119 | effect2.property("Color").setValue([1,1,1]); 120 | 121 | } else { 122 | alert("Doesn't work on camera layers."); 123 | } 124 | } 125 | } 126 | } 127 | 128 | app.endUndoGroup(); 129 | } 130 | 131 | /////////////////////////////////////////////////////////////////////////////////////////// 132 | 133 | // Notes: apply process to any number of layers 134 | function depthSort() { 135 | app.beginUndoGroup("Sort by Depth"); 136 | 137 | var theComp = app.project.activeItem; 138 | 139 | if (theComp == null || !(theComp instanceof CompItem)) { 140 | alert(errorNoCompSelected); 141 | } else { 142 | var theLayers = theComp.selectedLayers; 143 | var cz; 144 | var isCamera = true; 145 | try { 146 | cz = theComp.activeCamera.property("Position").valueAtTime(theComp.time,true); 147 | } catch(err) { 148 | isCamera = false; 149 | } 150 | 151 | if (theLayers.length==0) { 152 | alert(errorNoLayerSelected); 153 | } else { 154 | var minMax = confirm("Sort from min to max depth?"); 155 | if (minMax) { 156 | theLayers.sort(sortByZmin); 157 | } else { 158 | theLayers.sort(sortByZmax); 159 | } 160 | 161 | for (var i = 0; i < theLayers.length; i++) { 162 | theLayers[i].moveToBeginning(); 163 | } 164 | } 165 | } 166 | 167 | app.endUndoGroup(); 168 | } 169 | 170 | /////////////////////////////////////////////////////////////////////////////////////////// 171 | 172 | // Notes: apply process to two layers 173 | function mergeStereoPair(doUndoGroup) { 174 | if (doUndoGroup) app.beginUndoGroup("Merge Stereo pair"); 175 | 176 | var theComp = app.project.activeItem; 177 | 178 | if (theComp == null || !(theComp instanceof CompItem)) { 179 | alert(errorNoCompSelected); 180 | } else { 181 | var theLayers = theComp.selectedLayers; 182 | 183 | if (theLayers.length != 2) { 184 | alert("Select exactly two layers."); 185 | } else { 186 | var overUnder = confirm("Use over-under stereo?"); 187 | 188 | var leftLayer = theLayers[0]; 189 | var rightLayer = theLayers[1]; 190 | 191 | leftLayer.name += " L"; 192 | rightLayer.name += " R"; 193 | 194 | rightLayer.audioEnabled = false; 195 | 196 | var sL = leftLayer.transform.scale.value; 197 | var sR = rightLayer.transform.scale.value; 198 | 199 | if (!overUnder) { 200 | sL[0] = ((theComp.width/2) / leftLayer.width) * 100; 201 | sL[1] = (theComp.height / leftLayer.height) * 100; 202 | sR[0] = ((theComp.width/2) / rightLayer.width) * 100; 203 | sR[1] = (theComp.height / rightLayer.height) * 100; 204 | } else { 205 | sL[0] = (theComp.width / leftLayer.width) * 100; 206 | sL[1] = ((theComp.height/2) / leftLayer.height) * 100; 207 | sR[0] = (theComp.width / rightLayer.width) * 100; 208 | sR[1] = ((theComp.height/2) / rightLayer.height) * 100; 209 | } 210 | 211 | leftLayer.transform.scale.setValue([sL[0],sL[1]]); 212 | rightLayer.transform.scale.setValue([sR[0],sR[1]]); 213 | //leftLayer.transform.scale.setValue([50,100]); 214 | //rightLayer.transform.scale.setValue([50,100]); 215 | 216 | var pL = leftLayer.transform.position.value; 217 | var pR = rightLayer.transform.position.value; 218 | 219 | if (!overUnder) { 220 | pL[0] = theComp.width*0.25; 221 | pL[1] = theComp.height*0.5; 222 | pR[0] = theComp.width*0.75; 223 | pR[1] = theComp.height*0.5; 224 | } else { 225 | pL[0] = theComp.width*0.5; 226 | pL[1] = theComp.height*0.25; 227 | pR[0] = theComp.width*0.5; 228 | pR[1] = theComp.height*0.75; 229 | } 230 | 231 | leftLayer.transform.position.setValue([pL[0],pL[1]]); 232 | rightLayer.transform.position.setValue([pR[0],pR[1]]); 233 | } 234 | } 235 | 236 | if (doUndoGroup) app.endUndoGroup(); 237 | } 238 | 239 | /////////////////////////////////////////////////////////////////////////////////////////// 240 | 241 | // Notes: apply process to a whole comp 242 | function stereoDispMap() { 243 | app.beginUndoGroup("s3D Displacement Map"); 244 | 245 | var ioDistance = 6.0; 246 | var theComp = app.project.activeItem; 247 | 248 | if (theComp == null || !(theComp instanceof CompItem)) { 249 | alert(errorNoCompSelected); 250 | } else { 251 | var theLayers = theComp.selectedLayers; 252 | 253 | if (theLayers.length==0 || theLayers.length > 2) { 254 | alert("Select one or two layers."); 255 | } else { 256 | var overUnder = confirm("Use over-under stereo?"); 257 | 258 | var oldLayer = theLayers[0]; 259 | 260 | //if one layer selected, duplicated that layer and make it a precomp. 261 | //if two layers selected, put the second layer in the precomp. 262 | var newLayer; 263 | if (theLayers.length==1) { 264 | newLayer = oldLayer.duplicate(); 265 | } else if (theLayers.length==2) { 266 | newLayer = theLayers[1]; 267 | } 268 | 269 | var newPrecomp = theComp.layers.precompose([newLayer.index], "Precomp DispMap", true); 270 | newPrecomp.layers[1].property("Effects").addProperty("Levels"); 271 | var fb = newPrecomp.layers[1].property("Effects").addProperty("Gaussian Blur"); 272 | fb.property("Blurriness").setValue(10); 273 | 274 | theComp.layer("Precomp DispMap").enabled = false; 275 | theComp.layer("Precomp DispMap").audioEnabled = false; 276 | oldLayer = oldLayer.duplicate(); //make an extra copy to fill in gaps caused by displacement 277 | oldLayer.audioEnabled = false; //turn off audio on copy 278 | 279 | var effect = oldLayer.property("Effects").addProperty("Displacement Map"); 280 | effect.property("Displacement Map Layer").setValue(effect.property("Displacement Map Layer").value-1); //target 281 | effect.property("Use For Horizontal Displacement").setValue(5); //luma 282 | effect.property("Max Horizontal Displacement").setValue(-ioDistance); //io distance 283 | effect.property("Use For Vertical Displacement").setValue(11); //off 284 | effect.property("Max Vertical Displacement").setValue(0); //off 285 | //effect.property("Edge Behavior").setValue(1); //on 286 | effect.property("Edge Behavior").setValue(0); //off 287 | 288 | var newComp = theComp.duplicate(); 289 | var stereoComp = theComp.duplicate(); 290 | stereoComp.name = theComp.name + " s3D Pair" 291 | newComp.name = theComp.name + " R"; 292 | theComp.name = theComp.name + " L"; 293 | 294 | var targetNum = 0; 295 | for (var i=0; i 0) { 315 | var curLayer = theLayers1[1]; 316 | curLayer.remove(); 317 | } 318 | 319 | var stereoL = theLayers1.add(theComp); 320 | var stereoR = theLayers1.add(newComp); 321 | stereoR.audioEnabled = false; 322 | 323 | if (!overUnder) { 324 | stereoL.transform.scale.setValue([50,100]); 325 | stereoR.transform.scale.setValue([50,100]); 326 | } else { 327 | stereoL.transform.scale.setValue([100,50]); 328 | stereoR.transform.scale.setValue([100,50]); 329 | } 330 | 331 | if (!overUnder) { 332 | stereoL.transform.position.setValue([(stereoComp.width*0.25),(stereoComp.height*0.5)]); 333 | stereoR.transform.position.setValue([(stereoComp.width*0.75),(stereoComp.height*0.5)]); 334 | } else { 335 | stereoL.transform.position.setValue([(stereoComp.width*0.5),(stereoComp.height*0.25)]); 336 | stereoR.transform.position.setValue([(stereoComp.width*0.5),(stereoComp.height*0.75)]); 337 | } 338 | } 339 | } 340 | 341 | app.endUndoGroup(); 342 | } 343 | 344 | /////////////////////////////////////////////////////////////////////////////////////////// 345 | 346 | // Notes: apply process to a whole comp 347 | function splitStereoPair() { 348 | app.beginUndoGroup("Split s3D Pair"); 349 | 350 | var theComp = app.project.activeItem; 351 | 352 | if (theComp == null || !(theComp instanceof CompItem)) { 353 | alert(errorNoCompSelected); 354 | } else { 355 | var overUnder = confirm("Use over-under stereo?"); 356 | 357 | var newComp1 = theComp.duplicate(); 358 | newComp1.name = theComp.name + " L"; 359 | var theLayers1 = newComp1.layers; 360 | 361 | while (theLayers1.length > 0) { 362 | var curLayer = theLayers1[1]; 363 | curLayer.remove(); 364 | } 365 | 366 | var newComp1target = theLayers1.add(theComp); 367 | if (!overUnder) { 368 | newComp1.width = newComp1.width/2; 369 | } else { 370 | newComp1.height = newComp1.height/2; 371 | } 372 | 373 | //~~~~~~~~~~~~~~~~~ 374 | 375 | var newComp2 = theComp.duplicate(); 376 | newComp2.name = theComp.name + " R"; 377 | var theLayers2 = newComp2.layers; 378 | 379 | while (theLayers2.length > 0) { 380 | var curLayer = theLayers2[1]; 381 | curLayer.remove(); 382 | } 383 | 384 | var newComp2target = theLayers2.add(theComp); 385 | 386 | if (!overUnder) { 387 | newComp2.width = newComp2.width/2; 388 | } else { 389 | newComp2.height = newComp2.height/2; 390 | } 391 | 392 | var p2 = newComp2target.transform.position.value; 393 | 394 | if (!overUnder) { 395 | newComp2target.transform.position.setValue([0,p2[1]]); 396 | } else { 397 | newComp2target.transform.position.setValue([p2[0],0]); 398 | } 399 | 400 | theComp.name = "Precomp s3D Pair"; 401 | } 402 | 403 | app.endUndoGroup(); 404 | } 405 | 406 | /////////////////////////////////////////////////////////////////////////////////////////// 407 | 408 | // Notes: apply process to two layers 409 | function stereo360() { 410 | app.beginUndoGroup("Merge Stereo pair"); 411 | 412 | var theComp = app.project.activeItem; 413 | 414 | if (theComp == null || !(theComp instanceof CompItem)) { 415 | alert(errorNoCompSelected); 416 | } else { 417 | var theLayers = theComp.selectedLayers; 418 | 419 | if (theLayers.length != 2) { 420 | alert("Select exactly two layers."); 421 | } else { 422 | theComp.width = 3840; 423 | theComp.height = 2160; 424 | if (theComp.frameRate == 12) { 425 | theComp.frameRate = 24; 426 | } else if (theComp.frameRate == 15) { 427 | theComp.frameRate = 30; 428 | } 429 | 430 | mergeStereoPair(false); 431 | } 432 | } 433 | 434 | app.endUndoGroup(); 435 | } 436 | 437 | /////////////////////////////////////////////////////////////////////////////////////////// 438 | /////////////////////////////////////////////////////////////////////////////////////////// 439 | -------------------------------------------------------------------------------- /build/aetoolbox_util.js: -------------------------------------------------------------------------------- 1 | // COMMON FUNCTIONS 2 | function grayToRgbDepth(comp) { 3 | var dLayerR = comp.layers[1]; 4 | dLayerR.blendingMode = BlendingMode.ADD; 5 | var rEffect1 = dLayerR.property("Effects").addProperty("Tint"); 6 | rEffect1.property("Map White To").setValue([1,0,0,1]); 7 | var rEffect2 = dLayerR.property("Effects").addProperty("Channel Combiner"); 8 | rEffect2.property("Invert").setValue(1); 9 | rEffect2.property("From").setValue(7); // Red 10 | rEffect2.property("To").setValue(6); // Hue 11 | 12 | var dLayerG = dLayerR.duplicate(); 13 | var gEffect1 = dLayerG.property("Effects").property("Tint"); 14 | gEffect1.property("Map White To").setValue([0,1,0,1]); 15 | var gEffect2 = dLayerG.property("Effects").property("Channel Combiner"); 16 | gEffect2.property("From").setValue(8); // Green 17 | 18 | var dLayerB = dLayerR.duplicate(); 19 | var bEffect1 = dLayerB.property("Effects").property("Tint"); 20 | bEffect1.property("Map White To").setValue([0,0,1,1]); 21 | var bEffect2 = dLayerB.property("Effects").property("Channel Combiner"); 22 | bEffect2.property("From").setValue(9); // Blue 23 | } 24 | 25 | function rgbToGrayDepth(comp) { 26 | var dLayerR = comp.layers[1]; 27 | dLayerR.blendingMode = BlendingMode.ADD; 28 | var rEffect = dLayerR.property("Effects").addProperty("Channel Combiner"); 29 | rEffect.property("Invert").setValue(1); 30 | rEffect.property("From").setValue(12); // Hue 31 | rEffect.property("To").setValue(10); // Red only 32 | 33 | var dLayerG = dLayerR.duplicate(); 34 | var gEffect = dLayerG.property("Effects").property("Channel Combiner"); 35 | gEffect.property("To").setValue(11); 36 | 37 | var dLayerB = dLayerR.duplicate(); 38 | var bEffect = dLayerB.property("Effects").property("Channel Combiner"); 39 | bEffect.property("To").setValue(12); 40 | 41 | var solid = comp.layers.addSolid([0, 1.0, 1.0], "Adjustment Layer", comp.width, comp.height, 1); 42 | solid.adjustmentLayer = true; 43 | var sEffect1 = solid.property("Effects").addProperty("Extract"); 44 | sEffect1.property("White Point").setValue(254); 45 | var sEffect2 = solid.property("Effects").addProperty("Simple Choker"); 46 | sEffect2.property("Choke Matte").setValue(1.0); 47 | } 48 | 49 | function degreesToRadians(degree) { 50 | var pi = Math.PI; 51 | var radians = (degree)*(pi/180); 52 | return(radians); 53 | } 54 | 55 | function radiansToDegrees(radian) { 56 | var pi = Math.PI; 57 | var degrees = (radian)*(180/pi); 58 | return(degrees); 59 | } 60 | 61 | function nameExists(name) { 62 | var returns = false; 63 | var theComp = app.project.activeItem; 64 | var allLayers = theComp.layers; 65 | for (var i=1; i < allLayers.length; i++) { 66 | if (allLayers[i].name == name) returns = true; 67 | } 68 | return returns; 69 | } 70 | 71 | function getUniqueName(name) { 72 | // if the name is already unique, return it 73 | if (!nameExists(name)) { 74 | return "" + name; 75 | } else { 76 | // create default variables for newDigit and shortname in case there"s no trailing digit 77 | var newDigit = 1; 78 | var shortname = name; 79 | 80 | // find the trailing digit in the name 81 | var trailingDigit = name.match(/\d+$/); 82 | 83 | if (trailingDigit) { 84 | // increment the last digit 85 | newDigit = parseInt(trailingDigit) + 1; 86 | // use the length of the trailing digit as a reference for how much to trim 87 | shortname = name.replace(/\d+$/,""); 88 | } 89 | 90 | // create the new name 91 | var newName = shortname + newDigit; 92 | 93 | // recursively run through the function until a unique name is reached and returned 94 | return "" + getUniqueName(newName); 95 | //return "" + newName; 96 | } 97 | } 98 | 99 | // allow only names that contain letters and numbers, and do not start with a number 100 | function removeForbiddenCharacters(theName) { 101 | FirstChar=theName.charAt(0); 102 | if (FirstChar>"0" && FirstChar<"9") { theName="Cam" + theName }; 103 | theName=theName.replace(/[^a-zA-Z0-9]+/g,""); // remove special characters and spaces 104 | return(theName); 105 | } 106 | 107 | // Convert Expression to Keyframes (in the work area) 108 | function Bake(theComp, propBeingCopied, propBeingWritten) { 109 | StartBake=theComp.workAreaStart; 110 | EndBake=StartBake+theComp.workAreaDuration; 111 | NextFrame=1/theComp.frameRate; 112 | for (var i=StartBake; i= 1; i--) { 132 | theLayer = theComp.layer(i); 133 | if (theLayer.name == LayerName) { return(i) }; 134 | } 135 | } 136 | 137 | // Deselect everything in the project window 138 | function DeselectProjectWindowItems() { 139 | for (var i = app.project.items.length; i >= 1; i--) { 140 | item = app.project.items[i]; 141 | if (item.selected) { item.selected = false }; 142 | } 143 | } 144 | 145 | function getSelectedItems() { 146 | var returns = []; 147 | for (var i=1; i= 1; i--) { 187 | item = theComp.layer(i); 188 | if (item.selected) { item.selected = false }; 189 | } 190 | } 191 | 192 | function kill(target) { 193 | var items = app.project.items; 194 | 195 | for (var i = items.length; i >= 1; i--) { 196 | if (items[i]==target || items[i].name==target.name || items[i].name==target || items[i]==target.name) { 197 | items[i].remove(); 198 | } 199 | } 200 | } 201 | 202 | function compare(a,b) { 203 | return a > b ? 1 : a < b ? -1 : 0; 204 | } 205 | 206 | function bubbleSort(a,b) { 207 | var swapped; 208 | do { 209 | swapped = false; 210 | for (var i=0; i < a.length-1; i++) { 211 | if (a[i] > a[i+1]) { 212 | var temp = a[i]; 213 | a[i] = a[i+1]; 214 | a[i+1] = temp; 215 | 216 | var temp = b[i]; 217 | b[i] = b[i+1]; 218 | b[i+1] = temp; 219 | swapped = true; 220 | } 221 | } 222 | } while (swapped); 223 | } 224 | 225 | function harvestPoint(inputVal, sourceLayer, destLayer, spaceTransform) { 226 | var outputVal; 227 | if (inputVal.length==2) { 228 | try { 229 | var posCalc = destLayer.property("Effects").addProperty("Point Control")("Point"); 230 | var posCalcExpr = "var p = ["+inputVal[0]+","+inputVal[1]+"];" + "\r" + 231 | "var target = thisComp.layer(\"" + sourceLayer.name + "\");" + "\r"; 232 | if (spaceTransform=="toComp") posCalcExpr += "target.toComp(p);"; 233 | if (spaceTransform=="fromComp") posCalcExpr += "target.fromComp(p);"; 234 | if (spaceTransform=="toWorld") posCalcExpr += "target.toWorld(p);"; 235 | if (spaceTransform=="fromWorld") posCalcExpr += "target.fromWorld(p);"; 236 | posCalc.expression= posCalcExpr; 237 | outputVal = posCalc.value; 238 | destLayer.property("Effects")("Point Control").remove(); 239 | return outputVal; 240 | } catch(err) { 241 | alert("Error harvesting 2D point data.") 242 | } 243 | }else if (inputVal.length==3) { 244 | try { 245 | var posCalc = destLayer.property("Effects").addProperty("3D Point Control")("3D Point"); 246 | var posCalcExpr = "var p = ["+inputVal[0]+","+inputVal[1]+","+inputVal[2]+"];" + "\r" + 247 | "var target = thisComp.layer(\"" + sourceLayer.name + "\");" + "\r"; 248 | if (spaceTransform=="toComp") posCalcExpr += "target.toComp(p);"; 249 | if (spaceTransform=="fromComp") posCalcExpr += "target.fromComp(p);"; 250 | if (spaceTransform=="toWorld") posCalcExpr += "target.toWorld(p);"; 251 | if (spaceTransform=="fromWorld") posCalcExpr += "target.fromWorld(p);"; 252 | posCalc.expression= posCalcExpr; 253 | outputVal = posCalc.value; 254 | destLayer.property("Effects")("3D Point Control").remove(); 255 | return outputVal; 256 | } catch(err) { 257 | alert("Error harvesting 3D point data.") 258 | } 259 | } else { 260 | alert("Requires a 2D or 3D point as input."); 261 | } 262 | } 263 | 264 | function convertToKeyframes(theProperty) { 265 | if (theProperty.canSetExpression && theProperty.expressionEnabled) { 266 | theProperty.selected = true; 267 | app.executeCommand(app.findMenuCommandId("Convert Expression to Keyframes")); 268 | theProperty.selected = false; 269 | } else { 270 | Bake(app.project.activeItem,theProperty,theProperty); 271 | } 272 | } 273 | 274 | function convertAudioToKeyframes(target) { 275 | target.selected = true; 276 | app.executeCommand(app.findMenuCommandId("Convert Audio to Keyframes")); 277 | target.selected = false; 278 | } 279 | 280 | function getDim(layer) { 281 | var time = app.project.activeItem.time; 282 | var x = layer.sourceRectAtTime(t=time, includeExtents=false).width; 283 | var y = layer.sourceRectAtTime(t=time, includeExtents=false).height; 284 | return [ x, y ]; 285 | } 286 | 287 | function sortByZmax(a,b) { 288 | if (a.position.value[2] < b.position.value[2]) { 289 | return -1; 290 | } else if (a.position.value[2] > b.position.value[2]) { 291 | return 1; 292 | } else { 293 | return 0; 294 | } 295 | } 296 | 297 | function sortByZmin(b,a) { 298 | if (a.position.value[2] < b.position.value[2]) { 299 | return -1; 300 | } else if (a.position.value[2] > b.position.value[2]) { 301 | return 1; 302 | } else { 303 | return 0; 304 | } 305 | } 306 | 307 | /////////////////////////////////////////////////////////////////////////////////////////// 308 | /////////////////////////////////////////////////////////////////////////////////////////// 309 | })(this); -------------------------------------------------------------------------------- /build/build.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | cd /d %~dp0 4 | 5 | set BUILD_TARGET=%~dp0..\AEToolbox.jsx 6 | 7 | del %BUILD_TARGET% 8 | 9 | copy /b aetoolbox_main.js+aetoolbox_basic.js+aetoolbox_advanced.js+aetoolbox_rigging.js+aetoolbox_stereo.js+aetoolbox_pip.js+aetoolbox_image.js+aetoolbox_guide.js+aetoolbox_export.js+aetoolbox_import.js+aetoolbox_plugins.js+aetoolbox_util.js %BUILD_TARGET% 10 | 11 | set VERSION=Adobe After Effects 2024 12 | 13 | set DEST="C:\Program Files\Adobe\%VERSION%\Support Files\Scripts\ScriptUI Panels\" 14 | 15 | copy %BUILD_TARGET% %DEST% 16 | 17 | @pause 18 | 19 | rem set VERSION="Adobe After Effects CS6" 20 | rem set VERSION="Adobe After Effects CC" 21 | rem set VERSION="Adobe After Effects CC 2014" 22 | rem set VERSION="Adobe After Effects CC 2015" 23 | rem set VERSION="Adobe After Effects CC 2015.3" 24 | rem set VERSION="Adobe After Effects CC 2017" 25 | rem set VERSION="Adobe After Effects CC 2018" 26 | rem set VERSION="Adobe After Effects CC 2019" 27 | rem set VERSION="Adobe After Effects CC 2020" 28 | rem set VERSION="Adobe After Effects 2021" 29 | rem set VERSION="Adobe After Effects 2022" 30 | -------------------------------------------------------------------------------- /build/build.command: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | BUILD_TARGET="../AEToolbox.jsx" 4 | 5 | SOURCE="${BASH_SOURCE[0]}" 6 | while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink 7 | DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" 8 | SOURCE="$(readlink "$SOURCE")" 9 | [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located 10 | done 11 | DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" 12 | 13 | cd $DIR 14 | 15 | rm $BUILD_TARGET 16 | touch $BUILD_TARGET 17 | 18 | cat "aetoolbox_main.js" "aetoolbox_basic.js" "aetoolbox_advanced.js" "aetoolbox_rigging.js" "aetoolbox_stereo.js" "aetoolbox_pip.js" "aetoolbox_image.js" "aetoolbox_guide.js" "aetoolbox_export.js" "aetoolbox_import.js" "aetoolbox_plugins.js" "aetoolbox_util.js" > $BUILD_TARGET 19 | 20 | VERSION="Adobe After Effects 2024" 21 | 22 | DEST="/Applications/$VERSION/Scripts/ScriptUI Panels/" 23 | 24 | cp $BUILD_TARGET $DEST 25 | 26 | #VERSION="Adobe After Effects CS6" 27 | #VERSION="Adobe After Effects CC" 28 | #VERSION="Adobe After Effects CC 2014" 29 | #VERSION="Adobe After Effects CC 2015" 30 | #VERSION="Adobe After Effects CC 2015.3" 31 | #VERSION="Adobe After Effects CC 2017" 32 | #VERSION="Adobe After Effects CC 2018" 33 | #VERSION="Adobe After Effects CC 2019" 34 | #VERSION="Adobe After Effects CC 2020" 35 | #VERSION="Adobe After Effects 2021" 36 | #VERSION="Adobe After Effects 2022" --------------------------------------------------------------------------------