Vytvoření inteligentního objektu

lekce 9.

Automatizování úloh v Adobe Photoshop

Pomocí skriptovacího jazyka JavaScript

Cíl lekce

V této lekci vytvořím ze skupiny vrstev dané uživatelem jeden inteligentní objekt v prostředí programu Adobe Photoshop. Z prvu zajistím výjimky, které mohou nastat, jako je neotevřený soubor, či existence samotného setu vrstev. Uživatel má navíc možnost pomocí dialogového okna, zadat název skupiny vrstev, kterou chce převést do inteligentního objektu.

images/lekce_7puvodni.png

Původní obrázek - obrázek 9.1

images/lekce_7TextDialog.png

Obrázek při zadávání do dialogového okna - obrázek 9.2

images/lekce_7Objekt.png

Výsledný inteligentní objekt z vrstev - obrázek 9.3


Využité třídy v této lekci

  • Application: pro práci s atributy dokumentu.
  • Konstanty: konstanty typu event ID.
  • Descriptor: pro popis prováděných akcí z rozhraní.
  • Reference: pro zadání objektů do ActionDescriptoru.

Vytvoření dialogu a dosazeních do proměnných

Metoda prompt() slouží jako dialogové okno s dvěma tlačítky a textboxem do kterého uživatel může psát vstup. Samotná metoda poté vrací textový řetězec a v případě prázdného pole hodnotu null. První parametr této metody je zpráva hlavního okna, druhý parametr označuje již předvyplněné textové pole (v tomto případě nastavím první nalezenou skupinu vrstev, aby bylo zřejmé, co má uživatel zadat) a třetí je titulek dialogového okna. Celou metodu poté přiřadím pomocí rovná se do proměnné jelikož metoda má návratovou hodnotu. Obsah lze jednoduše vypsat pomocí alertu, pro kontrolu, že přiřazení je funkční viz. zakomentovaný příkaz. Dále do proměnné layerSet přiřadím všechny skupiny vrstev v aktivním dokumentu.

var placeHolder;
//získej skupiny vrstev
var layerSet = activeDocument.layerSets;
//pokud existuje více skupin vrstev než 0, nastavím předvyplněné pole prvním
//názvem nalezené skupiny vrstev
layerSet.length > 0 ? placeHolder = layerSet[0].name : placeHolder = "";

//přiřaď název skupiny vrstev
var nameOfSet = prompt("Zadejte název skupiny, který chcete převést na inteligentní objekt.\n" +
        "Zamčené vrstvy budou odemčeny a také převedeny.", placeHolder, "Výběr");
				

Vytvoření funkce pro kontrolu skupiny vrstev

Jako další krok potřebuji zkontrolovat zda-li uživatelem zadaný název existuje jako skupina vrstev a skript se může provést. To ošetřím jednoduchou podmínkou (if), kde v cyklu procházím všechny skupiny vrstev a ptám se, či se jejich atribut name rovná názvu, který zadal uživatel. V tomto případě se jedná o funkci s dvěmi parametry, tedy skupinou a názvem. Při nalezení zadané skupiny vrstev je třeba také ošetřit zamčení jednotlivých vrstev. Proto si nalezenou skupinu vrstev vložím jako parametr do funkce, která ošetří zamčení vrstev.


function doesExist(layerSet, nameSet){
    for (var i = 0; i < layerSet.length; i++) {
        if(layerSet[i].name == nameSet){
            unlockLayers(layerSet[i]);
            return true;
        }
    }
    return false;
}
				

Ošetření zamčených vrstev

Na ošetření zamčených vrstev vytvořím jednuduchou funkci unlockLayers, která bude mít za úkol jen projít vrstvy skupiny a nastavit atribut allLocked, na false. Nastavaním tohoto atribut odemknu vrstvu a vyhnu se případným výjimkám u dalšího zpracování vrstev. Tuto funkci ilustruje zdrojový kód níže.


function unlockLayers(layerSet){
    for (var i = 0; i < layerSet.artLayers.length; i++) {
         // odemčení vrstvy
         layerSet.artLayers[i].allLocked = false;
    }
}
				

Event ID

Podobně jako v předchozích lekcích potřebuji získat event ID z konstantových typů a to ze znakové a řetězové konstanty. Opět jako předešlé lekce, konstanty je možné najít v rozšířených příručkách společnosti Adobe, či na githubovém portálu zde. Ve zkratce ke konstantám, které použiji: "Lyr " značí vrstvy, slct značí výběrovou událost, null prázdná hodnota.


//event ID ze znaku
function getIdFromChar(param) { 
    return app.charIDToTypeID(param) 
}  
//event ID z řetězce       
function getIdFromString(param) { 
    return app.stringIDToTypeID(param) 
};

Funkce pro vybrání vrstev ve skupině

