Skip to main content
Inspiring
August 7, 2017
Answered

How to re-Link every Displace on smart objects to target file

  • August 7, 2017
  • 7 replies
  • 3052 views

Hi all,

I have no idea where to start so here it is,

I would like to know if it is possible to script a function that relinks every instance of a 'Displace' effects in smart objects,

that comes linked to a file with a complete path to:

option A: a relative path (the same folder as the psd for instance, or a sub folder from it's location)

or

option B: a new path.

I am creating templates and a soon as i move them to another computer it becomes a problem.

When it's 1 or 2 you can rapidly link them by manualy double clicking the effects and choosing the new target file position,

but if you have a lot more this becomes quite an issue.

If anyone has an idea how to go about this, i would really appreciate.

Thanks,

Romeu

This topic has been closed for replies.
Correct answer romeuromeo

So i ha finaly got it working with the help of a friend,

my mistake was to add another loop inside the recursive loop,

any way here it is if some one needs it or parts of it:

#target photoshop

var dlg = new Window('dialog','seleciona o ficheiro de displace');

var file = new File() 

dlg.getFile = dlg.add('button',undefined,'ficheiro'); 

 

dlg.getFile.onClick = function(){ 

    file = file.openDlg('seleciona o ficheiro de displace'); 

    if(file.exists){dlg.close()} 

    } 

dlg.show()

var doc = activeDocument;

var horizon = dialogValorDiplace();

var testeCaminho = file

loopreplace(doc);

function loopreplace(gp){

for(var i = 0;i<gp.layers.length;i++) {

        doc.activeLayer = gp.layers

        if(doc.activeLayer.typename=='LayerSet'){

          loopreplace (gp.layers);

        } 

        else{ 

          try{

            //doc.activeLayer = gp.layers;

            displaceSettings ( horizon, testeCaminho );  

                   }

             catch(e){}

        }

    

}

}

function displaceSettings ( hori, testeCaminho ){ 

var idsetd = charIDToTypeID( "setd" );   

    var desc3067 = new ActionDescriptor();   

    var idnull = charIDToTypeID( "null" );   

        var ref1517 = new ActionReference();   

        var idfilterFX = stringIDToTypeID( "filterFX" );   

        ref1517.putIndex( idfilterFX, 1 );   

        var idLyr = charIDToTypeID( "Lyr " );   

        var idOrdn = charIDToTypeID( "Ordn" );   

        var idTrgt = charIDToTypeID( "Trgt" );   

        ref1517.putEnumerated( idLyr, idOrdn, idTrgt );   

    desc3067.putReference( idnull, ref1517 );   

    var idfilterFX = stringIDToTypeID( "filterFX" );   

        var desc3068 = new ActionDescriptor();   

        var idFltr = charIDToTypeID( "Fltr" );   

            var desc3069 = new ActionDescriptor();   

            var idHrzS = charIDToTypeID( "HrzS" );   

            desc3069.putInteger( idHrzS, hori );   

            var idVrtS = charIDToTypeID( "VrtS" );   

            desc3069.putInteger( idVrtS, hori );   

            var idDspM = charIDToTypeID( "DspM" );   

            var idDspM = charIDToTypeID( "DspM" );   

            var idStrF = charIDToTypeID( "StrF" );   

            desc3069.putEnumerated( idDspM, idDspM, idStrF );   

            var idUndA = charIDToTypeID( "UndA" );   

            var idUndA = charIDToTypeID( "UndA" );   

            var idRptE = charIDToTypeID( "RptE" );   

            desc3069.putEnumerated( idUndA, idUndA, idRptE );   

            var idDspF = charIDToTypeID( "DspF" );   

            desc3069.putPath( idDspF, new File( testeCaminho ) );   

        var idDspl = charIDToTypeID( "Dspl" );   

        desc3068.putObject( idFltr, idDspl, desc3069 );   

    var idfilterFX = stringIDToTypeID( "filterFX" );   

    desc3067.putObject( idfilterFX, idfilterFX, desc3068 );   

executeAction( idsetd, desc3067, DialogModes.NO ); 

}

function dialogValorDiplace() {

  var myWindow = new Window ("dialog", "valor Displace (default -35)");

  myWindow.orientation = "row";

  myWindow.add ("statictext", undefined, "valor");

  var myText = myWindow.add ("edittext", undefined, "");

  myText.characters = 30;

  myText.active = true;

   myWindow.add ("button", undefined, "OK");

  if (myWindow.show () == 1) return myText.text;

  }

cheers,

Romeu

7 replies

romeuromeoAuthorCorrect answer
Inspiring
August 29, 2017

So i ha finaly got it working with the help of a friend,

my mistake was to add another loop inside the recursive loop,

any way here it is if some one needs it or parts of it:

#target photoshop

var dlg = new Window('dialog','seleciona o ficheiro de displace');

var file = new File() 

dlg.getFile = dlg.add('button',undefined,'ficheiro'); 

 

dlg.getFile.onClick = function(){ 

    file = file.openDlg('seleciona o ficheiro de displace'); 

    if(file.exists){dlg.close()} 

    } 

dlg.show()

var doc = activeDocument;

var horizon = dialogValorDiplace();

var testeCaminho = file

loopreplace(doc);

function loopreplace(gp){

for(var i = 0;i<gp.layers.length;i++) {

        doc.activeLayer = gp.layers

        if(doc.activeLayer.typename=='LayerSet'){

          loopreplace (gp.layers);

        } 

        else{ 

          try{

            //doc.activeLayer = gp.layers;

            displaceSettings ( horizon, testeCaminho );  

                   }

             catch(e){}

        }

    

}

}

function displaceSettings ( hori, testeCaminho ){ 

var idsetd = charIDToTypeID( "setd" );   

    var desc3067 = new ActionDescriptor();   

    var idnull = charIDToTypeID( "null" );   

        var ref1517 = new ActionReference();   

        var idfilterFX = stringIDToTypeID( "filterFX" );   

        ref1517.putIndex( idfilterFX, 1 );   

        var idLyr = charIDToTypeID( "Lyr " );   

        var idOrdn = charIDToTypeID( "Ordn" );   

        var idTrgt = charIDToTypeID( "Trgt" );   

        ref1517.putEnumerated( idLyr, idOrdn, idTrgt );   

    desc3067.putReference( idnull, ref1517 );   

    var idfilterFX = stringIDToTypeID( "filterFX" );   

        var desc3068 = new ActionDescriptor();   

        var idFltr = charIDToTypeID( "Fltr" );   

            var desc3069 = new ActionDescriptor();   

            var idHrzS = charIDToTypeID( "HrzS" );   

            desc3069.putInteger( idHrzS, hori );   

            var idVrtS = charIDToTypeID( "VrtS" );   

            desc3069.putInteger( idVrtS, hori );   

            var idDspM = charIDToTypeID( "DspM" );   

            var idDspM = charIDToTypeID( "DspM" );   

            var idStrF = charIDToTypeID( "StrF" );   

            desc3069.putEnumerated( idDspM, idDspM, idStrF );   

            var idUndA = charIDToTypeID( "UndA" );   

            var idUndA = charIDToTypeID( "UndA" );   

            var idRptE = charIDToTypeID( "RptE" );   

            desc3069.putEnumerated( idUndA, idUndA, idRptE );   

            var idDspF = charIDToTypeID( "DspF" );   

            desc3069.putPath( idDspF, new File( testeCaminho ) );   

        var idDspl = charIDToTypeID( "Dspl" );   

        desc3068.putObject( idFltr, idDspl, desc3069 );   

    var idfilterFX = stringIDToTypeID( "filterFX" );   

    desc3067.putObject( idfilterFX, idfilterFX, desc3068 );   

executeAction( idsetd, desc3067, DialogModes.NO ); 

}

function dialogValorDiplace() {

  var myWindow = new Window ("dialog", "valor Displace (default -35)");

  myWindow.orientation = "row";

  myWindow.add ("statictext", undefined, "valor");

  var myText = myWindow.add ("edittext", undefined, "");

  myText.characters = 30;

  myText.active = true;

   myWindow.add ("button", undefined, "OK");

  if (myWindow.show () == 1) return myText.text;

  }

cheers,

Romeu

Chuck Uebele
Community Expert
Community Expert
August 9, 2017

For a simple UI to get a file, use something like this:

var dlg = new Window('dialog','get file');

var file = new File()

dlg.getFile = dlg.add('button',undefined,'Select a file');

dlg.getFile.onClick = function(){

    file = file.openDlg('Select a file');

    if(file.exists){dlg.close()}

    }

dlg.show()

Inspiring
August 9, 2017

Thanks for the tips,

i going to try to put these lines to good use

Inspiring
August 9, 2017

#target photoshop 

var doc = activeDocument;

checkLayer (doc);

function checkLayer(gp){ 

    for (var i=0;i<gp;i++){ 

        doc.activeLayer = gp.layers

        if(doc.activeLayer.typename=='LayerSet'){checkLayer (gp.layers)} 

        else{ 

            for(var i = 0;i<doc.layers.length;i++)

                try{doc.activeLayer = doc.layers;  

                replaceFilePath (); 

                    } 

                catch(e){}  

            }

        }

    }

 

 

function replaceFilePath (){ 

var idsetd = charIDToTypeID( "setd" );   

    var desc3067 = new ActionDescriptor();   

    var idnull = charIDToTypeID( "null" );   

        var ref1517 = new ActionReference();   

        var idfilterFX = stringIDToTypeID( "filterFX" );   

        ref1517.putIndex( idfilterFX, 1 );   

        var idLyr = charIDToTypeID( "Lyr " );   

        var idOrdn = charIDToTypeID( "Ordn" );   

        var idTrgt = charIDToTypeID( "Trgt" );   

        ref1517.putEnumerated( idLyr, idOrdn, idTrgt );   

    desc3067.putReference( idnull, ref1517 );   

    var idfilterFX = stringIDToTypeID( "filterFX" );   

        var desc3068 = new ActionDescriptor();   

        var idFltr = charIDToTypeID( "Fltr" );   

            var desc3069 = new ActionDescriptor();   

            var idHrzS = charIDToTypeID( "HrzS" );   

            desc3069.putInteger( idHrzS, -35 );   

            var idVrtS = charIDToTypeID( "VrtS" );   

            desc3069.putInteger( idVrtS, -35 );   

            var idDspM = charIDToTypeID( "DspM" );   

            var idDspM = charIDToTypeID( "DspM" );   

            var idStrF = charIDToTypeID( "StrF" );   

            desc3069.putEnumerated( idDspM, idDspM, idStrF );   

            var idUndA = charIDToTypeID( "UndA" );   

            var idUndA = charIDToTypeID( "UndA" );   

            var idRptE = charIDToTypeID( "RptE" );   

            desc3069.putEnumerated( idUndA, idUndA, idRptE );   

            var idDspF = charIDToTypeID( "DspF" );   

            desc3069.putPath( idDspF, new File( "C:\\Users\\romeu\\Desktop\\01\\DISP_new.psd" ) );   

        var idDspl = charIDToTypeID( "Dspl" );   

        desc3068.putObject( idFltr, idDspl, desc3069 );   

    var idfilterFX = stringIDToTypeID( "filterFX" );   

    desc3067.putObject( idfilterFX, idfilterFX, desc3068 );   

executeAction( idsetd, desc3067, DialogModes.NO ); 

so this is what i am trying but failing...

it doesn't seem to pass trough the first layer.

debuging it jumps straight from line 9 to 20, what i am doing wrong?

Jarda Bereza
Inspiring
August 8, 2017

You need to select next layers one by one with script and execute code.

Inspiring
August 8, 2017

Ok so i would need to make a loop something like this :

  1. var doc = activeDocument; 
  2.  
  3. for(var i = 0;i<doc.layers.length;i++){ 
  4.     doc.activeLayer = doc.layers
  5.     replaceFilePath (); 
  6.     } 

and define your scrip above as the replaceFilePath function ?

Inspiring
August 8, 2017

OK made it work,

the result final for people in the same scenario :

var doc = activeDocument;

for(var i = 0;i<doc.layers.length;i++){

    doc.activeLayer = doc.layers;

    replaceFilePath ();

    }

function replaceFilePath (){

var idsetd = charIDToTypeID( "setd" ); 

    var desc3067 = new ActionDescriptor(); 

    var idnull = charIDToTypeID( "null" ); 

        var ref1517 = new ActionReference(); 

        var idfilterFX = stringIDToTypeID( "filterFX" ); 

        ref1517.putIndex( idfilterFX, 1 ); 

        var idLyr = charIDToTypeID( "Lyr " ); 

        var idOrdn = charIDToTypeID( "Ordn" ); 

        var idTrgt = charIDToTypeID( "Trgt" ); 

        ref1517.putEnumerated( idLyr, idOrdn, idTrgt ); 

    desc3067.putReference( idnull, ref1517 ); 

    var idfilterFX = stringIDToTypeID( "filterFX" ); 

        var desc3068 = new ActionDescriptor(); 

        var idFltr = charIDToTypeID( "Fltr" ); 

            var desc3069 = new ActionDescriptor(); 

            var idHrzS = charIDToTypeID( "HrzS" ); 

            desc3069.putInteger( idHrzS, -35 ); 

            var idVrtS = charIDToTypeID( "VrtS" ); 

            desc3069.putInteger( idVrtS, -35 ); 

            var idDspM = charIDToTypeID( "DspM" ); 

            var idDspM = charIDToTypeID( "DspM" ); 

            var idStrF = charIDToTypeID( "StrF" ); 

            desc3069.putEnumerated( idDspM, idDspM, idStrF ); 

            var idUndA = charIDToTypeID( "UndA" ); 

            var idUndA = charIDToTypeID( "UndA" ); 

            var idRptE = charIDToTypeID( "RptE" ); 

            desc3069.putEnumerated( idUndA, idUndA, idRptE ); 

            var idDspF = charIDToTypeID( "DspF" ); 

            desc3069.putPath( idDspF, new File( "C:\\Users\\romeu\\Desktop\\teste\\02\\DISPL.psd" ) ); 

        var idDspl = charIDToTypeID( "Dspl" ); 

        desc3068.putObject( idFltr, idDspl, desc3069 ); 

    var idfilterFX = stringIDToTypeID( "filterFX" ); 

    desc3067.putObject( idfilterFX, idfilterFX, desc3068 ); 

executeAction( idsetd, desc3067, DialogModes.NO );

}

Jarda Bereza
Inspiring
August 8, 2017

ahaa... now I know what you mean. I didn't know about this filter. This is not compatible with cloud.

Looks like absolute path is stored inside SO.

"displaceFile": {

"stringID": "displaceFile",

"charID": "DspF",

"id": 1148416070,

"key": 4,

"type": "DescValueType.ALIASTYPE",

"value": "/d/desktop/file.psd",

"amCode": "var filter_DisplaceFile = desc.getObjectValue(stringIDToTypeID('filter')).getPath(stringIDToTypeID('displaceFile'))"

}

And you can use this code for change filter settings:

var idsetd = charIDToTypeID( "setd" );

    var desc3067 = new ActionDescriptor();

    var idnull = charIDToTypeID( "null" );

        var ref1517 = new ActionReference();

        var idfilterFX = stringIDToTypeID( "filterFX" );

        ref1517.putIndex( idfilterFX, 1 );

        var idLyr = charIDToTypeID( "Lyr " );

        var idOrdn = charIDToTypeID( "Ordn" );

        var idTrgt = charIDToTypeID( "Trgt" );

        ref1517.putEnumerated( idLyr, idOrdn, idTrgt );

    desc3067.putReference( idnull, ref1517 );

    var idfilterFX = stringIDToTypeID( "filterFX" );

        var desc3068 = new ActionDescriptor();

        var idFltr = charIDToTypeID( "Fltr" );

            var desc3069 = new ActionDescriptor();

            var idHrzS = charIDToTypeID( "HrzS" );

            desc3069.putInteger( idHrzS, 78 );

            var idVrtS = charIDToTypeID( "VrtS" );

            desc3069.putInteger( idVrtS, 54 );

            var idDspM = charIDToTypeID( "DspM" );

            var idDspM = charIDToTypeID( "DspM" );

            var idStrF = charIDToTypeID( "StrF" );

            desc3069.putEnumerated( idDspM, idDspM, idStrF );

            var idUndA = charIDToTypeID( "UndA" );

            var idUndA = charIDToTypeID( "UndA" );

            var idRptE = charIDToTypeID( "RptE" );

            desc3069.putEnumerated( idUndA, idUndA, idRptE );

            var idDspF = charIDToTypeID( "DspF" );

            desc3069.putPath( idDspF, new File( "D:\\desktop\\file2.psd" ) );

        var idDspl = charIDToTypeID( "Dspl" );

        desc3068.putObject( idFltr, idDspl, desc3069 );

    var idfilterFX = stringIDToTypeID( "filterFX" );

    desc3067.putObject( idfilterFX, idfilterFX, desc3068 );

executeAction( idsetd, desc3067, DialogModes.NO );

Inspiring
August 8, 2017

Hi again, that is fast writing

I'm really a newbie to this and so i don't really know how to run this code... can i save it to a .js file and run it trough the photoshop menu?

Jarda Bereza
Inspiring
August 8, 2017

The library has feature "relink to library". You can share library content and set read-only access for clients. Or embed all smart objects into document in single click. And embeded SO you can relink again into library if you have access and you want.

Inspiring
August 8, 2017

ok, so it looked great in theory but the displace filter always asks for a local path...

so i can't link it to a cloud file.

Chuck Uebele
Community Expert
Community Expert
August 8, 2017

If you create a  sv file when creating the displacement map, you could reference the file, but you would need to do that as you create the displacement map. It shouldn't be too hard to write a script that does that: bring up the displacement dialog, the save the Info to the cab, with a reference to the layer.

Jarda Bereza
Inspiring
August 8, 2017

Can you just use Cloud smart objects from library panel? This solves problem with multiple PCs. You don't need to solve where file is saved because SO contains something like absolute URL to the cloud and it copy automaticaly on the background files into temp folder when you want open this SO.

Inspiring
August 8, 2017

hi, thanks for the idea,

it could very well be a solution, since i never used the cloud based functionality of adobe products, i have to look into it deeper.

The one first issue i see is that i imagine would have to share my cloud files with my client so it works also on his computers/accounts.

Chuck Uebele
Community Expert
Community Expert
August 7, 2017

The trouble is that the displacement source is not stored in the Smart Object or file. You will get the same folder due to the OS remembering the last opened folder. So unless you save the sources, to a CSV file associated with your image file, I don't think you can do this.

Inspiring
August 8, 2017

Hi, thanks for the reply.

I looked into the csv file from here Creating data-driven graphics in Photoshop

and it looks a bit confusing for me,

but from what i understant you can link layers to a data base and influence the content of these from editing the csv file.

I have to look more into it but i don't think that i can link the displace effect this way.

is this correct?