Add a Point Light to each Selected Layers postition

What type of scripts do you need?

Moderator: byronnash

Post Reply
KarmaFx
Posts: 1
Joined: August 11th, 2011, 8:21 am

This has to be an easy one...
How about a script to add Point lights to the position property of each of the selected layers?
I would be useful for placing lights on several nulls from a matchmoving solve all at once.

Anyone can help me?
dfred
Posts: 29
Joined: July 23rd, 2010, 11:49 pm

Here's a not so pretty attempt. You need the After Effects project file (attached) in the same folder as the script. Also the undo is messed up.

Maybe somebody better at scripting could help get the undo working, but other than that it's functioning:

Code: Select all

#target aftereffects
{ function df_AddPointLightsToNullObjects()
	{
	/* df_Add Point Lights to Null Objects_v1.15
This script will create a new point light at all selected 3D nulls.
This might be useful for someone who imports 3D tracking nulls and applies affects
such as Video Copilot's Optical Flares, Trapcode Particular, Plexus, etc.
Created by Dan Fredley
Special thanks to nab for the lightComp idea and Paul Tuersley's DupWithChildren.

While this script is functioning there is one problem so far:
1) The undo group gets messed up by either the import project command or the looping function

Maybe someone who is better at scripting can fix this problem.  But other than that it works.

If you don't have access to the .aep file you can create your own by setting up the following:
1) Create a comp named "lightComp"
2) Add a light and name it "ambientLight" then set type to ambient
3) Duplicate it above "ambientLight" and name it "pointLight" and set to point
4) Duplicate it above "pointLight" and name it "spotLight" and set to spot
5) Duplicate it above "spotLight" and name it "parallelLight" and set to parallel
6) For this script it is important that "pointLight" be the third layer and the "lightComp" be
    the first object in the project window.  The reason I added the other lightTypes is so you can use
    the same project for other scripts and light type until Adobe allows scripting access to light types.
*/
	


    
	var proj = app.project;

	function dupeIt(comp, layer) {
		


		
    var pointLight = (app.project.activeItem.layer("pointLight").duplicate()); // duplicate the light
    pointLight.parent = layer; // parent the light to the selected layer
    var newName =  (layer.name.substr(0,25));//truncate the layer's name for new object's name
    pointLight.name = (lightPrefix + "_" + newName + "_light"); // add the Prefix that was prompted earlier
    pointLight.property("position").setValue([0,0,0]); // zero out the position of the light to match selected layer's position
    pointLight.moveToEnd(); //move the light to the bottom of the comp
    layer.selected = false; //deselect the layer
    pointLight.selected = false; //deselect the light
    
	
		// loop through each layer in the comp
		for(var i = 1; i<= comp.numLayers; i++) {
			//if the next layer doesn't have a parent, but is selected continue duplicating the point light
			if(!comp.layer(i).parent && !comp.layer(i) instanceof LightLayer) {
				comp.layer(i).selected = true ;

				// recursively run through this function, this time using the new selected layer
				var pointLight = dupeIt(comp, comp.layer(i));

                   
			}
		}

		return pointLight;

	}


	// this recursive function should deselect all lights that are parented

	function hasSelectedParent(layer) {

		//alert("checking layer " + layer.name + " has a parent");

		// if this layer has a parent
		if (layer.parent) {

			// and that parent is selected
			if (layer.parent.selected) {

				// I don't need to look any further up the parent heirarchy
				// the original layer will be deselected
				foundSelectedParent = true;
				return;
			}

			// check if that layer has a selected parent
			hasSelectedParent(layer.parent)
		}
	}
		
		
	
	// main script
	


	// if a project is open
	if (proj) {

		// make sure a comp is selected
		var comp = app.project.activeItem;
		if (comp == null || !(comp instanceof CompItem)) {
			alert("You need to select some 3D layers first.");
			return;
		} else {
			// make sure at least one layer is selected
			var selectedLayers = comp.selectedLayers;
			if (selectedLayers.length == 0 ) {
				alert("No layers are selected.\rSelect a layer and this script will create a point light " +
				"for every 3D null selected.");
				return;
			} else {
                    
						// make sure at least one layer is selected
			var selectedLayers = comp.selectedLayers;
			for ( p=0 ; p<selectedLayers.length; p++ ) 
                if(!selectedLayers[p].threeDLayer){
				alert("Layer '" + selectedLayers[p].name + "' is not a 3D null object.");
				return;

                
			} else {
	
				

		
		// make sure at least one layer is selected
		var selectedLayers = comp.selectedLayers;
			
		for ( p=0 ; p<selectedLayers.length; p++ ) 
                
		if(!selectedLayers[p].threeDLayer){
		
		alert("Layer '" + selectedLayers[p].name + "' is not a 3D layer.");
		return;
                
			
		
		} else {
					var lightPrefix = prompt("Light Prefix", "A");
				
			// make sure at least one layer is selected
			var selectedLayers = comp.selectedLayers;
			for ( r = 0 ; r < selectedLayers.length; r++ ) 
                if(!selectedLayers[r].nullLayer){
				alert("Layer '" + selectedLayers[r].name + "' is not a null object.");
				return;
				

                
			} else {



                            
    // Import the "light" project
    var lightProjName = "LightTypes.aep";
    var impOpt = new ImportOptions(File(lightProjName)); // same folder as the script
    proj.importFile(impOpt);

    // Retrieve the comp that contains the light layers
    var k, lightComp;
    for (k = 1; k <= proj.numItems; k++)
    {
    if (proj.item(k).name == lightProjName)
    {
    lightComp = proj.item(k).item(1); // assuming the comp is the first item
    break;
    }
    }
    if (lightComp)
    {
    
    // Retrieve light layers    
    var parallelLight = lightComp.layer(1);
    var spotLight = lightComp.layer(2);
    var origPointLight = lightComp.layer(3);
    var ambientLight = lightComp.layer(4);
    

    
    // Add point light to the active comp

    var myPointLight = origPointLight.copyToComp(comp);
    
    // Delete imported stuff
    proj.item(k).remove();

    }
app.beginUndoGroup("Delete pointLight");

				var foundSelectedParent = false;
				// loop through each selected layer, checking a higher parent isn't also selected
				for (var j = 0; j < selectedLayers.length; j++) {
					foundSelectedParent = false;
					hasSelectedParent(selectedLayers[j])
					if (foundSelectedParent) {
						//alert("deselecting layer " + selectedLayers[j].name);
						selectedLayers[j].selected = false;
					}
				}

				selectedLayers = comp.selectedLayers;

				// loop through each selected layer in the comp
				for(var j = 0; j < selectedLayers.length; j++) {

					// use dupeIt function on this comp/layer
					var dup_layer = dupeIt(comp, selectedLayers[j]);

					//alert(dup_layer.name);
                    
				
						}
			app.project.activeItem.layer("pointLight").remove();
			}
					}
					
				}
			}	
		}
		
	}
app.endUndoGroup();
	}
	df_AddPointLightsToNullObjects()
}
Attachments
df_Add_Point_Lights_to_Null_Objects_v1.15.zip
Here is the script with the required After Effects project file that needs to be in the same folder as the script.
(6.25 KiB) Downloaded 932 times
dfred
Posts: 29
Joined: July 23rd, 2010, 11:49 pm

That first script is a mess. I just wrote a much cleaner version where the Undo actually works. I'll post it as soon as I do some more testing.
User avatar
lloydalvarez
Enhancement master
Posts: 460
Joined: June 17th, 2004, 9:27 am
Location: New York City, NY
Contact:

NAB wrote a pretty clever script to add lights to selected layers. The cleverness is how it gets around the lack of light control in the scripting api: http://www.motionboutique.tv/en/researc ... -designers

-Lloyd
Post Reply