Історія однієї одержимості або як я писав календарний скрипт для Photoshop

Все почалося з ідеї, схематично змальованої на крихітному аркуші паперу. Захотілося написати скрипт, який міг у Photoshop створити календар на заданий рік. Спочатку потрібно було отримати річний календар розміром 6 на 2 місяців. Однак у процесі розробки «хотілки» зростали, і в результаті список бажаних налаштувань став таким, щоб користувач міг поставити:
Чому мені важливо зробити це у Photoshop? Просто я хочу створювати барвисті календарі з фотографіями чи ілюстраціями, докладаючи якнайменше зусиль і, по можливості, працюючи саме в цій програмі. Можливо, хтось також хоче.
Інструментарій
Отже, план є, настав час вибрати необхідні інструменти.
Скриптові інструменти від XBYTOR.Насправді я використовував лише один його інструмент, ActionToJavascript.jsx, але він був дуже корисний. Цей скрипт працює так — на вході задається записана операція у Photoshop (це на кшталт макросів у MS Office, тільки закритий формат), а на виході виходить файл з розширенням *.jsx, в якому прописана функція, що виконує за допомогою низькорівневих команд все те ж саме , як і вихідна операція.
) на початку імені плагіна.
Adobe ExtendScript Toolkit.Цей інструмент, по суті, є нативним рішенням для написання скриптів до програм Adobe, але я використовував його тільки в кінці роботи. З його допомогою можна закрити вихідний код сторонніх. На виході виходить робочий скрипт з вмістом, що не читається.
Документація.Без неї написати щось складніше спливного віконця «Hello word!» буде досить проблематично. Наприкінці статті можна знайти деякі посилання.
Оптимізація
Наступна несподіванка сталася, коли мені потрібно було дізнатися, яких розмірів кожен ізотриманих місяців, щоб їх правильно розставити один від одного (користувач може виставляти різні інтервали). Швидко написавши просту функцію, яка мала повернути значення висот і ширин місяців, я запустив її. Photoshop намертво завис. Давши йому щедрих десять хвилин, після яких він так і не реанімувався, процес довелося вбити. Догадуюся, що одного разу він таки закінчив би, але десять хвилин це занадто багато саме по собі. Справа знову виявилася у кількості шарів у документі – їх було надто багато, щоб одразу отримати потрібні цифри. І знову скріпивши серце, я переніс обчислення розмірів на той етап, де створювався щомісяця. Тепер створений місяць одразу визначався за розмірами та показання записувалися у масив для подальшого використання. Звучить нескладно, але насправді це зайняло в мене чимало часу.
Тут перш за все хочу сказати велике спасибі моїм тестувальникам, без них я залишив би в коді ще більше недоліків, ніж є зараз.
Помилка з малюванням.Це порада для тих, хто пише скрипти з інтерфейсом користувача і при малюванні використовує складний перерахунок розмірів елементів (кнопок, наприклад) - перевіряйте роботу свого скрипту в Windows і MacOS. У мене був випадок, що в одному місці скрипт зависав у MacOS. Я довго шукав причину і вона крилася в наступному: розрахунок розміру однієї з кнопок повинен був підганятися по відношенню до іншої у бік збільшення, причому ця операція була загнана в цикл (згоден, спірне рішення). На Windows на всіх версіях Photoshop це відпрацьовувало відмінно, так як кнопка, що підганяється, завжди була менше основної. Але на MacOS виявилося навпаки — основна кнопка була меншою, ніж підганяється на один-два пікселі, і скрипт йшов у нескінченний цикл. Зараз я це виправив, і єдинийВисновок, який можна зробити - не використовуйте сумнівні рішення при перерахунку елементів інтерфейсу (Кеп).
Ще пара гнітючих моментів полягає в тому, що різні версії Photoshop малюють віконця по-різному, особливо елементи з прозорістю, через що мені доводилося перемальовувати ці кнопки вже з фоном (хоча, мені здається, можна було заморочитися і придумати щось інше. ).

