Copy link to clipboard
Copied
How to make this slider work to control the stroke size in a small dialog box.
I find here that script that controls the opacity of the layer. I made a basic modification, but I do not know how to make it work by controlling stylles. Thanks in advance!
var d= new Window('dialog','Stylle');
d.grpOpacity = d.add('panel', undefined,'Stroke');
d.grpOpacity.orientation = 'column';
d.grpOpacity.alignChildren = ['fill','top'];
d.grpOpacity.grpSlider = d.grpOpacity.add('group');
d.grpOpacity.grpSlider.spacing = 0;
d.grpOpacity.grpSlider.orientation = 'column';
d.grpOpacity.grpSlider.st1 = d.grpOpacity.grpSlider.add('statictext',undefined,'Structure-Size');
d.grpOpacity.grpSlider.st1.alignment = 'left';
d.grpOpacity.grpSlider.grpSlider = d.grpOpacity.grpSlider.add('group');
d.grpOpacity.grpSlider.grpSlider.alignChildren = ['left','center'];
d.grpOpacity.grpSlider.grpSlider.spacing = 0;
d.slOpacity = d.grpOpacity.grpSlider.grpSlider.add('slider',undefined,0,0,255);
d.slOpacity.value = app.activeDocument.activeLayer.opacity;
d.slOpacity.preferredSize.width =100;
d.etOpacityValue = d.grpOpacity.grpSlider.grpSlider.add('edittext');
d.etOpacityValue.text = Math.round(app.activeDocument.activeLayer.opacity);
d.etOpacityValue.addEventListener ('keydown', InitEditKeyboardHandler );
d.etOpacityValue.preferredSize.width = 20;
d.grpOpacity.grpSlider.grpSlider.stUnit = d.grpOpacity.grpSlider.grpSlider.add('statictext',undefined,' px');
d.grpOpacity.grpSlider.grpSt = d.grpOpacity.grpSlider.add('group');
d.grpOpacity.grpSlider.grpSt.orientation = 'row';
d.grpOpacity.grpSlider.grpSt.alignment = 'fill';
d.grpOpacity.grpSlider.grpSt.spacing = 0;
d.grpOpacity.grpSlider.grpSt.margins = [5,0,0,0];
d.grpOpacity.grpSlider.grpSt.grpLeft = d.grpOpacity.grpSlider.grpSt.add('group');
d.grpOpacity.grpSlider.grpSt.grpLeft.st1 = d.grpOpacity.grpSlider.grpSt.grpLeft.add('statictext',undefined,'0');
d.grpOpacity.grpSlider.grpSt.grpLeft.st1.alignment = ['left','center'];
d.grpOpacity.grpSlider.grpSt.grpLeft.st1.preferredSize.width = 70;
d.grpOpacity.grpSlider.grpSt.grpLeft.st3 = d.grpOpacity.grpSlider.grpSt.grpLeft.add('statictext',undefined,'255');
d.grpOpacity.grpSlider.grpSt.grpLeft.st3.alignment = ['right','center'];
d.grpOpacity.grpSlider.grpSt.grpLeft.st3.preferredSize.width = 40;
d.grpButtons = d.add('group');
d.grpButtons.alignment = "right";
d.grpButtons.btnCanel = d.grpButtons.add( 'button', undefined, 'Cancel', { name:'cancel' });
d.grpButtons.btnOK = d.grpButtons.add( 'button', undefined, 'Ok', { name:'ok' });
d.etOpacityValue.onChanging = d.etOpacityValue.onChange = function(){
var d = FindDialog(this);
d.slOpacity.value = Number(this.text);
d.slOpacity.onChange();
}
d.slOpacity.onChanging = d.slOpacity.onChange = function(){
var d = FindDialog(this);
d.etOpacityValue.text = Math.round(this.value);
}
d.slOpacity.onChange = function(){
var d = FindDialog(this);
app.activeDocument.activeLayer.opacity = Math.round(this.value);
app.refresh();
}
d.show();
function FindDialog( inItem ) {
var w = inItem;
while ( 'dialog' != w.type ) {
if ( undefined == w.parent ) {
w = null;
break;
}
w = w.parent;
}
return w;
};
function InitEditKeyboardHandler (event) {
try {
var keyIsOK = KeyIsNumeric(event) ||
KeyIsDelete(event) ||
KeyIsLRArrow(event) ||
KeyIsTabEnterEscape(event);
if (! keyIsOK) {
event.preventDefault();
app.beep();
}
}
catch (e) {
}
};
Here is the fix for the cancel button also it starts with the correct stroke size.
#target photoshop;
app.bringToFront();
main();
function main(){
var strokeSize = getStrokeSize();
if(strokeSize == null) return;
var d= new Window('dialog','Style');
d.grpOpacity = d.add('panel', undefined,'Stroke');
d.grpOpacity.orientation = 'column';
d.grpOpacity.alignChildren = ['fill','top'];
d.grpOpacity.grpSlider = d.grpOpacity.add('group');
d.grpOpacity.grpSlider.spacing = 0;
d.grpOpacity.grpSlide
...Copy link to clipboard
Copied
It is easy to change a layers opacity and there are many interfaces to do it. Short-cuts sliders and even in a layer style dialog.
a simple script line
app.activeDocument.activeLayer.fillOpacity = 50;
Also a Stroke layer style effect has many more attributed then just stoke size. And as far as I know the only DOM support for layer style is one that applies a named layer style in the style palette. With Action manager code you can add a layer style that spell out all layer effect desired. Including a stroke style effect. You can change the stroke effect by adding that spelled out style again with the stroke size changed. It will be applied without a preview. If I want a preview I would need to open the dialog which would open the whole layer style dialog with the stroke effect in focus it the layer style just add a stroke effect. There is not way you can edit or simulate editing the stroke with a preview. Layer style pixels only exists in the document composite rendered by Photoshop in the layer all there are are layer style effect settings. Stroke size is bold below. If you do a copy and paste of a layer with a layer style all you paste in are the layers pixels you get no layer style or layer style pixels.
// =======================================================
var idsetd = charIDToTypeID( "setd" );
var desc42 = new ActionDescriptor();
var idnull = charIDToTypeID( "null" );
var ref20 = new ActionReference();
var idPrpr = charIDToTypeID( "Prpr" );
var idLefx = charIDToTypeID( "Lefx" );
ref20.putProperty( idPrpr, idLefx );
var idLyr = charIDToTypeID( "Lyr " );
var idOrdn = charIDToTypeID( "Ordn" );
var idTrgt = charIDToTypeID( "Trgt" );
ref20.putEnumerated( idLyr, idOrdn, idTrgt );
desc42.putReference( idnull, ref20 );
var idT = charIDToTypeID( "T " );
var desc43 = new ActionDescriptor();
var idScl = charIDToTypeID( "Scl " );
var idPrc = charIDToTypeID( "#Prc" );
desc43.putUnitDouble( idScl, idPrc, 138.888889 );
var idFrFX = charIDToTypeID( "FrFX" );
var desc44 = new ActionDescriptor();
var idenab = charIDToTypeID( "enab" );
desc44.putBoolean( idenab, true );
var idpresent = stringIDToTypeID( "present" );
desc44.putBoolean( idpresent, true );
var idshowInDialog = stringIDToTypeID( "showInDialog" );
desc44.putBoolean( idshowInDialog, true );
var idStyl = charIDToTypeID( "Styl" );
var idFStl = charIDToTypeID( "FStl" );
var idInsF = charIDToTypeID( "InsF" );
desc44.putEnumerated( idStyl, idFStl, idInsF );
var idPntT = charIDToTypeID( "PntT" );
var idFrFl = charIDToTypeID( "FrFl" );
var idSClr = charIDToTypeID( "SClr" );
desc44.putEnumerated( idPntT, idFrFl, idSClr );
var idMd = charIDToTypeID( "Md " );
var idBlnM = charIDToTypeID( "BlnM" );
var idCBrn = charIDToTypeID( "CBrn" );
desc44.putEnumerated( idMd, idBlnM, idCBrn );
var idOpct = charIDToTypeID( "Opct" );
var idPrc = charIDToTypeID( "#Prc" );
desc44.putUnitDouble( idOpct, idPrc, 100.000000 );
var idSz = charIDToTypeID( "Sz " );
var idPxl = charIDToTypeID( "#Pxl" );
desc44.putUnitDouble( idSz, idPxl, 8.000000 );
var idClr = charIDToTypeID( "Clr " );
var desc45 = new ActionDescriptor();
var idRd = charIDToTypeID( "Rd " );
desc45.putDouble( idRd, 254.000000 );
var idGrn = charIDToTypeID( "Grn " );
desc45.putDouble( idGrn, 4.980545 );
var idBl = charIDToTypeID( "Bl " );
desc45.putDouble( idBl, 4.980545 );
var idRGBC = charIDToTypeID( "RGBC" );
desc44.putObject( idClr, idRGBC, desc45 );
var idoverprint = stringIDToTypeID( "overprint" );
desc44.putBoolean( idoverprint, true );
var idFrFX = charIDToTypeID( "FrFX" );
desc43.putObject( idFrFX, idFrFX, desc44 );
var idLefx = charIDToTypeID( "Lefx" );
desc42.putObject( idT, idLefx, desc43 );
executeAction( idsetd, desc42, DialogModes.NO );
Copy link to clipboard
Copied
This I know how to do JJMack I'm creating actions that add styles frames that will have the size controlled by the user through a small and practical dialog ... I just want to be able to increase or decrease the strock size by one Dialog box and avoid this annoying standard Photoshop dialog box. This script I posted was just to serve as a template, if someone with more connection can modify and make it work.
Copy link to clipboard
Copied
Using action manager code like I posted made into a function where size is made a peramater could be used. The stroke would be updated with each slider move. When the user see what the want they would ckick OK. If they click cancel the function could be used to reset the stroke to the default size. There is no preview the user sees the actual layer style.
Copy link to clipboard
Copied
Please try this.
#target photoshop;
app.bringToFront();
var d= new Window('dialog','Style');
d.grpOpacity = d.add('panel', undefined,'Stroke');
d.grpOpacity.orientation = 'column';
d.grpOpacity.alignChildren = ['fill','top'];
d.grpOpacity.grpSlider = d.grpOpacity.add('group');
d.grpOpacity.grpSlider.spacing = 0;
d.grpOpacity.grpSlider.orientation = 'column';
d.grpOpacity.grpSlider.st1 = d.grpOpacity.grpSlider.add('statictext',undefined,'Stroke-Size');
d.grpOpacity.grpSlider.st1.alignment = 'left';
d.grpOpacity.grpSlider.grpSlider = d.grpOpacity.grpSlider.add('group');
d.grpOpacity.grpSlider.grpSlider.alignChildren = ['left','center'];
d.grpOpacity.grpSlider.grpSlider.spacing = 0;
d.slOpacity = d.grpOpacity.grpSlider.grpSlider.add('slider',undefined,0,0,255);
d.slOpacity.value = app.activeDocument.activeLayer.opacity;
d.slOpacity.preferredSize.width =100;
d.etOpacityValue = d.grpOpacity.grpSlider.grpSlider.add('edittext');
d.etOpacityValue.text = Math.round(app.activeDocument.activeLayer.opacity);
d.etOpacityValue.addEventListener ('keydown', InitEditKeyboardHandler );
d.etOpacityValue.preferredSize.width = 50;
d.grpOpacity.grpSlider.grpSlider.stUnit = d.grpOpacity.grpSlider.grpSlider.add('statictext',undefined,' px');
d.grpOpacity.grpSlider.grpSt = d.grpOpacity.grpSlider.add('group');
d.grpOpacity.grpSlider.grpSt.orientation = 'row';
d.grpOpacity.grpSlider.grpSt.alignment = 'fill';
d.grpOpacity.grpSlider.grpSt.spacing = 0;
d.grpOpacity.grpSlider.grpSt.margins = [5,0,0,0];
d.grpOpacity.grpSlider.grpSt.grpLeft = d.grpOpacity.grpSlider.grpSt.add('group');
d.grpOpacity.grpSlider.grpSt.grpLeft.st1 = d.grpOpacity.grpSlider.grpSt.grpLeft.add('statictext',undefined,'0');
d.grpOpacity.grpSlider.grpSt.grpLeft.st1.alignment = ['left','center'];
d.grpOpacity.grpSlider.grpSt.grpLeft.st1.preferredSize.width = 70;
d.grpOpacity.grpSlider.grpSt.grpLeft.st3 = d.grpOpacity.grpSlider.grpSt.grpLeft.add('statictext',undefined,'255');
d.grpOpacity.grpSlider.grpSt.grpLeft.st3.alignment = ['right','center'];
d.grpOpacity.grpSlider.grpSt.grpLeft.st3.preferredSize.width = 40;
d.grpButtons = d.add('group');
d.grpButtons.alignment = "right";
d.grpButtons.btnCanel = d.grpButtons.add( 'button', undefined, 'Cancel', { name:'cancel' });
d.grpButtons.btnOK = d.grpButtons.add( 'button', undefined, 'Ok', { name:'ok' });
d.etOpacityValue.onChanging = d.etOpacityValue.onChange = function(){
var d = FindDialog(this);
d.slOpacity.value = Number(this.text);
d.slOpacity.onChange();
}
d.slOpacity.onChanging = d.slOpacity.onChange = function(){
var d = FindDialog(this);
d.etOpacityValue.text = Math.round(this.value);
}
d.slOpacity.onChange = function(){
var d = FindDialog(this);
setStrokeSize(Math.round(this.value));
// app.activeDocument.activeLayer.opacity = Math.round(this.value);
app.refresh();
}
d.show();
function FindDialog( inItem ) {
var w = inItem;
while ( 'dialog' != w.type ) {
if ( undefined == w.parent ) {
w = null;
break;
}
w = w.parent;
}
return w;
};
function KeyHasModifier (event) {
return event.shiftKey || event.ctrlKey || event.altKey || event.metaKey;
}
function KeyIsNumeric (event) {
return (event.keyName >= '0') && (event.keyName <= '9') && ! KeyHasModifier (event);
}
function KeyIsDelete (event) {
// Shift-delete is ok
return (event.keyName == 'Backspace') && ! (event.ctrlKey);
}
function KeyIsLRArrow (event) {
return ((event.keyName == 'Left') || (event.keyName == 'Right')) && ! (event.altKey || event.metaKey);
}
function KeyIsTabEnterEscape (event) {
return event.keyName == 'Tab' || event.keyName == 'Enter' || event.keyName == 'Escape';
}
function InitEditKeyboardHandler (event) {
try {
var keyIsOK = KeyIsNumeric(event) ||
KeyIsDelete(event) ||
KeyIsLRArrow(event) ||
KeyIsTabEnterEscape(event);
if (! keyIsOK) {
event.preventDefault();
app.beep();
}
}
catch (e) {
}
};
// helper function for working with descriptors by Mike Hale
function getActiveLayerProperty( psKey, psType ) {
var ref = new ActionReference();
ref.putProperty( charIDToTypeID( 'Prpr' ), psKey );
ref.putEnumerated( charIDToTypeID('Lyr '), charIDToTypeID('Ordn'), charIDToTypeID('Trgt') );
if( undefined == psType ){
return executeActionGet( ref ).getObjectValue( psKey );
}else{
return executeActionGet( ref );
}
};
function duplicateDescriptor( descriptor ) {
var newDescriptor = new ActionDescriptor;
newDescriptor.fromStream( descriptor.toStream() );
return newDescriptor;
};
function localizeDescriptor( desc ) {
var stream, pointer, zStringLength, zstring, localized_string, newZStringLength, previousStream, followingStream, newDesc;
stream = desc.toStream();
while( true ) {
pointer = stream.search(/TEXT....\x00\$\x00\$\x00\$/);
if( pointer === -1 ) {
break;
}
zStringLength = getLongFromStream( stream, pointer + 4 );
zstring = readUnicode( stream.substr( pointer + 8, ( zStringLength - 1 ) * 2) );
localized_string = ( localize( zstring ) ) + '\u0000';
newZStringLength = localized_string.length;
previousStream = stream.slice( 0, pointer);
followingStream = stream.slice( pointer + 8 + zStringLength * 2);
stream = previousStream.concat( 'TEXT', longToString( newZStringLength ), bytesToUnicode( localized_string ), followingStream );
}
newDesc = new ActionDescriptor();
newDesc.fromStream( stream );
return newDesc;
};
function getShortFromStream( stream, pointer ) {
var hi, low;
hi = stream.charCodeAt( pointer ) << 8 ;
low = stream.charCodeAt( pointer + 1 );
return hi + low;
};
function getLongFromStream( stream, pointer ) {
var hi, low;
hi = getShortFromStream( stream, pointer) << 16;
low = getShortFromStream( stream, pointer + 2);
return hi + low;
};
function readUnicode( unicode ) {
var string = "";
for( i = pointer = 0; pointer < unicode.length; i = pointer += 2) {
string +=String.fromCharCode( getShortFromStream( unicode, pointer ) );
}
return string;
};
function longToString( longInteger ) {
var string;
string = String.fromCharCode( longInteger >>> 24 );
string += String.fromCharCode( longInteger << 8 >>> 24 );
string += String.fromCharCode( longInteger << 16 >>> 24 );
string += String.fromCharCode( longInteger << 24 >>> 24 );
return string;
};
function bytesToUnicode( bytes ) {
var unicode = "", char_code, charIndex;
for( charIndex = 0; charIndex < bytes.length; charIndex ++ ) {
char_code = bytes.charCodeAt( charIndex );
unicode += String.fromCharCode(char_code >> 8 ) + String.fromCharCode( char_code & 0xff );
}
return unicode;
};
function setStrokeSize(Size ) {
var layerEffects, newLayerEffects, currentDesc, newDesc, colorDesc, newLayerEffects, layerDesc, targetDesc, setDesc;
layerEffects = getActiveLayerProperty( charIDToTypeID( 'Lefx' ) );
newLayerEffects = duplicateDescriptor( layerEffects );
currentDesc = layerEffects.getObjectValue( stringIDToTypeID( 'frameFX') );
newDesc = duplicateDescriptor( currentDesc );
newDesc.putUnitDouble( charIDToTypeID('Sz '), charIDToTypeID('#Pxl'), Size );
newLayerEffects.putObject( stringIDToTypeID( 'frameFX'), stringIDToTypeID( 'frameFX'), newDesc );
newLayerEffects = localizeDescriptor( newLayerEffects );
layerDesc = new ActionDescriptor();
layerDesc.putObject( charIDToTypeID('Lefx'), charIDToTypeID('lfxv'), newLayerEffects);
targetDesc = new ActionReference();
targetDesc.putEnumerated( charIDToTypeID('Lyr '), charIDToTypeID('Ordn'), charIDToTypeID('Trgt') );
setDesc = new ActionDescriptor;
setDesc.putObject( charIDToTypeID('T '), charIDToTypeID('Lyr '), layerDesc );
setDesc.putReference( charIDToTypeID('null' ), targetDesc );
executeAction(charIDToTypeID('setd'), setDesc, DialogModes.NO);
};
Copy link to clipboard
Copied
SuperMerlin
I tried it on my photoshop cc2014
does not work?
Copy link to clipboard
Copied
Ah well, not everything gets better with new versions
It works with CS6, a layer must be selected that has stroke layer effect.
Copy link to clipboard
Copied
It work fine with CC 2014. The current layer need to have a layer style that include a stroke effect to start with. The script retrieves the layer's layer styles effects and the slider will change the size each time you move it and release the mouse button. The Cancel part is not coded.
Copy link to clipboard
Copied
Thank you SuperMerlin . As always, you were great and genial, so you have a magician's name. I live dreaming of new updates, Adobe further decrease this "Layer Style" style box making it smaller allowing more space for the user.
Copy link to clipboard
Copied
tssee@imgof.com escreveu
SuperMerlin
I tried it on my photoshop cc2014
does not work?
I use the CC2017 version and it worked! Just the "Cancel" button that has a small bug ... What matters is that the "OK" Button fulfills its function well.
Copy link to clipboard
Copied
Here is the fix for the cancel button also it starts with the correct stroke size.
#target photoshop;
app.bringToFront();
main();
function main(){
var strokeSize = getStrokeSize();
if(strokeSize == null) return;
var d= new Window('dialog','Style');
d.grpOpacity = d.add('panel', undefined,'Stroke');
d.grpOpacity.orientation = 'column';
d.grpOpacity.alignChildren = ['fill','top'];
d.grpOpacity.grpSlider = d.grpOpacity.add('group');
d.grpOpacity.grpSlider.spacing = 0;
d.grpOpacity.grpSlider.orientation = 'column';
d.grpOpacity.grpSlider.st1 = d.grpOpacity.grpSlider.add('statictext',undefined,'Stroke-Size');
d.grpOpacity.grpSlider.st1.alignment = 'left';
d.grpOpacity.grpSlider.grpSlider = d.grpOpacity.grpSlider.add('group');
d.grpOpacity.grpSlider.grpSlider.alignChildren = ['left','center'];
d.grpOpacity.grpSlider.grpSlider.spacing = 0;
d.slOpacity = d.grpOpacity.grpSlider.grpSlider.add('slider',undefined,0,0,255);
d.slOpacity.value = strokeSize;
d.slOpacity.preferredSize.width =100;
d.etOpacityValue = d.grpOpacity.grpSlider.grpSlider.add('edittext');
d.etOpacityValue.text = strokeSize;
d.etOpacityValue.addEventListener ('keydown', InitEditKeyboardHandler );
d.etOpacityValue.preferredSize.width = 50;
d.grpOpacity.grpSlider.grpSlider.stUnit = d.grpOpacity.grpSlider.grpSlider.add('statictext',undefined,' px');
d.grpOpacity.grpSlider.grpSt = d.grpOpacity.grpSlider.add('group');
d.grpOpacity.grpSlider.grpSt.orientation = 'row';
d.grpOpacity.grpSlider.grpSt.alignment = 'fill';
d.grpOpacity.grpSlider.grpSt.spacing = 0;
d.grpOpacity.grpSlider.grpSt.margins = [5,0,0,0];
d.grpOpacity.grpSlider.grpSt.grpLeft = d.grpOpacity.grpSlider.grpSt.add('group');
d.grpOpacity.grpSlider.grpSt.grpLeft.st1 = d.grpOpacity.grpSlider.grpSt.grpLeft.add('statictext',undefined,'0');
d.grpOpacity.grpSlider.grpSt.grpLeft.st1.alignment = ['left','center'];
d.grpOpacity.grpSlider.grpSt.grpLeft.st1.preferredSize.width = 70;
d.grpOpacity.grpSlider.grpSt.grpLeft.st3 = d.grpOpacity.grpSlider.grpSt.grpLeft.add('statictext',undefined,'255');
d.grpOpacity.grpSlider.grpSt.grpLeft.st3.alignment = ['right','center'];
d.grpOpacity.grpSlider.grpSt.grpLeft.st3.preferredSize.width = 40;
d.grpButtons = d.add('group');
d.grpButtons.alignment = "right";
d.grpButtons.btnCanel = d.grpButtons.add( 'button', undefined, 'Cancel', { name:'cancel' });
d.grpButtons.btnOK = d.grpButtons.add( 'button', undefined, 'Ok', { name:'ok' });
d.etOpacityValue.onChanging = d.etOpacityValue.onChange = function(){
var d = FindDialog(this);
d.slOpacity.value = Number(this.text);
d.slOpacity.onChange();
}
d.slOpacity.onChanging = d.slOpacity.onChange = function(){
var d = FindDialog(this);
d.etOpacityValue.text = Math.round(this.value);
}
d.slOpacity.onChange = function(){
var d = FindDialog(this);
setStrokeSize(Math.round(this.value));
// app.activeDocument.activeLayer.opacity = Math.round(this.value);
app.refresh();
}
d.grpButtons.btnCanel.onClick=function(){
d.close(2);
setStrokeSize(strokeSize);
}
d.show();
function FindDialog( inItem ) {
var w = inItem;
while ( 'dialog' != w.type ) {
if ( undefined == w.parent ) {
w = null;
break;
}
w = w.parent;
}
return w;
};
function KeyHasModifier (event) {
return event.shiftKey || event.ctrlKey || event.altKey || event.metaKey;
}
function KeyIsNumeric (event) {
return (event.keyName >= '0') && (event.keyName <= '9') && ! KeyHasModifier (event);
}
function KeyIsDelete (event) {
// Shift-delete is ok
return (event.keyName == 'Backspace') && ! (event.ctrlKey);
}
function KeyIsLRArrow (event) {
return ((event.keyName == 'Left') || (event.keyName == 'Right')) && ! (event.altKey || event.metaKey);
}
function KeyIsTabEnterEscape (event) {
return event.keyName == 'Tab' || event.keyName == 'Enter' || event.keyName == 'Escape';
}
function InitEditKeyboardHandler (event) {
try {
var keyIsOK = KeyIsNumeric(event) ||
KeyIsDelete(event) ||
KeyIsLRArrow(event) ||
KeyIsTabEnterEscape(event);
if (! keyIsOK) {
event.preventDefault();
app.beep();
}
}
catch (e) {
}
};
};
// helper function for working with descriptors by Mike Hale
function getActiveLayerProperty( psKey, psType ) {
var ref = new ActionReference();
ref.putProperty( charIDToTypeID( 'Prpr' ), psKey );
ref.putEnumerated( charIDToTypeID('Lyr '), charIDToTypeID('Ordn'), charIDToTypeID('Trgt') );
if( undefined == psType ){
return executeActionGet( ref ).getObjectValue( psKey );
}else{
return executeActionGet( ref );
}
};
function duplicateDescriptor( descriptor ) {
var newDescriptor = new ActionDescriptor;
newDescriptor.fromStream( descriptor.toStream() );
return newDescriptor;
};
function localizeDescriptor( desc ) {
var stream, pointer, zStringLength, zstring, localized_string, newZStringLength, previousStream, followingStream, newDesc;
stream = desc.toStream();
while( true ) {
pointer = stream.search(/TEXT....\x00\$\x00\$\x00\$/);
if( pointer === -1 ) {
break;
}
zStringLength = getLongFromStream( stream, pointer + 4 );
zstring = readUnicode( stream.substr( pointer + 8, ( zStringLength - 1 ) * 2) );
localized_string = ( localize( zstring ) ) + '\u0000';
newZStringLength = localized_string.length;
previousStream = stream.slice( 0, pointer);
followingStream = stream.slice( pointer + 8 + zStringLength * 2);
stream = previousStream.concat( 'TEXT', longToString( newZStringLength ), bytesToUnicode( localized_string ), followingStream );
}
newDesc = new ActionDescriptor();
newDesc.fromStream( stream );
return newDesc;
};
function getShortFromStream( stream, pointer ) {
var hi, low;
hi = stream.charCodeAt( pointer ) << 8 ;
low = stream.charCodeAt( pointer + 1 );
return hi + low;
};
function getLongFromStream( stream, pointer ) {
var hi, low;
hi = getShortFromStream( stream, pointer) << 16;
low = getShortFromStream( stream, pointer + 2);
return hi + low;
};
function readUnicode( unicode ) {
var string = "";
for( i = pointer = 0; pointer < unicode.length; i = pointer += 2) {
string +=String.fromCharCode( getShortFromStream( unicode, pointer ) );
}
return string;
};
function longToString( longInteger ) {
var string;
string = String.fromCharCode( longInteger >>> 24 );
string += String.fromCharCode( longInteger << 8 >>> 24 );
string += String.fromCharCode( longInteger << 16 >>> 24 );
string += String.fromCharCode( longInteger << 24 >>> 24 );
return string;
};
function bytesToUnicode( bytes ) {
var unicode = "", char_code, charIndex;
for( charIndex = 0; charIndex < bytes.length; charIndex ++ ) {
char_code = bytes.charCodeAt( charIndex );
unicode += String.fromCharCode(char_code >> 8 ) + String.fromCharCode( char_code & 0xff );
}
return unicode;
};
function setStrokeSize(Size ) {
var layerEffects, newLayerEffects, currentDesc, newDesc, colorDesc, newLayerEffects, layerDesc, targetDesc, setDesc;
layerEffects = getActiveLayerProperty( charIDToTypeID( 'Lefx' ) );
newLayerEffects = duplicateDescriptor( layerEffects );
currentDesc = layerEffects.getObjectValue( stringIDToTypeID( 'frameFX') );
newDesc = duplicateDescriptor( currentDesc );
newDesc.putUnitDouble( charIDToTypeID('Sz '), charIDToTypeID('#Pxl'), Size );
newLayerEffects.putObject( stringIDToTypeID( 'frameFX'), stringIDToTypeID( 'frameFX'), newDesc );
newLayerEffects = localizeDescriptor( newLayerEffects );
layerDesc = new ActionDescriptor();
layerDesc.putObject( charIDToTypeID('Lefx'), charIDToTypeID('lfxv'), newLayerEffects);
targetDesc = new ActionReference();
targetDesc.putEnumerated( charIDToTypeID('Lyr '), charIDToTypeID('Ordn'), charIDToTypeID('Trgt') );
setDesc = new ActionDescriptor;
setDesc.putObject( charIDToTypeID('T '), charIDToTypeID('Lyr '), layerDesc );
setDesc.putReference( charIDToTypeID('null' ), targetDesc );
executeAction(charIDToTypeID('setd'), setDesc, DialogModes.NO);
};
function getStrokeSize(){
var ref = new ActionReference();
ref.putEnumerated( charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
var desc = executeActionGet(ref);
if(desc.hasKey(stringIDToTypeID( 'layerEffects' ))){
if(!desc.getBoolean (stringIDToTypeID( 'layerFXVisible'))) return undefined;
desc = desc.getObjectValue(stringIDToTypeID('layerEffects'));
if(!desc.hasKey(stringIDToTypeID( 'frameFX'))) return null;
desc = desc.getObjectValue(stringIDToTypeID('frameFX'));
return desc.getUnitDoubleValue (stringIDToTypeID( 'size' ));
}
return null;
};
Copy link to clipboard
Copied
Perfect SuperMerlin! I will be eternally grateful to you! Thank you one more time.
Copy link to clipboard
Copied
That restores your Super prefix magician or is wizard. I think I remember watching your farther MrWizard on TV that new invention my farther brought home when I was a boy.
It is also nice to see you leave Mike name in code he is missed RIP..
Copy link to clipboard
Copied
That's really cool, I was looking for something like that too. I did some tests here and realized that the Slider works well but if correctly position the mouse pointer over the slider arrow. I've found this script that shows you can get better and more precise control.
#target photoshop
function WinObject() {
// Long resource String for 'palette' Window
var windowResource = "palette { orientation: 'column', alignChildren: ['fill', 'top'], preferredSize:[300, 130], text: 'ScriptUI Window - palette', margins:15, sliderPanel: Panel { orientation: 'row', alignChildren: 'right', margins:15, text: ' PANEL ', st: StaticText { text: 'Value:' }, sl: Slider { minvalue: 1, maxvalue: 100, value: 30, size:[220,20] }, te: EditText { text: '30', characters: 5, justify: 'left'} } bottomGroup: Group{ cd: Checkbox { text:'Checkbox value', value: true }, cancelButton: Button { text: 'Cancel', properties:{name:'cancel'}, size: [120,24], alignment:['right', 'center'] }, applyButton: Button { text: 'Apply', properties:{name:'ok'}, size: [120,24], alignment:['right', 'center'] }, } }";
var win = new Window(windowResource);
win.bottomGroup.cancelButton.onClick = function() { win.close() };
win.bottomGroup.applyButton.onClick = function() { win.close() };
// Show the Window
win.show();
};
// String message for BridgeTalk
var message = WinObject.toString();
// construct an anonymous instance and add it to the string
message += "\nnew WinObject();"
// $.writeln(message); // check it in the ESTK Console, just in case
var bt = new BridgeTalk();
bt.target = "photoshop";
bt.body = message;
bt.send();
SuperMerlin, could a better control be based on this script? Would be great
Copy link to clipboard
Copied
I do not see any difference in the sliders except the one you like is displayed wider that is just a couple of setting in the dialog.
Is the length of the slider what make you state it more precise. Precise is what the input field is. Adding 100 to a couple of the width setting in SuperMerrlin dialog will make the slider wider precise is still the input field in both Dialog yours and his.
I have notice I can nudge the slider using the arrow keys and the stroke updates but the number in the input field is not updated.
I also seem to be able to hang CC 2015, CC 2015.5 and CC 2017 using this script and playing around with the slider input filed and arrow keys. I still use CC 2014 I have not been able to hang cc 2014 using this script.
I'm still testing CC 2014 for it is not that east the hand cc 2015, cc 2015.5 and cc 2017 but it is possible with this script.
Copy link to clipboard
Copied
It does seem smoother!
#target photoshop;
app.bringToFront();
if(documents.length) main();
function main(){
function WinObject() {
try{
var strokeSize = getStrokeSize();
if(strokeSize == null) return;
/*Resource String for 'palette' Window */
var windowResource = "palette {orientation: 'column',alignChildren: ['fill', 'top'],preferredSize:[300, 130],"+
"text: 'Set Stroke Effect Size',margins:15,sliderPanel: Panel {orientation: 'row',alignChildren: 'right',"+
"margins:15,text: ' Set Size ',st: StaticText { text: 'Value:' },sl: Slider{"+
"minvalue: 1, maxvalue: 255, value: 0, size:[220,20] }, te: EditText { text: '30', characters: 5, justify: 'left'}}"+
"bottomGroup: Group{cancelButton: Button {"+
"text: 'Cancel', properties:{name:'cancel'}, size: [120,24], alignment:['right', 'center'] },"+
"applyButton: Button { text: 'Apply', properties:{name:'ok'}, size: [120,24], alignment:['right', 'center'] },}}";
var win = new Window(windowResource);
win.sliderPanel.te.text=strokeSize;
win.sliderPanel.sl.value=strokeSize;
win.sliderPanel.te.onChanging = function(){
win.sliderPanel.sl.value = Number(win.sliderPanel.te.text);
setStrokeSize(win.sliderPanel.sl.value.toFixed(0));
}
win.sliderPanel.sl.onChanging = function(){
win.sliderPanel.te.text=win.sliderPanel.sl.value.toFixed(0);
setStrokeSize(Math.round(this.value));
}
win.bottomGroup.cancelButton.onClick = function() {
win.close(2);
setStrokeSize(strokeSize);
};
win.bottomGroup.applyButton.onClick = function() {
win.close(0);
setStrokeSize(win.sliderPanel.sl.value.toFixed(0));
};
// Show the Window
win.show();
// helper function for working with descriptors by Mike Hale
function getActiveLayerProperty( psKey, psType ) {
var ref = new ActionReference();
ref.putProperty( charIDToTypeID( 'Prpr' ), psKey );
ref.putEnumerated( charIDToTypeID('Lyr '), charIDToTypeID('Ordn'), charIDToTypeID('Trgt') );
if( undefined == psType ){
return executeActionGet( ref ).getObjectValue( psKey );
}else{
return executeActionGet( ref );
}
};
function duplicateDescriptor( descriptor ) {
var newDescriptor = new ActionDescriptor;
newDescriptor.fromStream( descriptor.toStream() );
return newDescriptor;
};
function localizeDescriptor( desc ) {
var stream, pointer, zStringLength, zstring, localized_string, newZStringLength, previousStream, followingStream, newDesc;
stream = desc.toStream();
while( true ) {
pointer = stream.search(/TEXT....\x00\$\x00\$\x00\$/);
if( pointer === -1 ) {
break;
}
zStringLength = getLongFromStream( stream, pointer + 4 );
zstring = readUnicode( stream.substr( pointer + 8, ( zStringLength - 1 ) * 2) );
localized_string = ( localize( zstring ) ) + '\u0000';
newZStringLength = localized_string.length;
previousStream = stream.slice( 0, pointer);
followingStream = stream.slice( pointer + 8 + zStringLength * 2);
stream = previousStream.concat( 'TEXT', longToString( newZStringLength ), bytesToUnicode( localized_string ), followingStream );
}
newDesc = new ActionDescriptor();
newDesc.fromStream( stream );
return newDesc;
};
function getShortFromStream( stream, pointer ) {
var hi, low;
hi = stream.charCodeAt( pointer ) << 8 ;
low = stream.charCodeAt( pointer + 1 );
return hi + low;
};
function getLongFromStream( stream, pointer ) {
var hi, low;
hi = getShortFromStream( stream, pointer) << 16;
low = getShortFromStream( stream, pointer + 2);
return hi + low;
};
function readUnicode( unicode ) {
var string = "";
for( i = pointer = 0; pointer < unicode.length; i = pointer += 2) {
string +=String.fromCharCode( getShortFromStream( unicode, pointer ) );
}
return string;
};
function longToString( longInteger ) {
var string;
string = String.fromCharCode( longInteger >>> 24 );
string += String.fromCharCode( longInteger << 8 >>> 24 );
string += String.fromCharCode( longInteger << 16 >>> 24 );
string += String.fromCharCode( longInteger << 24 >>> 24 );
return string;
};
function bytesToUnicode( bytes ) {
var unicode = "", char_code, charIndex;
for( charIndex = 0; charIndex < bytes.length; charIndex ++ ) {
char_code = bytes.charCodeAt( charIndex );
unicode += String.fromCharCode(char_code >> 8 ) + String.fromCharCode( char_code & 0xff );
}
return unicode;
};
function setStrokeSize(Size ) {
var layerEffects, newLayerEffects, currentDesc, newDesc, colorDesc, newLayerEffects, layerDesc, targetDesc, setDesc;
layerEffects = getActiveLayerProperty( charIDToTypeID( 'Lefx' ) );
newLayerEffects = duplicateDescriptor( layerEffects );
currentDesc = layerEffects.getObjectValue( stringIDToTypeID( 'frameFX') );
newDesc = duplicateDescriptor( currentDesc );
newDesc.putUnitDouble( charIDToTypeID('Sz '), charIDToTypeID('#Pxl'), Size );
newLayerEffects.putObject( stringIDToTypeID( 'frameFX'), stringIDToTypeID( 'frameFX'), newDesc );
newLayerEffects = localizeDescriptor( newLayerEffects );
layerDesc = new ActionDescriptor();
layerDesc.putObject( charIDToTypeID('Lefx'), charIDToTypeID('lfxv'), newLayerEffects);
targetDesc = new ActionReference();
targetDesc.putEnumerated( charIDToTypeID('Lyr '), charIDToTypeID('Ordn'), charIDToTypeID('Trgt') );
setDesc = new ActionDescriptor;
setDesc.putObject( charIDToTypeID('T '), charIDToTypeID('Lyr '), layerDesc );
setDesc.putReference( charIDToTypeID('null' ), targetDesc );
executeAction(charIDToTypeID('setd'), setDesc, DialogModes.NO);
};
function getStrokeSize(){
var ref = new ActionReference();
ref.putEnumerated( charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
var desc = executeActionGet(ref);
if(desc.hasKey(stringIDToTypeID( 'layerEffects' ))){
if(!desc.getBoolean (stringIDToTypeID( 'layerFXVisible'))) return undefined;
desc = desc.getObjectValue(stringIDToTypeID('layerEffects'));
if(!desc.hasKey(stringIDToTypeID( 'frameFX'))) return null;
desc = desc.getObjectValue(stringIDToTypeID('frameFX'));
return desc.getUnitDoubleValue (stringIDToTypeID( 'size' ));
}
return null;
};
}catch(e){alert(e + "\n" + e.line);}
};
// String message for BridgeTalk
var message = WinObject.toString();
// construct an anonymous instance and add it to the string
message += "\nnew WinObject();"
// $.writeln(message); // check it in the ESTK Console, just in case
var bt = new BridgeTalk();
bt.target = "photoshop";
bt.body = message;
bt.send();
};
Copy link to clipboard
Copied
Seeing the two examples here, I really noticed a difference in behavior, it slides smoother, I also had the sensation that the mouse arrow has a Snap linked to the slider indicator making it behave better than the standard Photoshop slider.
Copy link to clipboard
Copied
SuperMerlin, Your modification is 100% better now, Congratulations ...
Thank you very much!
Copy link to clipboard
Copied
So far I have not been able to hang CC 2015 and up with this version but I do notice some other strange thing. The arrow keys will move the slider but nothing is updated. If I type a number and have not first targeted the input field this script will change the layers opacity the old script does not. If I mover the slider with the arrow key and click apply the un-display moved value will be used to set the stroke at that point.. The two script seem to act differently if a I empty the input field and press enter. Nether acted as I expect them too.
Copy link to clipboard
Copied
This script is very good and very useful, Congratulations to those who had this brilliant idea and to the guy who made it funcinar: "SuperMerlin,". How many good ideas here! I'll leave my ideira here: A button with an option to alter the color of strock?
Copy link to clipboard
Copied
I would use CC 2014 that version of ScriptUI seems to work better than the newer versions of ScriptUI....
Copy link to clipboard
Copied
Impressive. Way over my abilities. However the cancel button should be removed. The script does not reset the stoke size to the initial size.