[Из песочницы] Автоматизация создания 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: 3.1 Написание скрипта jsx Откроем Adobe ExtendScript Toolkit и поменяем target:
Если у вас нет такой вкладки, тогда советую обновить 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 Сам 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 секунд компиляции: Статья получилась немаленькая, поэтому я решил вынести полный код скрипта в исходник (starling мини движок, асеты, скрипт photoshop). Доступно по ссылке: https://www.dropbox.com/s/8jurdz2ze4qzz18/pr.zip