Шанувальники творчості сера Террі Пратчетта, можливо, звернули увагу на кнопку "Holi WIZZARD". Мені подобаються такі речі, не знаю, це пасхалкою чи ні (до речі, про них нижче), я бачив щось подібне в одного антивіруса – там сканер називається Luke Filewalker (Люк Скай Файлоуокер).
Помилки внутрішні.Рідко, але трапляються помилки, які дуже складно пояснити. У моєму випадку такою проблемою виявилось завдання розміру ширини (а, можливо, і висоти) блокового тексту. Поясню: у Photoshop є два види тексту – Point Text (короткий) та Paragraph Text (блоковий). Перший немає кордонів, на відміну другого.
Так ось, у мене сталося таке – я поставив розмір ширини цього блокового тексту в 800 пікселів. На виході у мене вийшла ширина 3333 пікселів. Я не повірив своїм очам і почав перевіряти код. Помилки не було. Справа була ввечері, і я грішив на втомлену голову, тому почав перевіряти з особливою ретельністю з листочком у руках. Помилка на очі не попадалася.
Помилка з... масивом?Ось тут я не знаю в чому була справа, проте рішення виявилося цікавим.
Ось код, який створює сім випадаючих меню з іменами шрифтів:
При першій генерації вікна все проходило добре і без проблем. Але якщо користувач завантажить збереження, вікно буде закрито і перевідкрито з новим значенням fontIndex. Приперестворенні вікна з навантаженими налаштуваннями Фотошоп вилітав, якщо шрифт мав ім'я (в моєму випадку)Aarcover (Plain):001.001. Інші шрифти проходили нормально, але цей давав збій всій програмі.
Здавалося б, і добре, ймовірність вкрай мала (насправді ні), але мене це смикало дуже сильно. Перше вирішення проблеми виявилося таким:
Тобто, якщо перед цим циклом просто викликати вікно-попередження, в якому будуть перераховані всі елементи масиву arrFonts (і це віконце виходило на весь екран і навіть не було видно кнопки ОК), вікно скрипта згенерується нормально, як треба. Інші «алерти» з порожніми рядками та безладним текстом не допомагали, тільки з масивом шрифтів.
Через деякий час з'явилося друге рішення, яке працює, але я не розумію чому.
Корисна перерва
Для більшої наочності наведу порівняльну табличку:
Час, витрачений настворення 600 текстових шарів, що містять текст «01» (НУ - низькорівневе виробництво, РМ - створення стандартними методами)
| CS5 | НУ: 0 хв 47 сек СМ: 3 хв 43 сек | НУ: 2 хв 28 сек СМ: 9 хв 49 сек |
| CC 2015 | НУ: 1 хв 18 сек СМ: 10 хв 42 сек | НУ: 3 хв 12 сек СМ: 42 хв 36 сек |
Отже, спочатку потрібно було позбутися непотрібних рядків коду в отриманому елементі.
Я міг видалити кілька рядків без порушення функціоналу. Чистив я до тих пір, поки це було легко: шукаєш новий дескриптор, що неповторюється, дивишся, що він робить, видаляєш, перевіряєш роботу і, якщо все працює без видимих змін, продовжуєш так робити і далі. Коли помилки після кожного такого грубого хірургічного втручання у тіло функції стали виникати все частіше, я зупинився – найкраще ворог гарного. Потім знайшов, де задається шрифт, його розмір і колір, перевів ці місця в змінні, що задаються.
Отримана функція добре відпрацьовувала, причому їй потрібно було вказувати, де створювати новий текст – якщо активна якась група, то текстовий шар створиться у ній. Якщо активний текстовий шар, який знаходиться в якійсь групі, то правильно, новий шар буде в цій групі. Дуже зручно та економить час, заміна проведена не дарма. Ось код отриманої функції.
І ще дещо додам. Я не впевнений, але здається не всі низькорівневі функції виконуються швидше за стандартні методи — одного разу мені здалося, що переміщення шару на задану кількість пікселів по X і Y виконувалося швидше саме стандартним методом. Експериментуйте.
Великодні яйця
Без цього не можна ніяк. У скрипті є кілька пасхалок, і деякі з них видно тільки мені у вихідному коді (наприклад, одна функція називається fireStarter). Але є ті, що я залишив для своїх користувачів. Нижче спойлер, кому цікаво.

Довідкові матеріали до скрипту
Чесно скажу, для мене це був перший випадок, де я писав документацію без фанатизму, але із задоволенням. Склав я її дуже докладно, настільки, наскільки це вмію робити взагалі. Скооперувавшись із подругою, отримав відмінний (IMHO) переклад керівництва користувача. Так само вона допомогла мені перекладати елементи інтерфейсу, підказки та багато інших речей у скрипті, за що їй велике спасибі.
І для повного комплекту непогано було мати свій маленький форум для питань. Для цього я скористався сервісом Google групи.
Плюсом, я додав до скрипту директорію Examples зі створеними календарями. Один із них перекидний із фотографіями мого міста, зроблені найкращим другом — окрема гордість.




Відкриття магазинчика
«І хіба мій талант, і мій душевний жар не заслужили скромний гонорар?»Скрипт вийшов робочим і багатофункціональним, тому я вирішив, що він комусь виявиться корисним. Я вибрав досить популярний нині майданчик з помірними відсотками, виставив усе, що я маю, протрубив у деяких місцях про запуск і одразу пішов спати — я дуже переживав з приводу запуску, тому про результати вирішив дізнатися на свіжу голову.
Тепер я хочу лише одного. Відпочити. Відпустивши результат роботи у вільне плавання, я відчув тугу, полегшення та неймовірну втому. Так, є ще підтримка та інші речі, які потребують моєї уваги, але це вже інше. А взагалі вже є ідеї, як ще його поліпшити, або навіть зробити зовсім нову версію з іншим підходом. Але трохи згодом.
А з побічних ефектів — я став постійно звертати увагу на календарі, що опинилися поблизу. Щоразу я запитую себе — а мій скрипт так зможе? І тепер у більшостівипадків я відповідаю собі «Так». Бувають і відповіді «ні», звичайно, але це особливі календарі, де, наприклад, усі числа закручені у спіраль. Хоча, якщо написати скрипт... Утім, ні, не зараз.
Код писався у вільний час, часом і ночами, я був одержимий цим проектом, дякую дружині за розуміння. І всім, хто подужав цю статтю – ви славні хлопці. Сподіваюся, кожен з вас знайшов щось корисне для себе.
P.S. Якщо комусь сподобався кошеня, то він ось тут (
Додаткові матеріали:
» Документація Adobe Photoshop – особисто я використовував документацію до версії CS5 (для основного коду) та CS2 (там є розділ за UI) » Scripting Listener — плагін на Photoshop CC від Adobe для Windows та MacOS » Adobe ExtendScript Toolkit — версії CS3-CS5 та версія СС