/* Block Dissolve Experiments Scripting Basics: pulling random values from within a defined range A common scripting requirement is to pull random values from within a defined range. For example, in the block dissolve transition the individual blocks of video are extracted from the video in a random order. As an example, let's revisit our float away video wall script (http://www.creative-workflow-hacks.com/2006/07/09/how-to-make-a-float-away-video-wall-in-after-effects-via-scripting/) and customize it to work in the same manner as a block dissolve but with a little more flair. We will scale the individual blocks up instead of just transitioning on and off. 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 Block Dissolve Grid"); var gridArray = new Array(); var counter = 0; for(x = 0; x < gridWidth; x++){ for(y= 0; y < gridHeight; y++){ gridArray.push(++counter); } } 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); scaleProp = itemToMask.scale; scaleProp.setValueAtTime(0, [0,0]); var random = Math.floor(Math.random() * gridArray.length); var startTime = gridArray.splice(random, 1) * (win.speed.value * .10); var endTime = startTime + (win.speed.value * .10); scaleProp.setValueAtTime(startTime, [0,0]); scaleProp.setValueAtTime(endTime, [100,100]); /* alternate styles scaleProp = itemToMask.scale; scaleProp.setValueAtTime(0, [0,0]); var random = Math.random(gridArray.length); var startTime = gridArray.pop(random) * .2; var endTime = startTime + .2; scaleProp.setValueAtTime(startTime, [0,0]); scaleProp.setValueAtTime(endTime, [100,100]); var startTime = (x + y) * (win.speed.value * .10); var endTime = startTime + (win.speed.value * .10); scaleProp.setValueAtTime(startTime, [0,0]); scaleProp.setValueAtTime(endTime, [100,100]); */ //thanks to Jeff @ http://www.redefinery.com for the ALPHA_ADD itemToMask.blendingMode = BlendingMode.ALPHA_ADD; } } 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 a Block Dissolve effect."; 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], 2, 1, 100); win.speed.value = 2; 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();