[Из песочницы] Автоматизация создания GUI (Photoshop + Stalring)

Стала задача автоматизировать сборку GUI для одного проекта X.1 Текущая реализацияАртист делает все свои дела в photoshop и отдает их программистам. Программисты, в свою очередь, сами как-то вытягивают текстуры или атласы и с помощью улиты позиционируют каждый отдельный элемент на stage флешки, далее ручкам добавляют все текстовые поля, эффекты, прописывают всем этим элементам координаты, которые получили благодаря утилите. В итоге получается очень долгая и мучительная работа, а если учесть, что это делает еще и программист — это АД.1.1 Текущие проблемы Программисту приходится: долго и мучительно выгонять все текстуры из проекта позиционировать все элементы создавать экземпляры классов и задавать им нужные свойства подбирать цвет текста, размер подбирать эффект, если такой имеется по 3 миллиона раз запускаться и проверять Я уже не говорю о том случае, когда что-то поменяется.2 Решение Скрипт, который из psd выгоняет JSON со всеми настройками и параметрами + текстуры всех элементов на сцене. Собираем в атлас Движок для клиента (flash), который все это дело собирает в кучу. 2.1 Ограничения Небольшая подготовка psd перед экспортом, а именно объединение всех слоев и эффектов объекта. Т.е. если есть кнопка и над ней слой с бликом, то эти слои нужно объединить. Все исходники psd должны быть с расширением проекта на flash Необходимо растрировать все слои (возможно дальше пофикшу) 2.2 Что нам понадобится Adobe Photoshop CC Adobe ExtendScript Toolkit CS5 TexturePackerGUI intel ideja + (starling) Немного знаний JS && AS 3 Подготовка psd *учитывается, что каждый отдельный слой — это 1 элемент на сцене.Вот так выглядит заготовка самого psd: image3.1 Написание скрипта jsx Откроем Adobe ExtendScript Toolkit и поменяем target: image

Если у вас нет такой вкладки, тогда советую обновить photoshop. Я боролся с этим пока не нашел сборку с Adobe Application Manager в комплекте.

3.1.1 Скрипт Основа основ: #target photoshop //это нужно для информирования с чем мы работаем app.bringToFront (); //чтобы не открывать уже открытый экземпляр приложения Далее нам необходимо подключить либу для работы с JSON, поскольку стандартный js не хочет работать.Сама либа немаленькая, поэтому положил отдельно. Все что внутри нужно просто скопировать в документ скрипта, поскольку мы будем делать один документ, чтобы его с легкостью переносить.jam_libКонстанты необходимые для идентификации типа с которым работаем

var TYPE_SPRITE = «sprite»; var TYPE_TEXT = «text»; var TYPE_COLLECTION = «collection»; Основные переменные в скрипте

var arts = app.activeDocument.artLayers//все Нормальные слои в документе var sets = app.activeDocument.layerSets;//все группы слоев var respont = new Object ();//обж. который будет подвержен сериализации и сохранению var arr = new Array ();//обж. всех листов для сохранения var u = 0;//индекс в обж. сохранения var width_document = app.activeDocument.width.value; var heigth_document = app.activeDocument.height.value; Далее говорим Старт, и просим выбрать место сохранения результата в формате JSON (туда же добавятся и текстуры).

alert («Старт!»); var defaultInFolder = new Folder («C:\\»); var jsonFilter =«JSON Text Files:*.json, All Files:*.*»; var inFile = defaultInFolder.saveDlg («Open JSON text file:», jsonFilter); Проверка на валидность выбранного пути и запуск скрипта.

if (inFile) main (); Функция main — наша точка входа выполнения.

