Copy/Paste Multiple Layer Styles Between Documents
-
bradatx
Copy/Paste Multiple Layer Styles Between Documents
I am wondering if it is possible to script the copy-and-pasting of a group of layer styles (really, just the blending mode and opacity) from one document to another document with identical layer names. If it would make it easier, the layer names always have the same prefix. Any suggestions?
-
Mike Hale
Copy/Paste Multiple Layer Styles Between Documents
It is be possible if there is only one given layer name in each document or the layer structure is the same.
It may be possible under other conditions if there is some other way to match the layers.
It may be possible under other conditions if there is some other way to match the layers.
-
bradatx
Copy/Paste Multiple Layer Styles Between Documents
Yes all the layers have the same names and there are only 12 or so of them. I just don't really know where to start. Would javascript be the way to go?
-
Mike Hale
Copy/Paste Multiple Layer Styles Between Documents
I think javascript is the way to go because it is cross-platform and the example I will post will be javascript. But before I do that I need to know if there are layer sets in either document and what layer settings you would like synched.
-
bradatx
Copy/Paste Multiple Layer Styles Between Documents
I only need the blending mode and opacity to be synced. There are layer sets within the document, but the layers I need synced aren't split up in different layer sets if that is what you are asking.
The way I was thinking of doing it (and I don't know much about coding) was to have the script "get" a list of all the layer names in document1, filter them by the text string "vray" --which is the prefix that all the layers I need synced start with (e.g. vray.reflection, vray.diffuse, vray.alpha, etc.) -- and then store all those attributes. Then, in document2, "get" a list of all the layer names again, but find the layers whose names match the ones that are stored. Then just paste all those attributes into the identically named layers (e.g. copy the blending mode and opacity of the layer "vray.reflection" from document1 and paste it into the blending mode and opacity of layer "vray.reflection" in document2).
I hope that makes sense...
The way I was thinking of doing it (and I don't know much about coding) was to have the script "get" a list of all the layer names in document1, filter them by the text string "vray" --which is the prefix that all the layers I need synced start with (e.g. vray.reflection, vray.diffuse, vray.alpha, etc.) -- and then store all those attributes. Then, in document2, "get" a list of all the layer names again, but find the layers whose names match the ones that are stored. Then just paste all those attributes into the identically named layers (e.g. copy the blending mode and opacity of the layer "vray.reflection" from document1 and paste it into the blending mode and opacity of layer "vray.reflection" in document2).
I hope that makes sense...
-
Mike Hale
Copy/Paste Multiple Layer Styles Between Documents
Give this a try. It works on a sample docs I made to test.
Code: Select all/*
This is quick and dirty so don't use it as an example of how things should be done.
But because it is only access commom layer properties and the name are unique
I can let the try/catch block do way with most of the test that should be used.
With no documents open, open the document you want to copy the setting to.
Then open the document you want to copy the setting from;
It will scan the layer stack looking for layer with 'vray.' in the name.
If it finds a match it get the setting.
When it's finished the search it switches to the first doc
Finds the layer by name from the matchedNames array
and then updates the layer. I used Action Manger to do all the layer work
so it shouldn't be too slow
*/
var mask = /vray\./;
var matchedLayerSettings = [];
var foundNames = [];
searchLayers( mask );
app.activeDocument = app.documents[0];
for(var l=0;l<foundNames.length;l++){
try{
var matchingLayerIndex = getLayerIndexByName(foundNames[l]);
upDateLayer( matchingLayerIndex, matchedLayerSettings[l].mode, matchedLayerSettings[l].opacity );
}catch(e){}
}
function searchLayers( mask ){
var layerCount = getNumberOfLayer();
for(l=0;l<layerCount;l++){
var setting = getLayerSetting( l, mask );
if(setting != -1){
matchedLayerSettings.push(setting);
foundNames.push(setting.name);
}
}
};
function getLayerSetting( idx, mask ){
var layerDesc = getLayerDescriptorByIndex( idx );
try{
var layerName = layerDesc.getString(charIDToTypeID( "Nm " ));
if(layerName.match(mask)==null) return -1;
var setting = {};
setting.name = layerDesc.getString(charIDToTypeID( "Nm " ));
setting.opacity = Math.round(layerDesc.getInteger(charIDToTypeID( "Opct" ))/255*100);
setting.mode = layerDesc.getEnumerationValue(charIDToTypeID( "Md " ));
setting.toString = function(){return this.name;};
return setting;
}catch(e){ return -1;}
}
function getLayerDescriptorByIndex( idx ) {
try{
var ref = new ActionReference();
ref.putIndex( charIDToTypeID( "Lyr " ), idx );
return executeActionGet(ref);
}catch(e){}
};
function getNumberOfLayer(){
var ref = new ActionReference();
ref.putEnumerated( charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
var desc = executeActionGet(ref);
var numberOfLayer = desc.getInteger(charIDToTypeID("NmbL"));
return numberOfLayer;
};
function getLayerIndexByName(name) {
var ref = new ActionReference();
ref.putProperty( charIDToTypeID("Prpr") , charIDToTypeID( "ItmI" ));
ref.putName( charIDToTypeID( "Lyr " ), name );
return executeActionGet(ref).getInteger(charIDToTypeID( "ItmI" ));;
};
function upDateLayer( idx, mode, opct ) {
var desc = new ActionDescriptor();
var ref = new ActionReference();
ref.putIndex( charIDToTypeID("Lyr "), idx );
desc.putReference( charIDToTypeID( "null" ), ref );
var desc1 = new ActionDescriptor();
desc1.putEnumerated( charIDToTypeID( "Md " ), charIDToTypeID( "BlnM" ), mode );
desc1.putUnitDouble( charIDToTypeID('Opct'), charIDToTypeID('#Prc'), opct );
desc.putObject( charIDToTypeID( "T " ), charIDToTypeID( "Lyr " ), desc1 );
executeAction( charIDToTypeID( "setd" ), desc, DialogModes.NO );
};
Code: Select all/*
This is quick and dirty so don't use it as an example of how things should be done.
But because it is only access commom layer properties and the name are unique
I can let the try/catch block do way with most of the test that should be used.
With no documents open, open the document you want to copy the setting to.
Then open the document you want to copy the setting from;
It will scan the layer stack looking for layer with 'vray.' in the name.
If it finds a match it get the setting.
When it's finished the search it switches to the first doc
Finds the layer by name from the matchedNames array
and then updates the layer. I used Action Manger to do all the layer work
so it shouldn't be too slow
*/
var mask = /vray\./;
var matchedLayerSettings = [];
var foundNames = [];
searchLayers( mask );
app.activeDocument = app.documents[0];
for(var l=0;l<foundNames.length;l++){
try{
var matchingLayerIndex = getLayerIndexByName(foundNames[l]);
upDateLayer( matchingLayerIndex, matchedLayerSettings[l].mode, matchedLayerSettings[l].opacity );
}catch(e){}
}
function searchLayers( mask ){
var layerCount = getNumberOfLayer();
for(l=0;l<layerCount;l++){
var setting = getLayerSetting( l, mask );
if(setting != -1){
matchedLayerSettings.push(setting);
foundNames.push(setting.name);
}
}
};
function getLayerSetting( idx, mask ){
var layerDesc = getLayerDescriptorByIndex( idx );
try{
var layerName = layerDesc.getString(charIDToTypeID( "Nm " ));
if(layerName.match(mask)==null) return -1;
var setting = {};
setting.name = layerDesc.getString(charIDToTypeID( "Nm " ));
setting.opacity = Math.round(layerDesc.getInteger(charIDToTypeID( "Opct" ))/255*100);
setting.mode = layerDesc.getEnumerationValue(charIDToTypeID( "Md " ));
setting.toString = function(){return this.name;};
return setting;
}catch(e){ return -1;}
}
function getLayerDescriptorByIndex( idx ) {
try{
var ref = new ActionReference();
ref.putIndex( charIDToTypeID( "Lyr " ), idx );
return executeActionGet(ref);
}catch(e){}
};
function getNumberOfLayer(){
var ref = new ActionReference();
ref.putEnumerated( charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
var desc = executeActionGet(ref);
var numberOfLayer = desc.getInteger(charIDToTypeID("NmbL"));
return numberOfLayer;
};
function getLayerIndexByName(name) {
var ref = new ActionReference();
ref.putProperty( charIDToTypeID("Prpr") , charIDToTypeID( "ItmI" ));
ref.putName( charIDToTypeID( "Lyr " ), name );
return executeActionGet(ref).getInteger(charIDToTypeID( "ItmI" ));;
};
function upDateLayer( idx, mode, opct ) {
var desc = new ActionDescriptor();
var ref = new ActionReference();
ref.putIndex( charIDToTypeID("Lyr "), idx );
desc.putReference( charIDToTypeID( "null" ), ref );
var desc1 = new ActionDescriptor();
desc1.putEnumerated( charIDToTypeID( "Md " ), charIDToTypeID( "BlnM" ), mode );
desc1.putUnitDouble( charIDToTypeID('Opct'), charIDToTypeID('#Prc'), opct );
desc.putObject( charIDToTypeID( "T " ), charIDToTypeID( "Lyr " ), desc1 );
executeAction( charIDToTypeID( "setd" ), desc, DialogModes.NO );
};
-
bradatx
Copy/Paste Multiple Layer Styles Between Documents
Hmm, it doesn't seem to be working. I created a layers vray.red and vray.blue and tried to copy the blending modes and opacities from one document to the other and it didn't work...
-
Mike Hale
Copy/Paste Multiple Layer Styles Between Documents
That is strange, it does for me. Just to be clear, the document you want to copy the settings to needs to be the first opened document. By that I mean only it is open. The document you want to copy the setting from must be the active or highlighted document. If you need to do this a lot and we can get it working for you with these conditions I can change the script so you can choose the to/from documents.
If you will supply me with two samples that are not working for you I will test them here. They don't have to be big. You can down-sample to a very small size and fill the layers with white if you don't/can't share the contents( I just need the layer structure ). Then zip it up an upload the zip in the upload section if you need a way to get them to me.
Mike
If you will supply me with two samples that are not working for you I will test them here. They don't have to be big. You can down-sample to a very small size and fill the layers with white if you don't/can't share the contents( I just need the layer structure ). Then zip it up an upload the zip in the upload section if you need a way to get them to me.
Mike
-
bradatx
Copy/Paste Multiple Layer Styles Between Documents
It won't let me upload the file because it says the maximum allowed size is 256KB. Here's the link to a dropbox instead: https://www.dropbox.com/s/bszjjh4wllnyn ... sh_PSD.zip ... sh_PSD.zip. The files include the original and the second with the suffix "finish" which is the completed version. This is a stripped down, but fairly representative example of what I do on a regular basis. I''ll have a finished document, then have a new "raw" version submitted to me and I'll have to go through and reproduce the photoshop edits I just completed. Going through and copying the blending modes and opacity is just a headache which is why I would love to find a way to script it.
I was incorrect as to the prefix string as well -- it's "VRay" without a dot (not "vray."). During my testing however, I changed the layer names to "vray." so I don't think that is why the script isn't working for me. I really appreciate your help.
I really appreciate all your help and your time.
I was incorrect as to the prefix string as well -- it's "VRay" without a dot (not "vray."). During my testing however, I changed the layer names to "vray." so I don't think that is why the script isn't working for me. I really appreciate your help.
I really appreciate all your help and your time.
-
Mike Hale
Copy/Paste Multiple Layer Styles Between Documents
I took you too literally so it only matches 'vray.' anywhere in the layer name.
Replace the search mask line with...Code: Select allvar mask = /^vray.*/i;That will match any layer that starts with 'vray' in any combination. Note the dot in RegEx means followed by anything including the 'dot', not just the 'dot' char.
Yes, there is a size limit on uploads. That is why I suggested you down size to something very small. 1x1 pixel document(s) would have been fine in this case because I only needed the layer structure and I can see if the script is working by looking at the layers panel.
Replace the search mask line with...Code: Select allvar mask = /^vray.*/i;That will match any layer that starts with 'vray' in any combination. Note the dot in RegEx means followed by anything including the 'dot', not just the 'dot' char.
Yes, there is a size limit on uploads. That is why I suggested you down size to something very small. 1x1 pixel document(s) would have been fine in this case because I only needed the layer structure and I can see if the script is working by looking at the layers panel.