Enhance Footage (from an Adobe Premiere Project)

All things .jsx

Moderator: Paul Tuersley

Post Reply
w_m0zart
Posts: 20
Joined: June 6th, 2005, 1:52 pm
Location: Hengelo, Netherlands
Contact:

What is it for?
Improving the quality from a large collection of clips from the Adobe Premiere project manager by using the power of After Effects and its scripting feature. The basic idea behind this is that when working in a multicamera environment, each footage should undergo its own specific processing, depending from which camera it comes. (These differences have to do with CCD-noise levels and de-interlacing settings, depending on noise and movement in the recorded material.) This will reduce the differences between the footage from each camera. It's like giving each camera it's own profile.

Adobe Premiere
After the project has been optimised by its project manager, you are stuck with a tremendous amount of seperated clips. Making projects and compositions by hand with all these clips in After Effects, is too painstaking. So here comes scripting!

After Effects Processing
If you have DV-files, you could use the Fieldskit Deinterlacer and the (build in) Remove Grain effects in order to get proper deinterlacing and film-like footage. But if you have hundreds of clips would you like to do the following steps by hand?
1.Interpret footage setting: Fields OFF
2.Create Comp, add footage to it; length, size and framerate will be same as footage
3.*User interaction: select which Fieldskit deinterlace effect preset should be used
4.*User interaction: select which remove grain preset should be used
5.Apply fieldskit effect with the selected preset/template
6.Pre-compose
7.Apply remove-grain effect with selected preset/template
8.Add a mask which will be the TV 'safe area'
9.Add comp to render queue with correct settings by using two templates.

For creating the presets, a small utility is available. It extracts from a composition which contains a layer with some selected effect its settings and writes that to a file. See the second post for that.

How to use the footageToFilm script
(In combination with Adobe Premiere, once your Project is finished do the following:
~1.In Adobe Premiere go to Project->Project Manager
~2.Select the following (default settings):
~-----Create New Trimmed Project
~-----Exclude Unused Clips
~-----Include Handles 25 Frames
~-----Rename Media Files to Match Clip Names
~-----Set a new folder name for your Project Destination
~3.Click OK
Premiere analyses your project, copies only those parts of your footage which are being displayed.
~4. Once done, close Premiere, open the .prproj Premiere project with After Effects, continue with step
3. below)
1. Make a project in After Effects
2. Add footage
3. Select the footage which should undergo these 9 steps
4. Start script, follow it's instruction

The rendered output files will be written in the same folder as the source footage files with a preceding 'R_Fx_'. To change this see function myDataObj. If an alternativ location should be specified, you should change the function add2RenderQ. Please note that if the footage origin is coming from a network source, the filename for the rendered output cannot not (yet) be created properly. You should correct this in the Render Queue manually.

FOR THE RENDER QUEUE FOLLOWING IS VERY IMPORTANT!
In order to create proper output in the Render Queue, you must create a template with your best settings, called: "BestSettings"
And an output module with your preferred codec, called: "LosslessCodec"

Code: Select all

//###############################################################################
//# FootageToFilm script
//# What it does basically:
//# Creates from footage which is in the project window automatically a composition
//# to which basically the Fieldskit Deinterlacer and the Remove Grain effects
//# will be applied.
//# The settings for these two effects are taken from a template file, for which
//# file dialog windows appear in which these files can be selected.
//#
//# What is it for?
//# Improving quality of clips from a Premiere project. After the project has been 
//# optimized by its project manager, you are stuck with a tremendous amount of 
//# separated clips. Making a project with all these clips in After Effects is
//# too painstaking. So here comes scripting!
//#
//# What it does in steps: (See function performAction() below)
//# For a group of selected footage files in the project, each file will be treated as follows:
//# 1.interpret footage setting: Fields OFF
//# 2.Create Comp, add footage to it; length, size and frame rate will be same as footage
//# 3.*User interaction: select which fieldskit effect preset should be used
//# 4.*User interaction: select which remove grain preset should be used
//# 5.apply fieldskit effect with the selected preset/template
//# 6.pre-compose
//# 7.apply remove-grain effect with selected preset/template
//# 8.Add a mask which will be the TV 'safe area'
//# 9.add comp to render queue with correct settings by using two templates.:
//#
//# The two templates for the Render Queue need exactly the following names
//# 1. BestSettings
//#  This has all details concerning the Render Settings.
//# 2. LosslessCodec
//#  This has all details concerning the Output Module.
//#
//# Written in June-September 2005, by Marc Nijdam
//###############################################################################