function main () { for (var j=0; j

function setSets (set) { var res = new Object (); res[«type»] = TYPE_COLLECTION; res[«name»] = set.name; for (var j=0; j

function setLayers (el) { var res= new Object (); var x; var y; x = el.bounds[0].value; y = el.bounds[1].value; res[«x»] = x; res[«y»] = y; res[«alpha»] = Math.round (el.opacity)/100;//альфу к диапазону 0–1 res[«name»] = el.name.replace (/\s+/g, '');//удаляем все пробелы с имени

try{//нехитрая конструкция проверки на текстовое поле var textItem = el.textItem res[«type»] = TYPE_TEXT;//если тут еще не вылетел эксепшен, значит, это текст res[«color»] = textItem.color.rgb.hexValue; res[«font»] = textItem.font; res[«size»] = Math.round (textItem.size.value); res[«contents»] = textItem.contents; res[«width»] = Math.round (textItem.width.value); res[«height»] = Math.round (textItem.height.value); }catch (e) { res[«type»] = TYPE_SPRITE; } arr.push (el); return res; } Сам парсинг сохранения текстуры вы глядит так:

function saveLayer (layer) { try{ var textItem = layer.textItem //это текст, то пропускаем его сохранение как текстуры return; }catch (e){ } activeDocument.activeLayer = layer; var o = layer.opacity; //получаем координаты и размеры текстур var xx = (layer.bounds[0].value); var yy = (layer.bounds[1].value); var ww = (layer.bounds[2].value); var hh = (layer.bounds[3].value);

var shape = [ [xx, yy], [ww, yy], [ww, hh], [xx, hh] ]; app.activeDocument.selection.select (shape);//выделяем область текстуры

app.activeDocument.selection.translate (new UnitValue (-xx, «px»), new UnitValue (-yy, «px»));//сдвигаем ее в 0 0

app.activeDocument.selection.deselect ();//уберем выделенную область

app.activeDocument.resizeCanvas (new UnitValue (ww-xx, «px»), new UnitValue (hh-yy, «px»), AnchorPosition.TOPLEFT);//изменяем размер документа к размеру текстуры

activeDocument.activeLayer.opacity = 100;//альфу текстуре 100

var saveFile= File (inFile.path+»/»+layer.name.replace (/\s+/g, '')+».png»); SavePNG (saveFile);//именно сохранение activeDocument.activeLayer.opacity = o;//возвращаем альфу слоя app.activeDocument.resizeCanvas (new UnitValue (width_document, «px»), new UnitValue (heigth_document, «px»), AnchorPosition.TOPLEFT);//возвращаем размеры слоя app.activeDocument. activeLayer.translate (new UnitValue (xx, «px»), new UnitValue (yy, «px»));//возвращаем позицию слоя }

function SavePNG (saveFile){ var pngOpts = new ExportOptionsSaveForWeb; pngOpts.format = SaveDocumentType.PNG pngOpts.PNG8 = false; pngOpts.transparency = true; pngOpts.interlaced = false; pngOpts.quality = 100; activeDocument.exportDocument (new File (saveFile), ExportType.SAVEFORWEB, pngOpts); } И 2 фун. для отображения слоев.

function visibleElement (sprite, flag) { sprite.visible = flag; }

function visible (flag) { for (var i = 0; i

image

Сам JSON файл:

{ »0»: { «x»: 205, «y»: 53, «alpha»: 1, «name»: «magic», «type»: «text», «color»:»0006FC», «font»: «Verdana», «size»: 30, «contents»: «Тут у нас волшебный текст», «width»: 417, «height»: 180 }, »1»: { «x»: 458, «y»: 281, «alpha»: 1, «name»: «el5», «type»: «sprite» }, … »6»: { «type»: «collection», «name»: «btn», »0»: { «x»: 300, «y»: 537, «alpha»: 1, «name»: «btn_art», «type»: «sprite» } } } Далее собираем обычный атлас текстур, Я делаю это с помощью TexturePackerGUI (не забываем указывать формат Sparrow / Starling)и кидаем в собранный на скорую руку движок. Сам результат видно через N секунд компиляции:

image

Статья получилась немаленькая, поэтому я решил вынести полный код скрипта в исходник (starling мини движок, асеты, скрипт photoshop). Доступно по ссылке: https://www.dropbox.com/s/8jurdz2ze4qzz18/pr.zip

© Habrahabr.ru