/* Float Away Video Wall Script Script Use this script to apply a masked grid to a video or still source, the script applies an expression which makes the masked video "float" to a placed template Null A full demo of the use of this script is available at: http://creative-workflow-hacks.com/2006/07/09/how-to-make-a-float-away-video-wall-in-after-effects-via-scripting/ Copyright 2006 - Dale Bradshaw, dale@creative-workflow-hacks.com http://creative-workflow-hacks.com Free To Distribute, but you must maintain this header if used without alteration, please also include a link to http://creative-workflow-hacks.com if posted on the web If you use parts of this script please include my contact info as attribution (suggested but not required...thanks) v1.0 July 8, 2006 */ function main(){ //calculate units var footageWidth = selectedItemInfo.width; var gridWidth = win.videoGridWidth.value; var widthUnit = footageWidth / gridWidth; var footageHeight = selectedItemInfo.height; var gridHeight = win.videoGridHeight.value; var heightUnit = footageHeight / gridHeight; var speedBase = win.speed.value; app.beginUndoGroup("Apply Float Away Video Wall"); //do we need to add a null? var layers = activeItem.layers; var matchingLayers = new Array(); var layer; for (var i = 1; i <= layers.length; i++) { layer = layers[i]; if (layer.nullLayer){ matchingLayers[matchingLayers.length] = layer; } } if(matchingLayers.length == 0){ var destinationNull = activeItem.layers.addNull(); destinationNull.threeDLayer = true; destinationNull.property("position").setValue([-218, 242, -314]); destinationNull.property("orientation").setValue([11, 278, 158]); }else{ var destinationNull = matchingLayers[matchingLayers.length - 1]; } //make threeDLayer == true if(selectedItemInfo.source.threeDLayer == false) selectedItemInfo.source.threeDLayer = true; for(x = 0; x < gridWidth; x++){ for(y= 0; y < gridHeight; y++){ var itemToMask = selectedItemInfo.source.duplicate(); newMask = itemToMask.Masks.addProperty("Mask"); newMask.inverted = false; myMaskShape = newMask.property("maskShape"); myShape = myMaskShape.value; myShape.closed = true; var tempVertices = new Array(); tempVertices.push([x * widthUnit , y * heightUnit]); tempVertices.push([x * widthUnit + widthUnit , y * heightUnit]); tempVertices.push([x * widthUnit + widthUnit , y * heightUnit + heightUnit]); tempVertices.push([x * widthUnit , y * heightUnit + heightUnit]); myShape.vertices = tempVertices; myMaskShape.setValue(myShape); var randomTime = Math.random() * speedBase; var nullName = destinationNull.name; var positionExpression = 't = timeToFrames(t = time + thisComp.displayStartTime, fps = 1.0 / thisComp.frameDuration, isDuration = false) /' + randomTime + '; position =ease(t, position, thisComp.layer("' + nullName + '").position);'; var orientationExpression = 't = timeToFrames(t = time + thisComp.displayStartTime, fps = 1.0 / thisComp.frameDuration, isDuration = false) /' + randomTime + '; orientation = ease(t, orientation, thisComp.layer("' + nullName + '").orientation);'; itemToMask.position.expression = positionExpression; if(itemToMask.orientation){ itemToMask.orientation.expression = orientationExpression; } } } selectedItemInfo.source.enabled = false; app.endUndoGroup(); } //UI setup //help text function usage(){ var usage = "Use this script to apply a masked grid to a video or still source, the script applies an expression which makes the masked video \"float\" to a placed template Null"; alert(usage); } //UI build function buildUI(){ if (win != null) { win.GridPnl = win.add('panel', [20,25,230,145], 'Video Grid Size:'); win.videoGridWidthText = win.GridPnl.add('statictext', [15,20,105,30], 'Width:'); win.videoGridWidthValuesText = win.GridPnl.add('statictext', [15,35,205,45], '2 10'); win.videoGridWidth = win.GridPnl.add ("slider",[10,48,205,58], 5, 2, 10); win.videoGridWidth.value = 5; win.videoGridHeightText = win.GridPnl.add('statictext', [15,70,105,80], 'Height:'); win.videoGridHeightValuesText = win.GridPnl.add('statictext', [15,85,205,95], '2 10'); win.videoGridHeight = win.GridPnl.add ("slider",[10,98,205,108], 5, 2, 10); win.videoGridHeight.value = 5; win.SpeedPnl = win.add('panel', [20,150,230,195], 'Speed:'); win.speed = win.SpeedPnl.add ("slider",[10,25,205,35], 100, 20, 300); win.speed.value = 100; win.helpBtn = win.add('button', [20,205,50,225], '?', {name:'help'}); win.helpBtn.onClick = usage; win.cancBtn = win.add('button', [105,205,165,225], 'Cancel', {name:'cancel'}); win.cancBtn.onClick = function () {this.parent.close(0)}; win.okBtn = win.add('button', [172,205,230,225], 'OK', {name:'ok'}); win.okBtn.onClick = function () {main();}; } return win } //check that a single FootageItem is selected function checkPrerequisites(){ var selectedCount = 0; var selectAlert = "Please select a single Footage Item in a Comp."; if ((activeItem != null) && (activeItem instanceof CompItem)){ var selectedLayers = activeItem.selectedLayers; }else{ var selectedLayers = ''; } var matchingLayers = new Array(); var layer; for (var i = 0; i < selectedLayers.length; i++) { layer = selectedLayers[i]; if (layer.source instanceof FootageItem){ matchingLayers[matchingLayers.length] = layer; } } if(matchingLayers.length > 1 || matchingLayers.length == 0){ selectedItemInfo.source = ''; selectedItemInfo.width = ''; selectedItemInfo.height = ''; alert(selectAlert); }else{ selectedItemInfo.source = matchingLayers[0]; selectedItemInfo.width = matchingLayers[0].width; selectedItemInfo.height = matchingLayers[0].height; if(w != null){ w.show(); }else{ alert("Couldn't build UI"); } } } //globals var items = app.project.items; var activeItem = app.project.activeItem; var selectedItemInfo = {source:"", width:"", height:""}; var win = new Window('palette', 'Create Float Away Video Wall',[100,100,350,345]); var w = buildUI(); checkPrerequisites();