Nyní vytvořím objekty ActionDescriptor, ActionReference. Poté do reference pomocí metody putName() vložím vrstvy v dané skupině a referenci vložím do objektu ActionDescriptor. Na první místo, kde se očekává klíč vložím null a jako hodnotu vložím vytvořenou referenci. Poté pomocí metody executeAction() provedu výběr bez dialogových oken sestupně. Tuto metodu obalím blokem try{ }catch (){} v případě výskytu chyby.

function doSelection(nameSet){
    var descriptor = new ActionDescriptor();
    var reference = new ActionReference();
    reference.putName( getIdFromChar( "Lyr " ), nameSet);
    descriptor.putReference( getIdFromChar( "null" ), reference );
    try{ 
        executeAction( getIdFromChar( "slct" ), desc, DialogModes.NO ); 
    }catch(exception){
        return false;
    }
}

Využití funkcí a sestavení kódu

Nyní mám vše co potřebuji a mohu funkce zakomponovat do celého skriptu. Nejprvě je ale ještě třeba ošetřit, pokud uživatel zadal nějaký název a nenechal pole prázdné a také jestli skupina vrstev s názvem zadaným od uživatele existuje. Dalším důležitým krokem je nastavit aktivní vrstvu, toto je velice zásadní, protože v případě že uživatel má vybranou nějakou jinou vrstvu než zadal, vytvořil by se inteligetní objekt z této vrstvy a nikoliv z vrstvy zadané. Poté provedu výběr, ten se díky akce transformuje do vrstvy, kterou zviditelním a poté zavolám akci pro vytvoření inteligentního objektu. Poslední část skriptu ilustruje kód níže.

if(doesExist(layerSet, nameOfSet)){
        //nastavení activní vrstvy v dokumentu na uživateli vybranou vrstvu
        app.activeDocument.activeLayer = app.activeDocument.layerSets.getByName(nameOfSet)

        //vyber vrstvy
        doSelection(nameOfSet);
        //zviditelni aktivní vrstvu
        activeDocument.activeLayer.visible = true;
        //proveď akci pro převedení do chytrého objektu
        executeAction(getIdFromString('newPlacedLayer'), undefined, DialogModes.NO);

        //informuji o dokočení skriptu
        alert("Skript ukončen!")
}else if(nameOfSet.length > 0 && !doesExist(layerSet, nameOfSet)){
        alert ("Zadaná skupina neexistuje!", "Upozornění");
}

Výsledný zdrojový kód

//je otevřený dokument?
if (isDocumentOpened()) {
    var placeHolder;
    //získej skupiny vrstev
    var layerSet = activeDocument.layerSets;
    //pokud existuje více skupin vrstev než 0, nastavím předvyplněné pole prvním
    //názvem nalezené skupiny vrstev
    layerSet.length > 0 ? placeHolder = layerSet[0].name : placeHolder = "";

    //přiřaď název skupiny vrstev
    var nameOfSet = prompt("Zadejte název skupiny, který chcete převést na inteligentní objekt.\n" +
        "Zamčené vrstvy budou odemčeny a také převedeny.", placeHolder, "Výběr");

    if (nameOfSet !== null) {
        //existuje tato skupina?
        if (doesExist(layerSet, nameOfSet)) {
            app.activeDocument.activeLayer = app.activeDocument.layerSets.getByName(nameOfSet)

            //vyber vrstvy
            doSelection(nameOfSet);
            //zviditelni aktivní vrstvu
            activeDocument.activeLayer.visible = true;
            //proveď akci pro převedení do chytrého objektu
            executeAction(getIdFromString('newPlacedLayer'), undefined, DialogModes.NO);

            alert("Skript ukončen!")
        } else if (nameOfSet.length > 0 && !doesExist(layerSet, nameOfSet)) {
            alert("Zadaná skupina neexistuje!", "Upozornění");
        }
    }
} else {
    alert("Žádný dokument není otevřený.", "Varování");
}


function isDocumentOpened() {
    return documents.length;
}


function doesExist(layerSet, nameSet) {
    for (var i = 0; i < layerSet.length; i++) {
        if (layerSet[i].name == nameSet) {
            unlockLayers(layerSet[i]);
            return true;
        }
    }
    return false;
}

function unlockLayers(layerSet) {
    for (var i = 0; i < layerSet.artLayers.length; i++) {
        // odemčení vrstvy
        layerSet.artLayers[i].allLocked = false;
    }
}

function doSelection(nameSet) {
    var descriptor = new ActionDescriptor();
    var reference = new ActionReference();
    reference.putName(getIdFromChar("Lyr "), nameSet);
    descriptor.putReference(getIdFromChar("null"), reference);
    try {
        executeAction(getIdFromChar("slct"), desc, DialogModes.NO);
    } catch (exception) {
        return false;
    }
}

function getIdFromChar(param) {
    return app.charIDToTypeID(param)
}

function getIdFromString(param) {
    return app.stringIDToTypeID(param)
}