{ function onCreditsClick() { alert("RotAE rotoscoping script for AE6.5 and 7\n\n"+ "Idea by Alejandro Perez\n"+ "Main code by Juan Corcoles\n"+ "Additional code by Alejandro Perez\n\n\n"+ "Originally based on a script by Dan Ebberts at Creative Cow \n\n\n"+ "Thanks to CreativeCow.net and Aenhancers.com for their support and ideas. \n\n"+"v1.1\n\n"+ "This version fixes a small bug, an unnecesary check that blocked the \n"+ "Apply Tracker command when the first layer in the comp didn't have \n"+ "a mask; it ignored if it was the layer selected to apply the trackers.\n\n"); } function onRotohelpClick() { alert("Create a Mask around a moving object, select it and click on Apply Tracker.\n"+ "A Tracker will appear with as many Track Points as vertices are there in the Mask. \n"+ "Now you can track as you usually do with After Effects.\n"+ "If you want to focus on certain Track Points,\n"+ "just make the others invisible in the timeline as you do with layers.\n\n"+ "When you are done tracking, select the Tracker (not the trackpoints) \n"+ "and the same Mask and click on Apply Mask in the Palette.\n\n"+ "After a while the mask will be animated, each vertex will be placed where each Track Point is.\n\n"+ "Remember that the script animates the Mask along the whole layer, so keep it as small\n"+ "as possible to save time."); } function onInterpolhelpClick() { alert("This bunch of functions will solve little problems you get on big complex masks,\n"+ "not necessarily related to rotoscoping.\n\n"+ "When you have a point that does not fit correctly in several keyframes, you can either\n"+ "correct them manually or use this script.\n\n"+ "The << < > >> buttons will rotate the position of the First Vertex along the mask.\n"+ "DO NOT USE THE SET FIRST VERTEX command in After Effects, as it will only move\n"+ "a single keyframe and can screw everything up. The First Vertex is vissible on screen, \n"+ "as it is bigger than the others, so you can always know if it is in the right place.\n\n"+ "Now you have to add layer markers before and after a vertex goes wrong and the \n"+ "script will interpolate the position between them.\n\n"+ "You can choose between:\n"+ " Interpolate Vertex: It will move smoothly, lineally between the position\n"+ " of the 2 or more layer markers.\n"+ " Interpolate Vertex Rel: The same, but related to the (average) position\n"+ " of the previous and next vertex.\n"+ " Interpolate Tangents: The same for the two tangents of a vertex, always related\n"+ " to its current position.\n" ); alert("Of course, you can use this functions to modify a vertex or tangent at certain points\n"+ "using 3 or more layer markers, not only to correct problems.\n\n"+ "Sorry for the inconvenience of the << < > >> buttons, we haven't found a way to\n"+ "detect which vertex is selected when running a script.\n\n"+ "If you want to apply the Tracker data into the Mask again, Tangent data will not be altered;\n"+ "but remember to put the first vertex back where it originally was or tangets will be placed\n"+ "in the wrong places."); } function TrackToMaskClick() { app.beginUndoGroup("Apply Tracker"); TrackToMask(app.project.activeItem.layers[1],1); app.endUndoGroup(); } function TrackToMask(obj,maskIndex) { // check if(obj==undefined){ alert('Invalid object selected.');return } // if(maskIndex>obj.Masks.numProperties){ // alert('Incorrect mask index specified');return // } //asegurarse de que solo hay una mascara seleccionada var masksGroup = app.project.activeItem.selectedLayers[0]("Masks"); var selectedMasks = new Array(); // Store masks in an array; starts as empty if (masksGroup != null) // Iterate through properties of masksGroup { // Append selected mask to the array for (var i = 1; i <= masksGroup.numProperties; i++) { if (masksGroup.property(i).selected) { selectedMasks[selectedMasks.length] = masksGroup.property(i); var Mimascara=i; //alert(selectedMasks.length); } } } if(selectedMasks.length>1) {alert("Please select just one mask");return} if(selectedMasks.length<1) {alert("Please select a mask");return} //alert(Mimascara); //comienza el script var myComp = app.project.activeItem; var myLayer = myComp.selectedLayers[0]; var myMotionTrackers = myLayer.property("Motion Trackers"); var myMask = myLayer.property("ADBE Mask Parade").property(Mimascara); var myProperty = myMask.property("ADBE Mask Shape"); var myShape,p,v,resta; myShape = myProperty.value; v = myShape.vertices; myMotionTrackers.addProperty("ADBE MTracker") var nuevotracker = myMotionTrackers.numProperties; if (nuevotracker == 0){ ;} //nuevotracker++ //var nuevotracker = myMotionTrackers.numProperties; //alert(nuevotracker); var myMotionTracker = myMotionTrackers.property(nuevotracker); for (var i=1; i<=v.length; i++) { var myVertexIndex = i-1; // la siguiente linea puede sustituir por entero a las dos siguientes: // var myTrackPoint = myMotionTracker.addProperty("ADBE MTracker Pt"); myMotionTracker.addProperty("ADBE MTracker Pt"); var myTrackPoint = myMotionTracker.property(i); var myAttachPoint = myTrackPoint.property("ADBE MTracker Pt Attach Pt"); var myFeaturePoint = myTrackPoint.property("ADBE MTracker Pt Feature Center"); myShape = myProperty.value; p = v[myVertexIndex]; myAttachPoint.setValue(p); myFeaturePoint.setValue(p); } } function MaskToTrackClick() { app.beginUndoGroup("Apply Mask"); MaskToTrack(); app.endUndoGroup(); } function MaskToTrack() { //asegurarse de que solo hay una mascara seleccionada var masksGroup = app.project.activeItem.selectedLayers[0]("Masks"); var selectedMasks = new Array(); // Store masks in an array; starts as empty if(app.project.activeItem.selectedLayers.length<1){alert("Please select a mask");return} if (masksGroup != null) // Iterate through properties of masksGroup { // Append selected mask to the array for (var i = 1; i <= masksGroup.numProperties; i++) { if (masksGroup.property(i).selected) { selectedMasks[selectedMasks.length] = masksGroup.property(i); var Mimascara=i; //alert(selectedMasks.length); } } } if(selectedMasks.length>1) {alert("Please select just one mask");return} if(selectedMasks.length<1) {alert("Please select a mask");return} //asegurarse de que solo hay el tracker seleccionado var TrackersGroup = app.project.activeItem.selectedLayers[0]("Motion Trackers"); var selectedTrackers = new Array(); // Store Trackers in an array; starts as empty if (TrackersGroup != null) // Iterate through properties of TrackersGroup { // Append selected Tracker to the array for (var i = 1; i <= TrackersGroup.numProperties; i++) { if (TrackersGroup.property(i).selected) { selectedTrackers[selectedTrackers.length] = TrackersGroup.property(i); var Mitracker=i; //alert(selectedTrackers.length); } } } if(selectedTrackers.length>1) {alert("Please select just a Tracker");return} if(selectedTrackers.length<1) {alert("Please select a Tracker (that contains the trackpoints)");return} //alert(MiTracker); //comienza el script var myComp = app.project.activeItem; var myLayer = myComp.selectedLayers[0]; var myMotionTrackers = myLayer.property("Motion Trackers"); var myMask = myLayer.property("ADBE Mask Parade").property(Mimascara); var myProperty = myMask.property("ADBE Mask Shape"); var myShape,p,v,resta; myShape = myProperty.value; v = myShape.vertices; var myMotionTracker = myMotionTrackers.property(Mitracker); if (myMotionTracker.numProperties < v.length) { resta =v.length - myMotionTracker.numProperties; alert("There are "+resta+" Track Points LESS than Mask Vertices.\n"+"Please create "+resta+" Track Points\n"+"or delete "+resta+" Mask Vertices\n"+"or choose another Mask and/or Tracker."); } else { if (myMotionTracker.numProperties > v.length) { resta =myMotionTracker.numProperties-v.length ; alert("There are "+resta+" Track Points MORE than Mask Vertices.\n"+"Please delete "+resta+" Track Points\n"+"or create "+resta+" Mask Vertices\n"+"or choose another Mask and/or Tracker."); } else { for (var i=1; i<=v.length; i++) { var myVertexIndex = i-1; var myTrackPoint = myMotionTracker.property(i); var myAttachPoint = myTrackPoint.property("ADBE MTracker Pt Attach Pt"); var myAttachPoint2 = myTrackPoint.property("attachPointOffset"); var myMask = myLayer.property("ADBE Mask Parade").property(Mimascara); var myProperty = myMask.property("ADBE Mask Shape"); var myIn = myLayer.inPoint; var myOut = myLayer.outPoint; var f = Math.round(myIn/myComp.frameDuration); // frame counter var myShape,myPoint,p,t; while (f <= Math.round(myOut/myComp.frameDuration)){ t = f*myComp.frameDuration; p = myAttachPoint.valueAtTime(t,true) + myAttachPoint2.valueAtTime(t,true); myShape = myProperty.valueAtTime(t,true); v = myShape.vertices; v[myVertexIndex] = p; myShape.vertices = v; myProperty.setValueAtTime(t,myShape); f++; } } } } } function Minus10Click() { app.beginUndoGroup("First Vertex <<"); rotateMask(app.project.activeItem.layers[1],1,-10) app.endUndoGroup(); } function Minus1Click() { app.beginUndoGroup("First Vertex <"); rotateMask(app.project.activeItem.layers[1],1,-1) app.endUndoGroup(); } function Plus1Click() { app.beginUndoGroup("First Vertex >"); rotateMask(app.project.activeItem.layers[1],1,1) app.endUndoGroup(); } function Plus10Click() { app.beginUndoGroup("First Vertex >>"); rotateMask(app.project.activeItem.layers[1],1,10) app.endUndoGroup(); } function rotateMask(obj,maskIndex,distancia) { //asegurarse de que solo hay una mascara seleccionada var masksGroup = app.project.activeItem.selectedLayers[0]("Masks"); var selectedMasks = new Array(); // Store masks in an array; starts as empty if (masksGroup != null) // Iterate through properties of masksGroup { // Append selected mask to the array for (var i = 1; i <= masksGroup.numProperties; i++) { if (masksGroup.property(i).selected) { selectedMasks[selectedMasks.length] = masksGroup.property(i); var Mimascara=i; //alert(selectedMasks.length); } } } if(selectedMasks.length>1) {alert("Please select just one mask");return} if(selectedMasks.length<1) {alert("Please select a mask");return} //alert(Mimascara); //comienza el script //mete todas las mascaras en un array var masksGroup = app.project.activeItem.selectedLayers[0]("Masks"); var selectedMasks = new Array(); // Store masks in an array; starts as empty // Append selected mask to the array // if (masksGroup.property(j).selected) { // selectedMasks[selectedMasks.length] = masksGroup.property(i); // maskIndex=j; //aqui viene el script var curMask2=masksGroup.property(Mimascara).property("ADBE Mask Shape") var cuantoskeyframes=curMask2.numKeys; //alert("va"); if(cuantoskeyframes>0) { // alert(cuantoskeyframes);return for (var keyIndex = 1; keyIndex <= cuantoskeyframes ; keyIndex++) { // existing mask var curMask= masksGroup.property(Mimascara).property("ADBE Mask Shape") var verts= curMask.keyValue(keyIndex).vertices var inTans= curMask.keyValue(keyIndex).inTangents var outTans= curMask.keyValue(keyIndex).outTangents // collect the values var tempVerts=[] var tempInTans=[] var tempOutTans=[] for(var i=curMask.value.vertices.length-1;i>=0;i--){ for (distancia;distancia>=curMask.value.vertices.length;distancia-=curMask.value.vertices.length) {} for (distancia;distancia<0;distancia+=curMask.value.vertices.length) {} var punto = i+distancia if (punto>=curMask.keyValue(keyIndex).vertices.length) { punto-=curMask.keyValue(keyIndex).vertices.length } tempVerts[i]=verts[punto] tempInTans[i]=inTans[punto] tempOutTans[i]=outTans[punto] } // build the shape var tempMask=new Shape() tempMask.vertices = tempVerts tempMask.inTangents = tempInTans tempMask.outTangents = tempOutTans tempMask.closed=curMask.value.closed // assign mask //alert("vamos bien"); ahora=curMask.keyTime(keyIndex) //alert(ahora) // curMaskAhora=curMask.valueAtTime(,true) curMask.setValueAtTime(ahora, tempMask) //alert("ya") } } else{ // existing mask var curMask= masksGroup.property(Mimascara).property("ADBE Mask Shape") var verts= curMask.value.vertices var inTans= curMask.value.inTangents var outTans= curMask.value.outTangents // collect the values var tempVerts=[] var tempInTans=[] var tempOutTans=[] for(var i=curMask.value.vertices.length-1;i>=0;i--){ for (distancia;distancia>=curMask.value.vertices.length;distancia-=curMask.value.vertices.length) {} for (distancia;distancia<0;distancia+=curMask.value.vertices.length) {} var punto = i+distancia if (punto>=curMask.value.vertices.length) { punto-=curMask.value.vertices.length } tempVerts[i]=verts[punto] tempInTans[i]=inTans[punto] tempOutTans[i]=outTans[punto] } // build the shape var tempMask=new Shape() tempMask.vertices = tempVerts tempMask.inTangents = tempInTans tempMask.outTangents = tempOutTans tempMask.closed=curMask.value.closed // assign mask curMask.setValue(tempMask) } //alert(selectedMasks.length); } function InterpolTClick() { app.beginUndoGroup("Interpolate Tangents"); Interpol(0,1,0); app.endUndoGroup(); } function InterpolVClick() { app.beginUndoGroup("Interpolate Vertex"); Interpol(1,0,0); app.endUndoGroup(); } function InterpolVRClick() { app.beginUndoGroup("Interpolate Vertex"); Interpol(1,0,1); app.endUndoGroup(); } function Interpol(verticessi, tangentessi,relativo) { //asume q el tiempo en las keyframes coincide inequivocamente //con el de alguna frame //asegurarse de que solo hay una mascara seleccionada if(app.project.activeItem.selectedLayers.length<1){alert("Please select a mask");return} var masksGroup = app.project.activeItem.selectedLayers[0]("Masks"); var selectedMasks = new Array(); // Store masks in an array; starts as empty if (masksGroup != null) // Iterate through properties of masksGroup { // Append selected mask to the array for (var i = 1; i <= masksGroup.numProperties; i++) { if (masksGroup.property(i).selected) { selectedMasks[selectedMasks.length] = masksGroup.property(i); var Mimascara=i; //alert(selectedMasks.length); } } } if(selectedMasks.length>1) {alert("Please select just one mask");return} if(selectedMasks.length<1) {alert("Please select a mask");return} //alert(Mimascara); //comienza el script //tolerancia para los tiempos: var tol = 0.005; //se aplica sobre el primer vertice. para cambiarlo, cambiar //la siguiente variable: var numVertice = 0; var myComp = app.project.activeItem; var myLayer = myComp.selectedLayers[0]; var myMask = myLayer.property("ADBE Mask Parade").property(Mimascara); var myProperty = myMask.property("ADBE Mask Shape"); if (myProperty.isTimeVarying==0){ alert("This function interpolates a vertex in Mask Keyframes.\n"+"Please select a mask with a keyframed shape."); return} var markerTimes = new Array(); layerIn = myLayer.inPoint; layerOut = myLayer.outPoint; numMarkers = myLayer.property("Marker").numKeys for (var i = 1; i <= numMarkers; i++) { markerTimes[i] = myLayer.property("Marker").keyTime(i); } var myShape,inTanInicial,outTanInicial,inTanFinal,outTanFinal; var inTan, outTan, Frames, indiceKey, tiempo; var verts, vInicial, vFinal, vert; for (i = 1; i"); newButton.onClick = Plus1Click; return newButton; } function addPlus10Button(palette, buttonRect) { var newButton = palette.add("button", buttonRect, ">>"); newButton.onClick = Plus10Click; return newButton; } function addTangButton(palette, buttonRect) { var newButton = palette.add("button", buttonRect, "Interpol Tangets"); newButton.onClick = InterpolTClick; return newButton; } function addVertexButton(palette, buttonRect) { var newButton = palette.add("button", buttonRect, "Interpol Vertex"); newButton.onClick = InterpolVClick; return newButton; } function addVertexRelButton(palette, buttonRect) { var newButton = palette.add("button", buttonRect, "Interpol Vertex Rel"); newButton.onClick = InterpolVRClick; return newButton; } // Horizontal Spacing variables var left_margin_width = 5; var right_margin_width = 5; var between_button_width = 5; // Width of buttons depends on platform and language var button_width; if (system.osName.indexOf("Windows") != -1) { // Windows system has narrower buttons. button_width = 105; } else { // Mac has wider buttons button_width = 120; } if (app.language == Language.JAPANESE) { // Add 20 pixels for japanese machines, default font is wider button_width += 17; } var l_button_left = left_margin_width; var l_button_right = l_button_left + button_width; var l_button_right2 = l_button_right/2-between_button_width/2; var l_button_left2 = l_button_right2+between_button_width; var r_button_left = l_button_right + between_button_width; var r_button_right = r_button_left + button_width; var r_button_right2 = r_button_left + button_width/4-between_button_width/2; var r_button_left2 = r_button_left + button_width/4+between_button_width/2; var r_button_right3 = r_button_left2 + button_width/4-between_button_width/2; var r_button_left3 = r_button_right3 +between_button_width/2; var r_button_right4 = r_button_left3 + button_width/4-between_button_width/2; var r_button_left4 = r_button_right4 +between_button_width/2; var palette_width = r_button_right + right_margin_width; // Create and show a floating palette // var my_palette = new Window("palette","Script Demos"); my_palette.bounds = [300,100,300+palette_width,205]; var button1 = addHelp1Button( my_palette,[l_button_left, 5, l_button_right2, 25]); var button2 = addHelp2Button( my_palette,[l_button_left2, 5, l_button_right, 25]); var button3 = addApplyTrackerButton( my_palette,[l_button_left, 30, l_button_right, 50]); var button4 = addApplyMaskButton( my_palette,[l_button_left, 55, l_button_right, 75]); var button5 = addCredits( my_palette,[l_button_left, 80, l_button_right, 100]); var button6 = addMinus10Button( my_palette,[r_button_left, 5, r_button_right2, 25]); var button7 = addMinus1Button( my_palette,[r_button_left2, 5, r_button_right3, 25]); var button8 = addPlus1Button( my_palette,[r_button_left3, 5, r_button_right4, 25]); var button9 = addPlus10Button( my_palette,[r_button_left4, 5, r_button_right, 25]); var button10 = addTangButton( my_palette,[r_button_left, 30, r_button_right, 50]); var button11 = addVertexButton( my_palette,[r_button_left, 55, r_button_right, 75]); var button12 = addVertexRelButton( my_palette,[r_button_left, 80, r_button_right, 100]); my_palette.show(); }