// c2008 Adobe Systems, Inc. All rights reserved. // Written by Jeffrey Tranberry /* @@@BUILDINFO@@@ Flatten All Layer Effects.jsx 1.0.0.3 */ /* // BEGIN__HARVEST_EXCEPTION_ZSTRING $$$/JavaScripts/FlattenAllLayerEffects/Menu=Flatten All Layer Effects Flatten true 8a761c74-f362-4a1b-a3f7-e779ab319a08 >] >> >> ]]> // END__HARVEST_EXCEPTION_ZSTRING */ /* Description: This script flattens styles for all layers */ // enable double clicking from the // Macintosh Finder or the Windows Explorer #target photoshop // Make Photoshop the frontmost application app.bringToFront(); ///////////////////////// // SETUP ///////////////////////// // all the strings that need localized strFlattenAllLayerEffectsHistoryStepName = localize( "$$$/JavaScripts/FlattenAllLayerEffects/Menu=Flatten All Layer Effects" ); ///////////////////////// // MAIN ///////////////////////// // remember the document var doc = app.activeDocument; var myDialogMode = app.displayDialogs; // remember the dialog mode app.displayDialogs = DialogModes.NO; // set it to no to avoid dialogs // Create only one history state for the entire script doc.suspendHistory(strFlattenAllLayerEffectsHistoryStepName, "main()"); // Record the script in the Actions palette when recording an action try{ var playbackDescription = new ActionDescriptor; var playbackReference = new ActionReference; playbackReference.putEnumerated( charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") ); playbackDescription.putReference( charIDToTypeID("null"), playbackReference); app.playbackDisplayDialogs = DialogModes.NO; app.playbackParameters = playbackDescription; }catch(e) { ; // do nothing } app.displayDialogs = myDialogMode; ///////////////////////// // FUNCTIONS ///////////////////////// /////////////////////////////////////////////////////////////////////////////// // Function: main // Usage: container function to hold all the working code that generates history states // Input: Must have an open document // Return: /////////////////////////////////////////////////////////////////////////////// function main(){ var currentLayer = doc.activeLayer; // remember the selected layer var currentVisible = currentLayer.visible; // remember the visibility setting of the selected layer var currentSelectedLayers = getSelectedLayers(); // remember the selected layers if (currentSelectedLayers.length < 1){ var currentLayer = activeDocument.activeLayer; // remember the selected layers } // create an array and store all the art layers states var currentState = new Array; try{ getCurrentStateAlteringAsNeeded(activeDocument, currentState); }catch(e) { ; // do nothing } // Do some voodoo on the layer selection incase no layer is selected or multiple layers are selected try{ touchUpLayerSelection() }catch(e) { ; // do nothing } // create an array and store all the art layers in that array var allArtLayers = new Array; var allVisibleInfo = new Array; getAllArtLayers(doc, allArtLayers, allVisibleInfo); // Walk the layer stack for (var i = 0; i < allArtLayers.length; i++){ try{ doc.activeLayer = allArtLayers[i]; if (hasLayerStyle() == true){ // Only if the has a layer style flattenLayerStyles(); // Flatten the styles into the layer } }catch(e) { ; // do nothing } } // restore the current state of the layers try{ setCurrentState(currentState); }catch(e) { ; // do nothing } if (currentSelectedLayers.length > 1){ try{ setSelectedLayers(currentSelectedLayers); }catch(e) { ; // do nothing } } // restore the selected layer try{ doc.activeLayer = currentLayer; }catch(e) { ; // do nothing } // restore the visibility setting of the original layer try{ currentLayer.visible = currentVisible; }catch(e) { ; // do nothing } } /////////////////////////////////////////////////////////////////////////////// // Function: touchUpLayerSelection // Usage: deal with odd layer selections of no layer selected or multiple layers // Input: Must have an open document // Return: /////////////////////////////////////////////////////////////////////////////// function touchUpLayerSelection() { try{ // Select all Layers var idselectAllLayers = stringIDToTypeID( "selectAllLayers" ); var desc252 = new ActionDescriptor(); var idnull = charIDToTypeID( "null" ); var ref174 = new ActionReference(); var idLyr = charIDToTypeID( "Lyr " ); var idOrdn = charIDToTypeID( "Ordn" ); var idTrgt = charIDToTypeID( "Trgt" ); ref174.putEnumerated( idLyr, idOrdn, idTrgt ); desc252.putReference( idnull, ref174 ); executeAction( idselectAllLayers, desc252, DialogModes.NO ); // Select the previous layer var idslct = charIDToTypeID( "slct" ); var desc209 = new ActionDescriptor(); var idnull = charIDToTypeID( "null" ); var ref140 = new ActionReference(); var idLyr = charIDToTypeID( "Lyr " ); var idOrdn = charIDToTypeID( "Ordn" ); var idBack = charIDToTypeID( "Back" ); ref140.putEnumerated( idLyr, idOrdn, idBack ); desc209.putReference( idnull, ref140 ); var idMkVs = charIDToTypeID( "MkVs" ); desc209.putBoolean( idMkVs, false ); executeAction( idslct, desc209, DialogModes.NO ); }catch(e) { ; // do nothing } } /////////////////////////////////////////////////////////////////////////////// // Function: hasLayerStyle // Usage: see if there are styles present on a layer // Input: Must have an open document // Return: true if there is a layer style/effect present /////////////////////////////////////////////////////////////////////////////// function hasLayerStyle() { var hasLayerStyle = false; try { var ref = new ActionReference(); var keyLayerEffects = app.charIDToTypeID( 'Lefx' ); ref.putProperty( app.charIDToTypeID( 'Prpr' ), keyLayerEffects ); ref.putEnumerated( app.charIDToTypeID( 'Lyr ' ), app.charIDToTypeID( 'Ordn' ), app.charIDToTypeID( 'Trgt' ) ); var desc = executeActionGet( ref ); if ( desc.hasKey( keyLayerEffects ) ) { hasLayerStyle = true; } }catch(e) { hasLayerStyle = false; } return hasLayerStyle; } /////////////////////////////////////////////////////////////////////////////// // Function: flattenLayerStyles // Usage: worker function for flattening styles into the layer // Input: Must have an open document // Return: /////////////////////////////////////////////////////////////////////////////// function flattenLayerStyles() { try { var targetLayer = app.activeDocument.activeLayer.name; // Remember the layers name makeLayerBelow(targetLayer); // Make a new layer below with the target layers name selectPreviousLayer(); // select the previous layer mergeDown(); // and merge it down }catch(e) { ; // do nothing } } /////////////////////////////////////////////////////////////////////////////// // Function: makeLayerBelow // Usage: Creates a new layer below with the target layers name // Input: targetName. the name of the layer we want to create a new layer below // Return: /////////////////////////////////////////////////////////////////////////////// function makeLayerBelow(targetName) { try { var id829 = charIDToTypeID( "Mk " ); var desc169 = new ActionDescriptor(); var id830 = charIDToTypeID( "null" ); var ref105 = new ActionReference(); var id831 = charIDToTypeID( "Lyr " ); ref105.putClass( id831 ); desc169.putReference( id830, ref105 ); var id832 = stringIDToTypeID( "below" ); desc169.putBoolean( id832, true ); var id833 = charIDToTypeID( "Usng" ); var desc170 = new ActionDescriptor(); var id834 = charIDToTypeID( "Nm " ); desc170.putString( id834, targetName ); var id835 = charIDToTypeID( "Lyr " ); desc169.putObject( id833, id835, desc170 ); executeAction( id829, desc169, DialogModes.NO ); }catch(e) { ; // do nothing } } /////////////////////////////////////////////////////////////////////////////// // Function: selectPreviousLayer // Usage: Selects the layer above the selected layer, adding that layer to the current layer selection // Input: Must have an open document // Return: /////////////////////////////////////////////////////////////////////////////// function selectPreviousLayer() { try { var idslct = charIDToTypeID( "slct" ); var desc9 = new ActionDescriptor(); var idnull = charIDToTypeID( "null" ); var ref8 = new ActionReference(); var idLyr = charIDToTypeID( "Lyr " ); var idOrdn = charIDToTypeID( "Ordn" ); var idFrwr = charIDToTypeID( "Frwr" ); ref8.putEnumerated( idLyr, idOrdn, idFrwr ); desc9.putReference( idnull, ref8 ); var idselectionModifier = stringIDToTypeID( "selectionModifier" ); var idselectionModifierType = stringIDToTypeID( "selectionModifierType" ); var idaddToSelection = stringIDToTypeID( "addToSelection" ); desc9.putEnumerated( idselectionModifier, idselectionModifierType, idaddToSelection ); var idMkVs = charIDToTypeID( "MkVs" ); desc9.putBoolean( idMkVs, false ); executeAction( idslct, desc9, DialogModes.NO ); }catch(e) { ; // do nothing } } /////////////////////////////////////////////////////////////////////////////// // Function: mergeDown // Usage: merges the currently selected layers into one layer. If only one layer is selected it merges the current layer down into the layer below // Input: Must have an open document // Return: /////////////////////////////////////////////////////////////////////////////// function mergeDown() { try { var id828 = charIDToTypeID( "Mrg2" ); var desc168 = new ActionDescriptor(); executeAction( id828, desc168, DialogModes.NO ); }catch(e) { ; // do nothing } } /////////////////////////////////////////////////////////////////////////////// // Function: getAllArtLayers // Usage: get a reference to all artLayers in // the document, does recursion into groups // Input: obj, current object, document or layerSet // layersArray, place to put the resulting artLayers, // layersArray is both input and output // Return: /////////////////////////////////////////////////////////////////////////////// function getAllArtLayers(obj, layersArray, visibleArray) { for( var i = 0; i < obj.artLayers.length; i++) { layersArray.push(obj.artLayers[i]); //alert(obj.artLayers[i].name); visibleArray.push(obj.artLayers[i].visible); } for( var i = 0; i < obj.layerSets.length; i++) { getAllArtLayers(obj.layerSets[i], layersArray, visibleArray); // recursive call } } /////////////////////////////////////////////////////////////////////////////// // Function: getSelectedLayers // Usage: creates and array of the currently selected layers // Input: Must have an open document // Return: Array selectedLayers /////////////////////////////////////////////////////////////////////////////// function getSelectedLayers() { var selectedLayers = []; try { var backGroundCounter = activeDocument.artLayers[activeDocument.artLayers.length-1].isBackgroundLayer ? 0 : 1; var ref = new ActionReference(); var keyTargetLayers = app.stringIDToTypeID( 'targetLayers' ); ref.putProperty( app.charIDToTypeID( 'Prpr' ), keyTargetLayers ); ref.putEnumerated( app.charIDToTypeID( 'Dcmn' ), app.charIDToTypeID( 'Ordn' ), app.charIDToTypeID( 'Trgt' ) ); var desc = executeActionGet( ref ); if ( desc.hasKey( keyTargetLayers ) ) { var layersList = desc.getList( keyTargetLayers ); for ( var i = 0; i < layersList.count; i++) { var listRef = layersList.getReference( i ); selectedLayers.push( listRef.getIndex() + backGroundCounter ); } } } catch(e) { ; // do nothing } return selectedLayers; } /////////////////////////////////////////////////////////////////////////////// // Function: setSelectedLayers // Usage: Selects an array of layers // Input: Array selectedLayers // Return: /////////////////////////////////////////////////////////////////////////////// function setSelectedLayers( layerIndexesOrNames ) { // first select the first one setSelectedLayer( layerIndexesOrNames[0] ); // then add to the selection for ( var i = 1; i < layerIndexesOrNames.length; i++) { addSelectedLayer( layerIndexesOrNames[i] ); } } /////////////////////////////////////////////////////////////////////////////// // Function: setSelectedLayer // Usage: Selects the first layer // Input: Array selectedLayers // Return: /////////////////////////////////////////////////////////////////////////////// function setSelectedLayer( layerIndexOrName ) { try { var id239 = charIDToTypeID( "slct" ); var desc45 = new ActionDescriptor(); var id240 = charIDToTypeID( "null" ); var ref43 = new ActionReference(); var id241 = charIDToTypeID( "Lyr " ); if ( typeof layerIndexOrName == "number" ) { ref43.putIndex( id241, layerIndexOrName ); } else { ref43.putName( id241, layerIndexOrName ); } desc45.putReference( id240, ref43 ); var id242 = charIDToTypeID( "MkVs" ); desc45.putBoolean( id242, false ); executeAction( id239, desc45, DialogModes.NO ); } catch(e) { alert(e + ":" + e.line); // do nothing } } /////////////////////////////////////////////////////////////////////////////// // Function: addSelectedLayer // Usage: adds the rest of the layers in the array to the first layer // Input: Array selectedLayers // Return: /////////////////////////////////////////////////////////////////////////////// function addSelectedLayer( layerIndexOrName ) { try { var id243 = charIDToTypeID( "slct" ); var desc46 = new ActionDescriptor(); var id244 = charIDToTypeID( "null" ); var ref44 = new ActionReference(); var id245 = charIDToTypeID( "Lyr " ); if ( typeof layerIndexOrName == "number" ) { ref44.putIndex( id245, layerIndexOrName ); } else { ref44.putName( id245, layerIndexOrName ); } desc46.putReference( id244, ref44 ); var id246 = stringIDToTypeID( "selectionModifier" ); var id247 = stringIDToTypeID( "selectionModifierType" ); var id248 = stringIDToTypeID( "addToSelection" ); desc46.putEnumerated( id246, id247, id248 ); var id249 = charIDToTypeID( "MkVs" ); desc46.putBoolean( id249, false ); executeAction( id243, desc46, DialogModes.NO ); } catch(e) { alert(e + ":" + e.line); // do nothing } } /////////////////////////////////////////////////////////////////////////////// // Function: getCurrentStateAlteringAsNeeded // Usage: capture the current state of the layers in an array // Input: Must have an open document // Return: /////////////////////////////////////////////////////////////////////////////// function getCurrentStateAlteringAsNeeded( obj, stateArray ) { for( var i = 0; i < obj.artLayers.length; i++) { var oState = new ObjectState(obj.artLayers[i]); if ( oState.fixState( obj.artLayers[i], obj.artLayers[i].visible, true)) { obj.artLayers[i].visible = true; } if ( ! obj.artLayers[i].isBackgroundLayer) { if ( oState.fixState( obj.artLayers[i], obj.artLayers[i].allLocked, false)) { obj.artLayers[i].allLocked = false; } if ( oState.fixState( obj.artLayers[i], obj.artLayers[i].pixelsLocked, false)) { obj.artLayers[i].pixelsLocked = false; } if ( oState.fixState( obj.artLayers[i], obj.artLayers[i].positionLocked, false)) { obj.artLayers[i].positionLocked = false; } if ( oState.fixState( obj.artLayers[i], obj.artLayers[i].transparentPixelsLocked, false)) { obj.artLayers[i].transparentPixelsLocked = false; } } stateArray.push(oState); } for( var i = 0; i < obj.layerSets.length; i++ ) { var oState = new ObjectState(obj.layerSets[i]); if ( oState.fixState( obj.layerSets[i], obj.layerSets[i].visible, true)) { obj.layerSets[i].visible = true; } if ( oState.fixState( obj.layerSets[i], obj.layerSets[i].allLocked, false)) { obj.layerSets[i].allLocked = false; } stateArray.push(oState); getCurrentStateAlteringAsNeeded(obj.layerSets[i], stateArray); // recursive call } } /////////////////////////////////////////////////////////////////////////////// // Function: setCurrentState // Usage: set the state of the layers back to what what captured // Input: Must have an open document // Return: /////////////////////////////////////////////////////////////////////////////// function setCurrentState(stateArray) { for ( var i = 0; i < stateArray.length; i++ ) { try { if (stateArray[i].altered) { app.refresh(); activeDocument.activeLayer = stateArray[i].layer; stateArray[i].layer.allLocked = stateArray[i].allLocked; if ( ! stateArray[i].allLocked) { stateArray[i].layer.pixelsLocked = stateArray[i].pixelsLocked; stateArray[i].layer.positionLocked = stateArray[i].positionLocked; stateArray[i].layer.transparentPixelsLocked = stateArray[i].transparentPixelsLocked; } stateArray[i].layer.visible = stateArray[i].visible; } } catch(e) { alert(e + ":" + e.line); } } } /////////////////////////////////////////////////////////////////////////////// // Function: ObjectState // Usage: // Input: Must have an open document // Return: /////////////////////////////////////////////////////////////////////////////// function ObjectState( inObject ) { this.layer = inObject; this.visible = inObject.visible; this.allLocked = inObject.allLocked; this.pixelsLocked = inObject.pixelsLocked; this.positionLocked = inObject.positionLocked; this.transparentPixelsLocked = inObject.transparentPixelsLocked; this.altered = false; this.current = false; this.fixState = function (inObject, inState, wantState) { var wasAltered = false; if (inState != wantState) { if (this.current == false) { activeDocument.activeLayer = inObject; this.altered = true; this.current = true; } wasAltered = true; } return wasAltered; } } // End Flatten All Layer Effects.jsx