Скрипт для сброса масштаба Smart Object до 100%

Я пытаюсь сделать скрипт, который будет брать элемент на слое и восстанавливать его размер до 100%.

Это то, что у меня есть, но по какой-то причине он не работает со смарт-объектами. Я что-то пропустил?

try {
  var doc = app.activeDocument;

  var layers = doc.artLayers;

  var size = dialog();
  
  for (var i = 0; i < doc.artLayers.length -1; i++) {

    var activeLayer = doc.artLayers.getByName(doc.artLayers[i].name);

    var orUnits = app.preferences.rulerUnits;

    app.preferences.rulerUnits = Units.PERCENT;

    activeLayer.resize(size, size, AnchorPosition.MIDDLECENTER);

    app.preferences.rulerUnits = orUnits;

  }


} catch (e) {
   alert( e );
}


function dialog() {

  // Dialog box
  var myWindow = new Window("dialog", "Resize Each Layer");

  // Keeps things inline
  myWindow.orientation = "row";

  // Informational text
  myWindow.add("statictext", undefined, "New size ( percentage ):");

  // This is the box where the size is inserted
  var myText = myWindow.add("edittext", undefined, "");
  myText.characters = 5;
  myText.active = true;

  // Ok
  myWindow.add("button", undefined, "OK");
  if (myWindow.show() == 1) return myText.text;

} 

Он не работает всякий раз, когда я пытаюсь запустить его, и вообще ничего не делает со смарт-объектами.

введите описание изображения здесь

1 ответ

Единственный известный мне способ сброса масштаба смарт-объекта - это замена текущего смарт-слоя исходным временным файлом psb (справочным файлом). Для этого сначала нужно найти смарт-объект fileReference (имя временного файла psb, он будет находиться во временной папке, вы найдете его в дескрипторе действия слоя), затем поместите его в свой документ (используя File > Place Embedded), поместите его в координаты исходного слоя и затем удалите оригинальный слой. Вот алгоритм:

var originalLayer = activeDocument.activeLayer,
    bounds = activeDocument.activeLayer.bounds,
    smartObjectName = getFileReference() //get file reference here

placeLayer(Folder.temp + "/" + smartObjectName) //function to place layer with path to layer as an argument
centerLayerBasedOnBounds(bounds)
originalLayer.remove()

layer.resize() - относительное изменение размера, а не абсолютное, поэтому, если вы скажете ему изменить размер на 100%, это ничего не изменит - вы говорите ему изменить размер до его текущего размера. Вам нужно знать текущую шкалу, чтобы сделать это таким образом (что я не думаю, что выставлено).

Я не думаю, что есть какой-либо способ сбросить масштаб смарт-объекта с помощью сценария или записанного действия. Смарт-объекты не очень хорошо поддерживаются API Photoshop...

Адаптировав код, который я нашел здесь, я смог получить немасштабированные размеры активного слоя с помощью ActionReference; https://community.adobe.com/t5/photoshop/how-can-i-capture-a-smart-object-s-original-dimension-via-scripts/td-p/9679328?page=1

// works on active layer
function getUnscaledLayerDimensions() {
  var ref = new ActionReference();

  ref.putEnumerated(
    charIDToTypeID("Lyr "),
    charIDToTypeID("Ordn"),
    charIDToTypeID("Trgt")
  );

  var obj = executeActionGet(ref).getObjectValue(
    stringIDToTypeID("smartObjectMore")
  );

  var _tmp = obj.getObjectValue(stringIDToTypeID("size"));

  return {
    width: _tmp.getDouble(stringIDToTypeID("width")),
    height: _tmp.getDouble(stringIDToTypeID("height")),
  };
}

Затем вы можете использовать эти размеры с границами слоя для resize() до 100%.

Сначала пара вещей... Я минимально подправил ваш сценарий, чтобы заставить его что-то делать, однако, в зависимости от того, что вы хотите, он все еще может быть неадекватным. Вы говорите, что хотите "сбросить масштаб Smart Object до 100%". Подход, который вы используете, не делает этого. То, что вы (почти) выполнили, - это сценарий, который изменяет слои на экране в процентах от их текущего размера. Предполагая, что это то, что вы намерены, все хорошо.

Далее, одна из причин, по которой ваш код не работал, это то, что вы ссылаетесь layer в строке 8. Вы никогда (из кода, который вы опубликовали) не создавали переменную с именем layer это означает, что компилятор понятия не имеет, что делать с этим кодом. На самом деле, просто удалив два оператора if в начале вашего кода, он запустится.

Вот "рабочий" код:

#target photoshop
try {
  var doc = app.activeDocument;

  var layers = doc.artLayers;

  var size = dialog();

  var defaultRulerUnits = app.preferences.rulerUnits;
  app.preferences.rulerUnits = Units.PERCENT;


  for (var i = 0; i < doc.artLayers.length -1; i++) {

    var activeLayer = doc.artLayers.getByName(doc.artLayers[i].name);

    var orUnits = app.preferences.rulerUnits;

    app.preferences.rulerUnits = Units.PERCENT;

    activeLayer.resize(size, size, AnchorPosition.MIDDLECENTER);

    app.preferences.rulerUnits = orUnits;

  }


} catch (e) {
  // alert( e );
}


function dialog() {

  // Dialog box...
  var myWindow = new Window("dialog", "Resize Each Layer");

  // Keeps things inline
  myWindow.orientation = "row";

  // Informational text
  myWindow.add("statictext", undefined, "New size ( percentage ):");

  // This is the box where the size is inserted
  var myText = myWindow.add("edittext", undefined, "");
  myText.characters = 5;
  myText.active = true;

  // Ok....
  myWindow.add("button", undefined, "OK");
  if (myWindow.show() == 1) return myText.text;

} 

Кроме того, этот код в настоящее время не проверяет тип слоя, поэтому могут возникнуть проблемы. Ваш следующий лучший шаг к учету этого, вероятно, заключался бы в добавлении проверки слоя ВНУТРИ вашего цикла for, чтобы ваш скрипт проверял слой внутри вашего layers массив.

Я также добавил doc.artLayers.length -1 в ваш цикл for, чтобы он не пытался изменить размер фонового слоя. Вы должны удалить это "-1"Как только вы добавите проверку слоя. Дайте мне знать, если я могу уточнить для вас что-нибудь.

Другие вопросы по тегам