Copy link to clipboard
Copied
How to change the angle of a gradient layer without changing anything else?
When I try it myself my whole gradient turns black.
To add to the above, you can not just set the angle. If you want to use other existing settings you need to get them from the layer. The code in that other thread shows one way to get them.
But if you do not need the existing values for any other reason you can get the descriptor for the layer, make a duplicate of it with all the settings and just overwrite the ones you want to change.
This is one way to just change the angle while keeping the other existing settings.
...// helper function for working
Copy link to clipboard
Copied
Check out this thread:
Copy link to clipboard
Copied
How exactly could I use this?
Copy link to clipboard
Copied
First determine the current values then use them with the changes you want.
Copy link to clipboard
Copied
A warning: Mike Hale has used »typeIDToStringID« a couple of times, probably to improve clearness.
If you feed the information back into Action Manager code (recorded with ScriptingListener.plugin) it might be easier to switch the those instances to »typeIDToCharID«.
And to handle varying numbers of Color and Transparency Stops for-clauses based on the length of someObjectName.colorStops and someObjectName.transStops may have to be included.
Copy link to clipboard
Copied
If you want to add to the current gradient angle you could use Mike Hale’s code and instead of »45« use something like this (the function is lifted from Mike’s code).
var newAngle = getGradientAngle()+10;
function getGradientAngle(){
if(app.documents.length==0 || app.activeDocument.activeLayer.kind != LayerKind.GRADIENTFILL ) return;
var ref = new ActionReference();
ref.putEnumerated( charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
var desc = executeActionGet(ref).getList(charIDToTypeID("Adjs")).getObjectValue(0);
if(desc.hasKey(charIDToTypeID("Angl"))) theAngle = desc.getDouble(charIDToTypeID("Angl"));
return theAngle;
};
Copy link to clipboard
Copied
I think it would be a good thing to add a range check to newAngle. The GUI only uses -180 to 180. Not sure what Photoshop would do with values outside that range, say 200.
Also as the setGradientAdjustmentAngle() function already get the settings from the layer you could save time and code lines by extending that function instead of getting the settings twice. Maybe add an optional increment argument.
Copy link to clipboard
Copied
Good points.
Copy link to clipboard
Copied
To add to the above, you can not just set the angle. If you want to use other existing settings you need to get them from the layer. The code in that other thread shows one way to get them.
But if you do not need the existing values for any other reason you can get the descriptor for the layer, make a duplicate of it with all the settings and just overwrite the ones you want to change.
This is one way to just change the angle while keeping the other existing settings.
// helper function for working with descriptors
function getProperty( psClass, psKey, index ){// integer:Class, integer:key
var ref = new ActionReference();
if( psKey != undefined ) ref.putProperty( charIDToTypeID( "Prpr" ), psKey );
if(index != undefined ){
ref.putIndex( psClass, index );
}else{
ref.putEnumerated( psClass , charIDToTypeID( "Ordn" ), charIDToTypeID( "Trgt" ) );
}
try{
var desc = executeActionGet(ref);
}catch(e){ return; }// return on error
if(desc.count == 0) return;// return undefined if property doesn't exists
var dataType = desc.getType(psKey);
switch(dataType){// not all types supported - returns undefined if not supported
case DescValueType.INTEGERTYPE:
return desc.getInteger(psKey);
break;
case DescValueType.ALIASTYPE:
return desc.getPath(psKey);
break;
case DescValueType.BOOLEANTYPE:
return desc.getBoolean(psKey);
break;
case DescValueType.BOOLEANTYPE:
return desc.getBoolean(psKey);
break;
case DescValueType.UNITDOUBLE:
return desc.getUnitDoubleValue(psKey);
break;
case DescValueType.STRINGTYPE:
return desc.getString(psKey);
break;
case DescValueType.OBJECTTYPE:
return desc.getObjectValue(psKey);
break;
case DescValueType.LISTTYPE:
return desc.getList(psKey);
break;
case DescValueType.ENUMERATEDTYPE:
return desc.getEnumerationValue(psKey);
break;
}
};
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 setGradientAdjustmentAngle( angle ) {
var adjustmentDesc = getProperty( charIDToTypeID("Lyr "), charIDToTypeID( 'Adjs' ) ).getObjectValue(0);
var newAdjustmentDesc = duplicateDescriptor( adjustmentDesc );
newAdjustmentDesc.putUnitDouble( charIDToTypeID('Angl'), charIDToTypeID('#Ang'), angle );
var desc = new ActionDescriptor();
var ref = new ActionReference();
ref.putEnumerated( stringIDToTypeID('contentLayer'), charIDToTypeID('Ordn'), charIDToTypeID('Trgt') );
desc.putReference( charIDToTypeID('null'), ref );
desc.putObject( charIDToTypeID('T '), stringIDToTypeID('gradientLayer'), newAdjustmentDesc);
executeAction( charIDToTypeID('setd'), desc, DialogModes.NO );
};
var newAngle = 45;
setGradientAdjustmentAngle( newAngle );
Copy link to clipboard
Copied
Did you include the »Align with layer« setting?
Edit: Excuse me, I see your new code is very much different from the one in the old thread.
Copy link to clipboard
Copied
Weren't we expecting barely average code from Mike, were we?
Tomorrow morning I'll spend a happy hour dribbling over descriptors helper functions - localizeDescriptor is paramount in ActionManager fetish. Hat off!
Davide
www.davidebarranca.com
Copy link to clipboard
Copied
I get an error on line 108: charIDToTypeID is not a function. What am I doing wrong?
NVM FIXED IT
Find more inspiration, events, and resources on the new Adobe Community
Explore Now