{
//###############################################################################
//#              \/ \/ \/ \/ Program Entry point \/ \/ \/ \/

//###############################################################################
//# declare and initialise variables and some objects
//###############################################################################
	var proj 	= app.project;		// Set project
	String.prototype.trimExt=trimExtension; // String method usage: .trimExt() if present, removes file extension

	var Fn		= new Array(); 		// This Array will hold objects with effectdata and functionality
	Fn[0]		= new EffectsObj;	// Fn[0] is an object from EffectsObject; Create object, initialise and do the constructor
	Fn[1]		= new EffectsObj;
	myConst		= new myDataObj;	// This Object Stores Data about a.o Final Mask (So called 'Safe Area') and other constants

//###############################################################################
//# Check validity of project
//# Load effect array with objects for each effect
//# Iterate through each selected footage file
//###############################################################################
	var selectedFootage=examineProject(proj);
	if (typeof selectedFootage != 'string') // Alert error if a string is being returned, it contains a guru notice.
	{
		// ****  Prepare Data  ****
		Fn=getEffectData(proj,Fn);	// Stuff array with objects which hold data about the to be applied effects
		if (validEffectData(Fn))	// Check whether user pressed cancel in one of the dialogs
		{
			// **** Perform Action; iterate through each selected Footage in the Project window ****
			proj.renderQueue.showWindow(true);			// Show progress in the Render Queue window
			app.beginUndoGroup("Footage to Film");			// Create undo group
			for (var i = 0; i <selectedFootage> projClt		;project object (=app.project)
//# --> curItem		;this is the avi or mov file
//# <created>= cNMyData.nameMaxLength)  // abbreviate long names, by chopping off part of the middle. Long names will throw an error!
		{
			cN=cN.substring(0, cNMyData.nameStartLength)+cNMyData.nameAbbTxt+cN.substring(cN.length-(cNMyData.nameStartLength+cNMyData.nameAbbTxt.length+cNMyData.comp2Name.length)-1, cN.length);
		}
		return crProj.items.addComp(cNMyData.comp2Name + cN,crCurItem.width,crCurItem.height,crCurItem.pixelAspect,crCurItem.duration-.005,crCurItem.frameRate);
	}

//###############################################################################
//#
//# precompose a specific layer
//#
//# --> fproj		;project object (=app.project)
//# --> fprojComp	;comp with Fieldskit applied (typeName=Composition)
//# --> fprcnm		;The name for the precomp
//# <precomp> 24) flayerName = flayerName.substring(0, 23);
		fnCompName += flayerName;

		return fprojComp.layers.precompose([1], fnCompName, true );
	}

//###############################################################################
//#
//# myDataObj object; this objects holds some constants, which are collected here all together.
//#
//###############################################################################
	function myDataObj() // // ***** Object + constructor
	{
		this.maskTop	= 10;
		this.maskBottom	= 10;
		this.maskLeft	= 33;
		this.maskRight	= 33;

		this.nameMaxLength	= 27;	// a long filename will be abbreviated
		this.nameStartLength	= 8;	// 1234567890123456789012345678901234
		this.nameAbbTxt		= "...";// Fx_filename...tail_of_name_001
		this.comp1Name		= "~Fx_";
		this.comp2Name		= "Fx_";

		this.renderNameHead	="R_";
		this.templateSetting	="BestSettings";
		this.outputModule	="LosslessCodec";
	}


//###############################################################################
//#
//# addMask
//# adds a mask to a specified layer
//# ---> composition
//# ---> maskdata
//#
//###############################################################################
	function addMask(aMprojComp,aMdata)
	{
		var maskGroup	= aMprojComp.layer(1).property("Masks");
		var mask 	= maskGroup.addProperty("Mask");	// Create a new mask

		var atC	=aMdata.maskTop;
		var abC	=aMprojComp.height-aMdata.maskBottom;
		var arC	=aMdata.maskLeft;
		var alC	=aMprojComp.width-aMdata.maskRight;


		var mskShape	= new Shape();
		mskShape.vertices = [ [alC,atC], [arC,atC], [arC,abC], [alC,abC] ];
		mskShape.closed	= true;

		maskShape	= mask.property("maskShape");		// Get the Mask Shape property for the mask
		maskShape.setValue(mskShape);				// Change the mask shape (not keyframed)

		return;
	}

//###############################################################################
//#
//# EffectsObj object
//#
//###############################################################################
	function EffectsObj() // // ***** Object + constructor
	{
		this.EFFSTR	= "ADOBE_Property" + "_";
		this.EFFNAME	= "ADOBE_EffectName";
		this.succes	= false;
		this.guru	= ""; //this string might hold error after processing
		this.Apply	= FFApply; // call to function FFApply();

		String.prototype.trim = trimSpaces; 		// method usage: .trim() 		removes leading and trailing spaces
		String.prototype.parse = parseLine;		// method usage: .parse(_character_)	beginning at position 0, search for = character, return what's after = character
		String.prototype.isFfPrp = isEffectProperty;	// method usage: .isFfPrp() 		returns true if this line has = sign, false if it hasn't
		String.prototype.cntFfDat = countData;		// method usage: .cntFfDat()		returns the amount of numbers on this line. (e.g. "[1.0,5.4]".cntFfDat()=2)
		String.prototype.getFfIDat = getIndexedData;	// method usage: .getIndexedData(_index_) returns the n-th number on this line. (e.g. "[1.0,5.4]".getFfIDat(2)=5.4)
		String.prototype.isFfComment = isComment;	// method usage: .isFfComment()		true if this line is regarded as comment (starts with ;)
		String.prototype.getFfPrpNr = getPropertyNumber; //method usage: .getFfPrpNr()		returns the number, which follows after EFFSTR (e.g. ADOBE_Property_2=Point B will give 2)
		String.prototype.getFf2Array = getLine2Array;	// method usage: .getFf2Array()		returns array from a given string (e.g. [1,2,3,4,5] -> [0] = 1, [1]=2,.., [4]=5)
		Array.prototype.reOrder = reOrderArray;		// method usage: .reOrder()		returns reordered array, taking into account dependencies defined by a specific effect (first item in array says which effect)
	}

	function FFApply()
	{
		var FFename;
		var FFedata;
		var FFvalue;
		var FFbase;

		var FFi=0;
		var FFj;
		var FF1;
		this.FFArray.reOrder(); // optimize array, remove comment and properties without values; This line may be removed for compatibility options.
		while ( ( this.FFArray[FFi].indexOf(this.EFFNAME) == -1) && (FFi < this.FFArray.length-1) ) FFi++; // search for occurrence of string EFFNAME

		if (FFi <this>testfile)
	{
		var tEstr=this; // 'this' is only readable...
		var tEi=tEstr.length;
		while ( (tEstr.charAt(tEi) != '.') && (tEi > 0) ) tEi--;
		if (tEi != 0) return tEstr.substring(0,tEi);
		return tEstr;	}

	function parseLine(pLq) // extract part after character pLq
	{
		var pLstr=this; // 'this' is only readable...
		while ( (pLstr.charAt(0) != pLq) && (pLstr.length>0)) pLstr = pLstr.substring(1);
		return pLstr.substring(1);
	}
	
	function isEffectProperty() // does it start with EFFSTR and has this line the '=' character? if so, return true, else false
	{
		if ( this.indexOf("=") == -1) return false; // first check for presence of = sign;

		iEP= new EffectsObj; // need temporarily EFFSTR

		if ( this.substring(0,iEP.EFFSTR.length) == iEP.EFFSTR )
		{
			iEP=null;
			return true;
		}
		iEP=null;
		return false;
	}

	function countData() // count the amount of numbers
	{
		if (this.length==0) return 0;
		var cDi;
		var cDNaN=false;
		var cDBrB=0;
		var cDBrE=0;
		var cDcnt=1;
		for (cDi=0; cDi<this>1) || (cDBrE>1) || (cDBrB != cDBrE) ) return 0;
		return cDcnt;
	}

	function getIndexedData(gID) // will return the n-th number on this line
	{
		if (gID==0) return -1; // index =0 is not valid
		if (gID>this.cntFfDat()) return -1; // out of range
		if (this.cntFfDat()==1)
		{
			if ( (this.trim().charAt(0) != "[") || (this.trim().charAt(this.trim().length-1) != "]") ) return parseFloat(this.trim()); // there's only one number
		}

		if ( this.trim().length<=2) return 0; // or write 0.0? anyway, check length
		if ( (this.trim().charAt(0) != "[") || (this.trim().charAt(this.trim().length-1) != "]") ) return -1; // wrong array notation; string should be like [1,2,..,n]
		
		var gIDstr=this.trim().substring(1, this.trim().length-1).trim(); // remove [ and ]
		if (gIDstr.cntFfDat()==1) return parseFloat(gIDstr); // someone put a single number in an array notation e.g. [20.5]
		
		for (var gIDi=1; gIDi<gID>= 1) return parseFloat( gIDstr.substr( 0 , gIDstr.indexOf(",") ) ); // trim the rest of the numbers on this line
		
		return parseFloat(gIDstr); // there's only one number
	}

	function isComment()
	{
		if (this.trim().charAt(0)==";") return true;
		return false;
	}
	function getPropertyNumber() // will return number between second '_' character and '=' character
	{
		if (this.length==0) return -1;
		var gPNi;
		var gPNEqs=0;
		var gPNUsc=0;
		for (gPNi=0; gPNi<this>= 1) && (gPNEqs == 1) )
		{
			if ( this.trim().substring(this.trim().lastIndexOf("_")+1,this.trim().indexOf("=") ).trim().cntFfDat() == 1 ) return parseInt(this.trim().substring(this.trim().lastIndexOf("_")+1,this.trim().indexOf("=") ).trim());
		}
		return -1;
	}
	
	function getLine2Array() // will return an array with all data from a string
	{
		if (this.length == 0) return [-1];
		if (this.cntFfDat() == -1) return [-1];

		var gL2A = new Array( this.cntFfDat() );
		var gL2Ai;
		for (gL2Ai=0; gL2Ai<=this.cntFfDat()-1; gL2Ai++)
		{
			gL2A[gL2Ai]=this.toString().getFfIDat(gL2Ai+1);
		}
		return gL2A;
		
	}

	function reOrderArray()
	{
		if (this.length==0) return this;

		var FFrOA=this;
		var FFrOi;
		var FFrOstr="";

		var FFrOj=0;
		for (FFrOi = 0; FFrOi < this.length; FFrOi++) // remove all lines with comment
		{
			if ( this[FFrOi].toString().isFfComment()) ;
			else FFrOA[FFrOj++]=this[FFrOi];
		}
		FFrOA.length=FFrOj; // correct now the Array length

		FFrOEP= new EffectsObj; // need temporarily EFFSTR
		if ( FFrOA[0].indexOf(FFrOEP.EFFNAME) == -1) return FFrOA; // First line should contain the string EFFNAME
		FFrOEP=null; // discard object

		if (FFrOj==1) return FFrOA; // The current Array holds only item; the line with string EFFNAME, but no further property or data; so finished for now!

		FFrOj=1;
		var FFrOprOrd = new Array();
		for (FFrOi = 1; FFrOi <FFrOA> Project
//# ---> Array
//# <Array> Array
//# <Array> app.project
//# ---> composition
//#
//###############################################################################
	function add2RenderQ(a2rProj,a2rComp,a2rConst)
	{
		a2rProj.renderQueue.items.add(a2rComp);
		var a2rQ = a2rProj.renderQueue.item(a2rProj.renderQueue.numItems); 	// added rendertask will be the last in the stack
		a2rQ.applyTemplate(a2rConst.templateSetting);
		a2rQ.outputModules[1].applyTemplate(a2rConst.outputModule);
		var a2rOldLocation=a2rQ.outputModule(1).file;
		a2rQ.outputModule(1).file=new File(a2rProj.file.path + "/" + "R_"+a2rOldLocation.name);
		return;
	}

//###############################################################################
//#
//# performAction
//#
//# perform actions to a selected footage file in this project
//# ---> proj,selection,EffectsArray
//#
//###############################################################################
	function performAction(exProj,exSelection,exFn)
	{
		var newComp;						//holds a composition
		var newLayr;						//holds a layer
		var newPrcp;						//holds a precomposition

		if ( (exSelection.hasVideo) && (exSelection.typeName == "Footage") )	//check if item is a video file
		{
			// change interpret footage by setting separate fields
			exSelection.mainSource.fieldSeparationType=FieldSeparationType.OFF;

			// Create new comp with length, size and framerate. Name will be same as source, with preceding Fx and omitted extension
			newComp=createNcomp(exProj,exSelection,myConst);

			// Add Footage into this comp
			newLayr	= newComp.layers.add(exSelection);	//variable for collection of layer objects in logoComp

			// Apply Fieldskit effect
			exFn[0].layr=newLayr;				//set layer to which effect must be applied
			exFn[0].Apply();				//apply effect
			if (exFn[0].guru) { alert(exFn[0].guru); return; } //anounce any errors

			// Precompose previous layer
			newPrcp=fprecomp(exProj,newComp,myConst);

			// Apply Remove Grain
			exFn[1].layr=newComp.layers[1];
			exFn[1].Apply();
			if (exFn[1].guru) { alert(exFn[1].guru); return; } //anounce any errors

			// Add Mask
			addMask(newComp,myConst); // myConst holds data about the mask borders

			// Add to Render Queue
			add2RenderQ(exProj,newComp,myConst);
		}
		return;
	}
			
}
Last edited by w_m0zart on June 22nd, 2007, 3:28 pm, edited 13 times in total.
w_m0zart
Posts: 20
Joined: June 6th, 2005, 1:52 pm
Location: Hengelo, Netherlands
Contact:

Generator for .tfx-file
This script creates a .tfx file, which is being used in the footageToFilm script.
In order to use it make a project, add footage, make a comp from it and add your effect. Select the effect and run this script.

Code: Select all

//###############################################################################
//# Original file name: GenerateTFX.jsx
//# Generate EffectTemplateFile script
//# What it does basically:
//# Just creates a .tfx (effect template file; text file) from a certain selected
//# effect. The file helps finding out which property x and value y belongs to 
//# effect z.
//# 
//# Another purpose for a .tfx file is it can be read in directly with the Apply.tfx
//# script. Once read in adding this effect to a layer is very easy.
//###############################################################################
//# _The structure of an .tfx file is:_
//#
//# -Each line is seperated with cr/lf
//# -everything following a semicolon (;) is regarded as comment
//# -comment should be on a seperate line
//# -before all properties and data, there should be ADOBE_EffectName=
//#    for example: ADOBE_EffectName=Grain Surgery
//# -Effectproperties must start with "ADOBE_Property_" continued by a number and "="
//#    for example: ADOBE_Property_4=Width
//# -single values are written without brackets, just plain numbers
//#    for example: 1.523
//# -arrays are in the format [x,y,..,z]
//#    for example: [0.5,1.0,0.8]
//#
//# To have more insight, just produce one with the GenerateTFX script, and analyze it
//###############################################################################
//# Written in July 2005, by Marc Nijdam. Though probably lot's of useful code
//# from others can be found in here as well.
//###############################################################################
//# For reading out the following applies:
//# number of applied effects on this layer:
//# app.project.activeItem.selectedLayers[0]("Effects").numProperties;
//# name of first effect:
//# app.project.activeItem.selectedLayers[0]("Effects")(1).name;
//# number of properties from the (first) effect:
//# app.project.activeItem.selectedLayers[0]("Effects")(1).numProperties;
//# name of the i-th property from the (first) effect
//# app.project.activeItem.selectedLayers[0]("Effects")(1)(i).name;
//# query which kind of property from the i-th property this is
//# app.project.activeItem.selectedLayers[0]("Effects")(1)(i).propertyValueType;
//# possible values: PropertyValueType.NO_VALUE
//#                  PropertyValueType.TwoD_SPATIAL
//#                  PropertyValueType.TwoD
//#                  PropertyValueType.OneD
//#                  PropertyValueType.COLOR
//#                  PropertyValueType.CUSTOM_VALUE
//# number of elements in array from the i-th element (if it's an array)
//# app.project.activeItem.selectedLayers[0]("Effects")(1)(i).value.length;
//# Value from the i-th property; (if it ain't an array)
//# app.project.activeItem.selectedLayers[0]("Effects")(1)(i).value;
//# Value from the j-th array element from the i-th property (if an array it is)
//# app.project.activeItem.selectedLayers[0]("Effects")(1)(i).value[j];
//###############################################################################
{
// some kind of constants
	var _EFFSTR	= "ADOBE_Property_";
	var _EFFNAME	= "ADOBE_EffectName";
// variables
	var proj 	= app.project;						//set project
	var projClt 	= proj.items;						//list of items in project
	var projAi;
	var fileName;								//output filename
	var thisLayer;
	var thisEffectsLayer;
	var thisEffect;
	var i;
	var j;
	if (proj)
	{
		if (proj.numItems != 0) // select the active item in the project window, make sure it's footage
		{
			projAi=proj.activeItem;
			if ( (projAi != null) && (projAi instanceof CompItem) && (projAi.selectedLayers.length == 1) )
			{
				thisLayer=projAi.selectedLayers[0];
				thisEffectsLayer=thisLayer("Effects");
				if (thisEffectsLayer != null) // this layer might have effects...
				{
                     		if (thisEffectsLayer.numProperties == 1)
					{
						thisEffect=thisEffectsLayer(1); // Only one effect available, so it's safe to take the first

						var fileName=Dialog1();
						if (fileName != -1)
						{
							var Fstr = new File(fileName);
							if (Fstr != null)
							{
								Fstr.open("w","TEXT","????");
								Fstr.writeln(_EFFNAME + "=" + thisEffect.name);

								for (i = 1; i <= thisEffect.numProperties; i++) // iterate through all properties
								{
									if (thisEffect.property(i).name != "")
									{
										switch (thisEffect(i).propertyValueType)
										{
											case PropertyValueType.NO_VALUE: // property without a value
											{
												Fstr.writeln(";*** " + thisEffect.property(i).name + " ***");
												Fstr.writeln(_EFFSTR + i + "=" + thisEffect.property(i).name);
												break;
											}
											case PropertyValueType.OneD: // property with a single value
											{
												Fstr.writeln(_EFFSTR + i + "=" + thisEffect(i).name);
												Fstr.writeln(thisEffect.property(i).value);
												break;
											}
											case PropertyValueType.TwoD: // property with an array
											{
												Fstr.writeln(_EFFSTR + i + "=" + thisEffect.property(i).name);
												str="[";
												for (j = 1; j < thisEffect.property(i).value.length ; j++)
												{
													str+=thisEffect.property(i).value[j-1] + ",";
												}
												str+=thisEffect.property(i).value[thisEffect.property(i).value.length-1] + "]";
												Fstr.writeln(str);
												break;
											}
											case PropertyValueType.TwoD_SPATIAL:
											{
												Fstr.writeln(_EFFSTR + i + "=" + thisEffect.property(i).name);
												str="[";
												for (j = 1; j < thisEffect.property(i).value.length ; j++)
												{
													str+=thisEffect.property(i).value[j-1] + ",";
												}
												str+=thisEffect.property(i).value[thisEffect.property(i).value.length-1] + "]";
												Fstr.writeln(str);
												break;
											}
											case PropertyValueType.ThreeD:
											{
												Fstr.writeln(_EFFSTR + i + "=" + thisEffect.property(i).name);
												str="[";
												for (j = 1; j < thisEffect.property(i).value.length ; j++)
												{
													str+=thisEffect.property(i).value[j-1] + ",";
												}
												str+=thisEffect.property(i).value[thisEffect.property(i).value.length-1] + "]";
												Fstr.writeln(str);
												break;
											}
											case PropertyValueType.ThreeD_SPATIAL:
											{
												Fstr.writeln(_EFFSTR + i + "=" + thisEffect.property(i).name);
												str="[";
												for (j = 1; j < thisEffect.property(i).value.length ; j++)
												{
													str+=thisEffect.property(i).value[j-1] + ",";
												}
												str+=thisEffect.property(i).value[thisEffect.property(i).value.length-1] + "]";
												Fstr.writeln(str);
												break;
											}
											case PropertyValueType.COLOR: // property with a color
											{
												Fstr.writeln(_EFFSTR + i + "=" + thisEffect.property(i).name);
												str="[";
												for (j = 1; j < thisEffect.property(i).value.length ; j++)
												{
													str+=thisEffect.property(i).value[j-1] + ",";
												}
												str+=thisEffect.property(i).value[thisEffect.property(i).value.length-1] + "]";
												Fstr.writeln(str);
												break;
											}
											case PropertyValueType.CUSTOM_VALUE: // property with a custom value
											{
												Fstr.writeln(_EFFSTR + i + "=" + thisEffect(i).name);
												break;
											}
											default:;
										}
									}
								}
								Fstr.close();
							}
							else 
							{
								alert("Sorry, there had been a problem writing the file");
							}
						}
					}
					else
					{
						alert("Sorry, this layer should have (only) one effect applied");
					}
				}
				else
				{
					alert("Sorry, this layer has no effect applied...");
				}
			}
			else
			{
				alert("select (only) one layer in a composition please...");
			}
		}
		else
		{
			alert("Can't process an empty project, please put some footage into it");
		}
	}
	else
	{
		alert("In order to use this script, Please create a project (with some footage)");
	}

//###############################################################################
//#
//# Asks user for filename for effect template
//# --> nothing
//# <-- Array or -1 (User pressed cancel)
//#
//###############################################################################
	function Dialog1()
	{
		var _ffx1;
		_ffx1	= filePutDialog("Please select a Filename for the Effect Template, or cancel to quit", "", "TEXT tfx");
		if (_ffx1 != null) return _ffx1;
		else return [-1];
	}
}
Post Reply