Usando Scripts UXP (.psjs) para Controlar o Photoshop
Receitas executáveis para agentes: criar, modificar e exportar documentos no Photoshop. Os fatos são divididos em duas categorias:
- Oficial: da documentação da Adobe UXP, com links no final.
- Testado: experiência comprovada ao executar
.psjsno Windows e macOS, Adobe Photoshop 2026. Itens não verificados são marcados como não verificado e não devem ser tratados como API oficial.
Critério de sucesso: O script escreve um JSON de resultado (contendo done / ok / fatal / errs); apenas o documento alvo especificado pela tarefa é modificado, outros documentos abertos não são afetados; quando o alinhamento de pixels é necessário, exporte PNG e compare com a imagem de ouro usando ΔE/diferença de pixel e itere.
Pare primeiro: A tarefa não especifica qual documento modificar, ou solicita sobrescrever um documento com alterações não salvas pelo usuário sem permissão explícita.
1. Quando Usar / Quando Não Usar
Use .psjs quando:
- Você precisa do Photoshop para algo que só ele faz: renderizar pixels com efeitos de camada, exportar fatias por camada, usar
batchPlaypara criar formas/texto/efeitos, salvar resultados como PSD/PNG. - Inferir uma lista de fatias de um PSD/PSB, revisar e exportar PNG 1x e um JSON de layout independente de engine: veja a seção 9.
- O agente precisa executar uma tarefa de uma só vez (escrever script → iniciar → fazer polling do log → copiar artefatos), sem a necessidade de um painel persistente.
Não inicie o Photoshop quando:
- Apenas leitura da árvore de camadas, nomes, IDs, texto, bounds aproximados: use
psd-toolsouag-psdpara analisar offline. Testado:layer_iddopsd-toolscorresponde alayer.iddo UXP, você pode usar a estrutura offline para localizar e deixar apenas a renderização/exportação para o PS. Observe que o bbox dopsd-toolsnão inclui efeitos de camada; os bounds visuais finais ainda precisam ser calculados no PS.
Use um plugin UXP quando:
- Você precisa de um canal persistente e bidirecional (por exemplo, ponte MCP, painel, WebSocket). Oficial: scripts não têm manifest / painel; Network, LaunchProcess, WebView, IPC não estão disponíveis. Essas capacidades precisam ser implementadas em um plugin com permissões declaradas no manifest.
- Oficial: você não pode chamar outro
.psjsde dentro de um plugin; mas o código UXP de um script geralmente pode ser movido para um plugin e executado.
Use ExtendScript / JSX quando:
- O alvo é Photoshop 23.5 ou inferior, ou você só pode usar
DoJavaScriptno Windows COM /do javascriptno macOS AppleScript /evalScriptno CEP. JSX é ES3, API síncrona, modo de manutenção. Não tratepsx.jsx(a biblioteca auxiliar ExtendScript de xbytor) como um runtime.
2. Pontos Oficiais (Lembre-se Destes Primeiro)
- Scripts UXP independentes estão disponíveis desde o Photoshop 23.5, extensão
.psjs. A depuração pode usar o UXP Developer Tool ≥ 1.6, mas a execução de scripts não requer o UDT. - Formas oficiais de iniciar:
File > Scripts > Browse...; arraste o.psjspara o ícone do Dock (Mac) ou para a área de documento não aberta da janela do Photoshop (Mac/Win); execute um script por meio de uma Action. Duplo clique para abrir foi marcado como "Em breve". - Scripts são JS moderno, suportam
awaitde nível superior. Exemplos oficiais e testes dependem disso; não escreva um script que defineasync mainmas nunca a chama comawait main()e depois sai imediatamente. - Qualquer operação que modifique o documento ou o estado do aplicativo deve ser envolvida em
require("photoshop").core.executeAsModal(fn, { commandName }). OcommandNameaparece na barra de progresso (se o script demorar mais de 2–3 segundos, uma barra de progresso aparece e o usuário pode cancelar). - Quando o DOM não é suficiente, use
require("photoshop").action.batchPlay(descriptors, options). Os descritores são actionJSON. Oficial: prefira o DOM. Use "Copy As JavaScript" no painel Actions no modo desenvolvedor, ou grave descritores comPlugins > Development > Record Action Commands..., não invente nomes de chave. dialogOptionsé escrito no_optionsde cada descritor, com valores"silent"(padrão, sem pop-up mesmo em caso de erro),"dontDisplay"(geralmente sem pop-up, mas pode mostrar se faltar parâmetros ou houver erro),"display". Testado (PS 2026): o agente DEVE usar"silent". Com"dontDisplay", se o comando falhar, uma caixa de erro bloqueante ainda aparece (por exemplo,O comando "Obter" não está disponível no momento.), e o script espera até que alguém clique em OK; após clicar, ele retorna{_obj:"error", message:"", result:-128}(-128 é o código de cancelamento oficial do usuário)."silent"não exibe pop-up e retorna em cerca de 1–5ms com{_obj:"error", message:"NomeDoScript: O comando "…" não está disponível no momento.", result:-25920}. Anteriormente,{ dialogOptions: "dontDisplay" }foi passado como segundo argumento parabatchPlaysem erro, mas a tabela de opções oficial não tem essa chave, e não é seguro usar"display"para verificar se funciona. Novo código: coloquedialogOptionsno_optionsdo descritor, com valor"silent".- Parâmetros ilegais em
batchPlaycausam rejeição; falhas em tempo de execução (como alvo inexistente) resolvem, retornando{_obj:"error", message, result}.result === -128significa cancelamento pelo usuário. Sempre verifique o array retornado. - Sistema de arquivos: scripts não têm manifest, as permissões são incorporadas ao Photoshop. A documentação oficial de scripting ainda diz: você pode usar o seletor de arquivos e
getTemporaryFolder().getEntryWithUrl/createSessionTokensão APIs oficiais do FileSystemProvider (veja a seção 4 para testes). require("uxp").scriptforneceexecutionContext,args,setResult(result). O FAQ oficial (na documentação inicial) dizia: a primeira versão não suporta passar argumentos para scripts. Não dependa de argumentos de linha de comando ouscript.argspara passar a configuração da tarefa; escreva caminhos e parâmetros diretamente no script, ou faça o script ler um JSON adjacente. Testado (Windows / PS 2026,Photoshop.exe script.psjs):script.argsé[]. Se você passar argumentos CLI extras após o caminho do script, o script não será executado (nenhum arquivo de resultado em 3 minutos), o lançador ainda retorna imediatamente com código de saída 0, stdout sem saída do script. Não passe argumentos CLI extras.setResultpode ser chamado, retornaundefined, e não aparece no código de saída ou stdout doPhotoshop.exe. Sempre use um arquivo de resultado.- Apenas um script pode ser executado por vez, e um script não pode chamar outro script.
executionContextoficial:isCancelled/onCancelpara responder ao cancelamento do usuário,reportProgress({ value, commandName })para atualizar a barra de progresso,hostControl.suspendHistory({ documentID, name })+resumeHistory(id, commit)para agrupar um lote de modificações em uma única etapa do histórico, facilitando o desfazer para o artista. Testado:isCancelledé booleano;reportProgresspode ser chamado, retornaundefined.suspendHistory({documentID, name})retorna{historySuspensionID},resumeHistory(id)combina várias modificações subsequentes em uma única etapa, com o nome aparecendo emdoc.historyStates. As chaves enumeráveis dehostControlpodem estar vazias; useObject.getOwnPropertyNames. Para ler o histórico, use o DOM (doc.historyStates/doc.activeHistoryState), nãobatchPlaygethistoryStatesCount(esse comando não está disponível, veja a seção 7).
3. Inicialização e Polling do Agente (Testado no Windows)
Oficialmente, "passar um .psjs para Photoshop.exe pela linha de comando" não é uma interface documentada. Testado (Windows / Photoshop 2026):
& "C:\Program Files\Adobe\Adobe Photoshop 2026\Photoshop.exe" "D:\work\ps-job\run_job.psjs"
- Não requer o desktop do Creative Cloud, UDT ou modo desenvolvedor.
- Se o Photoshop já estiver aberto, o script é executado na instância existente.
- O lançador retorna imediatamente, o script continua de forma assíncrona no PS. Você DEVE fazer polling do JSON de resultado que o próprio script escreve (recomenda-se incluir
done,ok,fatal,errs), e não confiar no código de saída do processo para determinar sucesso ou fracasso. - Testado: um script de exportação levou cerca de 18 segundos para exportar 28 fatias de um
.psb(cerca de 10 segundos para abrir o arquivo) e escreveuexport_log.json. - Testado (Windows / PS 2026): A associação de arquivos existe (
.psjs=Photoshop.PSJSFileType.200, ftype éPhotoshop.exe "%1").Start-Process script.psjsrealmente executa o script e escreve o arquivo de resultado. O agente ainda deve passar explicitamentePhotoshop.exe+ caminho do script e confiar no arquivo de resultado. - Antes de iniciar, verifique se o PS não está com uma caixa de diálogo modal (como o prompt "Recuperar documentos" após uma falha, caixas de salvamento, etc.). Se houver uma caixa de diálogo, o script não será executado conforme o esperado e o polling apenas resultará em timeout; após o timeout, primeiro tire um print da tela do PS para ver a interface, não reexecute cegamente.
Fluxo do agente remoto: Escreva o .psjs no lado do agente → copie para a máquina com Photoshop (apenas diretórios autorizados pelo usuário) → inicie com shell e faça polling do log → copie PNG/PSD/log de volta → compare pixels se necessário.
Exemplo de polling (PowerShell):
$ps = "C:\Program Files\Adobe\Adobe Photoshop 2026\Photoshop.exe"
$script = "D:\work\ps-job\run_job.psjs"
$log = "D:\work\ps-job\job_log.json"
if (Test-Path $log) { Remove-Item $log }
& $ps $script
$deadline = (Get-Date).AddMinutes(10)
do {
Start-Sleep -Seconds 2
if (Test-Path $log) {
$j = Get-Content $log -Raw | ConvertFrom-Json
if ($j.done) {
$j | ConvertTo-Json -Depth 8
if (-not $j.ok) { exit 1 }
break
}
}
if ((Get-Date) -gt $deadline) { throw "timeout esperando por $log" }
} while ($true)
macOS (testado, Photoshop 2026, Mac mini): Oficialmente, ele diz apenas arrastar para o Dock/Janela; o seguinte comando de linha de comando não é visto na documentação oficial, mas foi testado e funciona:
open -a "Adobe Photoshop 2026" /path/to/run_job.psjs
# Quando .psjs está associado, também: open /path/to/run_job.psjs
- Inicialização a frio: Se o PS não estiver em execução,
open -aretorna em cerca de 0,3 segundos (exit 0), o PS inicia e executa o script automaticamente, levando cerca de 8 segundos para escrever o arquivo de resultado. - Inicialização a quente: Se o PS já estiver em execução, o script é executado na instância existente e escreve o resultado em alguns segundos.
open xxx.psjssem-a, usando a associação de arquivos, também executa.getEntryWithUrl("file:/Users/<user>/...")pode escrever arquivos sem seletor.- Assim como no Windows: o lançador retorna imediatamente, você deve fazer polling do arquivo de resultado e não adicionar argumentos de linha de comando extras.
Exemplo de polling (zsh):
log=~/ps-job/job_log.json; rm -f "$log"
open -a "Adobe Photoshop 2026" ~/ps-job/run_job.psjs
for i in {1..300}; do [ -f "$log" ] && grep -Eq '"done": ?true' "$log" && break; sleep 2; done
cat "$log"
Veja o script esqueleto em examples/run_job.psjs (await de nível superior, executeAsModal, proteção de ID de documento, arquivo de resultado, try/catch). Testado: Seguindo este esqueleto, ele funciona: escreve done/ok, exporta preview.png, fecha o documento que criou, e os IDs dos outros documentos abertos permanecem inalterados.
4. Acesso a Arquivos
FileSystemProvider oficial: getFileForOpening / getFileForSaving / getFolder, getTemporaryFolder, getEntryWithUrl(url), createEntryWithUrl, createSessionToken(entry).
O _path para batchPlay deve ser um session token, não um caminho de sistema bruto. Documentação oficial: ao usar o DOM do Photoshop (como app.open(file), doc.saveAs.psd(file, …)), você pode passar diretamente uma entrada File/Folder, e o host converte para token automaticamente.
Testado (PS 2026 script, sem seletor):
const fs = require("uxp").storage.localFileSystem;
const root = await fs.getEntryWithUrl("file:/D:/work/ps-job"); // diretório deve existir
const out = await root.createFile("job_log.json", { overwrite: true });
await out.write(JSON.stringify(log, null, 2));
URLs como file:/D:/... funcionam no Windows. A documentação de script ainda garante apenas seletor + diretório temporário; trate "caminho arbitrário, sem seletor" como comportamento testado no PS 2026, e em outras versões faça um teste de fumaca de escrita primeiro. Não use módulos de rede — o ambiente de script oficial os proíbe.
5. Escopo e Segurança do Documento (Obrigatório)
Princípio: O script só modifica o documento alvo especificado pela tarefa. O alvo pode ser um documento criado pelo script ou um PSD existente indicado pela tarefa (iterar sobre um design existente é um cenário comum). Todos os outros documentos abertos não devem ser alterados, salvos ou fechados.
Determinar o conjunto alvo targets:
- Novo: O ID retornado por
app.createDocument()é adicionado atargets. - Iterar sobre PSD existente: Localize pelo caminho fornecido pela tarefa. Primeiro, verifique nos
app.documentsse o documento já está aberto pordoc.path; se estiver, use essa instância diretamente (não abra uma segunda cópia); se não estiver, useapp.open(entry).Confiar apenas no nome não é confiável (nomes duplicados, cópias "-recuperado"). Priorize o caminho, depois o ID do documento fornecido pela tarefa. Testado: Usar o caminho reutiliza a mesma instância (mesmo ID de documento, não abre uma segunda cópia); após edições não salvas,doc.saved === false; ao usarsaveAs(..., true)para salvar uma nova versão, o mtime e o tamanho do arquivo original permanecem inalterados, o documento permanece aberto e ainda aponta para o caminho original. No Windows,doc.pathtem o formatoD:\work\file.psd. Documentos recuperados (como "xxx-recuperado") podem terpathvazio esaved === false, não sendo encontrados pelo caminho; use o ID do documento fornecido pela tarefa. - Documentos temporários (como fatias "Nova camada a partir de") são adicionados a
targetse fechados comcloseWithoutSaving()após o uso.
Proteção: Antes de qualquer batchPlay, salvamento ou fechamento, verifique se app.activeDocument.id está em targets. Esta verificação cobre apenas descritores que implicitamente se referem ao documento atual; para descritores que escrevem explicitamente { _ref: "document", _id }, esse ID também deve ser verificado. Antes e depois da execução, registre app.documents.map(d => ({ name: d.name, id: d.id, path: d.path })) no log.
Testado: Ao usar make em uma camada com { _ref: "document", _id } de um documento não ativo, a camada é criada nesse documento e activeDocument não muda; portanto, IDs explícitos devem ser verificados. No entanto, set não funciona em documentos não ativos (veja a seção 7); para alterar propriedades, primeiro defina app.activeDocument = target e depois set.
Ao modificar um documento existente:
- Se o documento alvo já está aberto e tem alterações não salvas (oficialmente
doc.saved === false), significa que o usuário está editando manualmente. Por padrão, você pode continuar editando (este é o objetivo da iteração), mas não sobrescreva o salvamento, a menos que a tarefa solicite explicitamente; primeiro registre no log que ele estava sujo antes da execução. - Use
hostControl.suspendHistorypara agrupar as modificações do script em uma única etapa do histórico, permitindo que o usuário desfaça tudo com um Ctrl+Z. - A estratégia de salvamento depende da tarefa: por padrão, salve como uma nova versão (por exemplo,
xxx_v14.psd), preservando o arquivo original; apenas salve diretamente comdoc.save()se a tarefa solicitar explicitamente "atualizar no local". - Ao final do script, não feche o documento alvo que o usuário já tinha aberto; feche apenas os documentos que o próprio script abriu ou criou e que a tarefa não pede para manter.
Limpeza automática: executionContext.hostControl.registerAutoCloseDocument(docID) oficial fecha automaticamente documentos temporários quando o usuário cancela ou o modal termina; use apenas para documentos criados pelo script. Se o artista precisar continuar editando, primeiro chame unregisterAutoCloseDocument. Não registre fechamento automático para documentos existentes do usuário.
6. Ciclo de Validação
- O script exporta PNG (e, opcionalmente, PSD).
- No lado do agente, compare com a imagem de ouro (CIEDE2000 ΔE, diferença de pixel, zoom local).
- Com base nas diferenças, modifique o script (caminhos, gradientes, estilos de camada) — não edite manualmente no documento aberto do usuário esperando que seja reproduzível.
- Reexecute, exporte novamente, compare novamente, até atingir a meta ou explicar a diferença restante.
7. Armadilhas Testadas
-
dialogOptions: "dontDisplay"ainda exibe uma caixa de erro bloqueante quando falha. Cada descritor executado pelo agente DEVE ter_options: { dialogOptions: "silent" }. Se o polling atingir timeout, primeiro verifique se o PS está com uma caixa de erro; não reexecute cegamente. Se houver uma caixa de diálogo, não inicie o próximo script. -
Leia o histórico usando o DOM, não
batchPlaygethistoryStatesCount. O último retorna "O comando 'Obter' não está disponível no momento." ComdontDisplay, exibe pop-up; comsilent, retornaresult: -25920. Usedoc.historyStates/doc.activeHistoryState. -
setem um documento não ativo falha ("O comando 'Definir' não está disponível no momento."). Primeiro, defina o alvo comoapp.activeDocumente depoisset. O mesmomakede camada, no entanto, pode funcionar em um documento não ativo sem alternar o documento atual — o_iddo documento no descritor deve ser incluído na proteção. -
Multi-contorno deve usar
frameFXMulti(um único pode usarframeFX). Gradiente ao longo da expansão da forma usagradientType: "shapeburst". -
innerShadowde chave única é silenciosamente ignorado; ele deve ser escrito comoinnerShadowMulti: [{ _obj: "innerShadow", ... }]. Após a modificação, leia de volta comgetlayerEffectspara confirmar que a chave realmente está lá. -
Caminho personalizado: primeiro
setworkPath, depoismake contentLayer. As formas criadas dessa forma geralmente não têmkeyOriginTypee não são formas em tempo real com cantos arredondados editáveis na barra de propriedades. Para cantos arredondados editáveis, usemake contentLayer+shape._obj = "rectangle"/"ellipse"comunitValueQuadVersion: 1e quatro raios de canto. -
A fonte é atribuída pelo nome PostScript (por exemplo,
textItem.characterStyle.font = "MuseoSansRounded-1000") e deve estar instalada; a instalação pelo usuário é suficiente, não precisa ser em nível de máquina. -
No descritor RGB, o campo verde é chamado de
grain, nãogreen. Não "corrija" este nome. -
executeAsModaldeve serawait. Se você esquecer, o código subsequente continuará sendo executado antes que o modal seja obtido. -
batchPlaylançará uma exceção se o usuário cancelar; não usecatchvazio para engolir o cancelamento, caso contrário o script não parará.
ActionJSON de estilos de camada e formas: veja references/batchplay.md.
8. Fontes de Informação
Oficial:
- UXP Scripting in Photoshop (
.psjs, 23.5, formas de iniciar) - Quickstart
- How it works (await de nível superior, permissões de módulo, FAQ: primeira versão não suporta passar argumentos, script não pode chamar script, sem rede)
- Scripting reference (
executionContext/hostControl) require("uxp").script(args,setResult)- executeAsModal
- batchPlay
- FileSystemProvider
- File access
- Samples
As seções acima incluem complementos testados, provenientes de trabalhos que usam .psjs para criar componentes de UI em lote e comparar pixels com imagens de ouro; não são padrão Adobe.
9. Fluxo de Trabalho de Slicing do Agente
Divida a interface em PNG 1x que podem ser importados por engines de jogo e produza um JSON de layout intermediário organizado por semântica de componente e independente de engine. Detalhes, schema, nomenclatura, métodos de identificação e testes: veja references/slicing.md. Primeiro, siga a árvore de decisão no início desse documento: Abra o material (incluindo efeitos de camada nos grupos e escolha o modo de efeito para cada parte afetada) → Identifique componentes → Separe peças compartilhadas das que variam com o estado → Diferencie variantes de rascunhos antigos → Registre como missing apenas as peças que realmente variam → Determine se elementos repetidos são reutilizados → Pare na trava de revisão. Scripts e auxiliares Python: examples/export_slices.psjs, examples/slicing_helper.py, examples/naming_rules.example.json, examples/export_config.example.json.
Ambiente Python: Execute o auxiliar com o venv do projeto, não instale pacotes no Python do sistema. Necessário: psd-tools[composite], Pillow, numpy. Para abrir documentos grandes, use o testado PSDImage.open(path, parse_limits=ParseLimits(max_objects=None)) (não adivinhe parâmetros e não defina ParseLimits.max_objects como atributo de classe). Veja slicing.md "Ambiente Python" para detalhes.
Divisão de trabalho: O auxiliar apenas prepara os materiais (imagem completa do estado padrão, recortes camada por camada com IDs, árvore de camadas com camadas ocultas, candidatos a nine-slice). O agente que executa esta skill lê esses materiais e escreve o manifest: componentes, partes, nomes canônicos, tipos, estados e hierarquia. --rules é apenas uma convenção de nomenclatura opcional do projeto. infer ainda pode produzir um rascunho de palavras-chave (draft_manifest.json), mas não substitui o inventário do agente.
Fluxo (não exporte antes da confirmação):
- Preparar materiais (offline):
prepare.--artboard <nome ou id da prancheta>opcional; omitir processa todas as pranchetas visíveis de nível superior; se não houver pranchetas, processa a tela inteira. A árvore inclui camadas ocultas (marcadasvisible).crops/contém principalmente folhas exportáveis; grupos com efeitos de camada são escritos emgroup_effects.jsonecrops_index.json(quando a composição é possível, também há um recorte do grupo), e anexa os parâmetros de efeitoeffect_paramslidos pelo psd-tools (tipo, modo de mesclagem, cor, opacidade, ângulo, distância, tamanho, expansão/contração, posição do contorno). Use o índice para encontrar IDs, não adivinhe nomes de arquivo. Se um grupo ID não tiver um recorte, não mude diretamente para as folhas internas — primeiro verifique se esse grupo tem efeitos. Agrupamentos sem efeitos, camadas vazias ou fora da prancheta: volte paratree.jsonpara determinar; a ausência de um recorte não significa estado ausente. - Agente escreve o manifest: Identifique componentes interativos como grupos de guias, barras inferiores, botões, linhas de lista, etc. Separe fundos/highlights/ícones/texto em partes independentes por estado, não cozinhe os estados juntos. Primeiro, veja quais partes no design são compartilhadas entre estados e quais mudam: as compartilhadas vão em
shared(nome do arquivo sem sufixo de estado), as que mudam vão em seus respectivosstates. Camadas ocultas são consideradas estados alternativos apenas quando o corpo/conteúdo principal é o mesmo, e a diferença é apenas no estilo do estado (luminosidade, contorno, brilho, esquema de cores, etc.); se a mesma posição tem conteúdo ou emblema diferente, trate como rascunho antigo e ignore, não use para substituir o verdadeiro recurso compartilhado e não marque peças compartilhadas comomissing. Camadas ocultas que estão na posição do item atualmente selecionado, com o mesmo corpo e apenas com estilo de brilho/destaque, devem ser tratadas comohighlightdesse estado (o estado selecionado padrão também deve ser incluído); camadas de brilho/balão sobrepostas ao fundo selecionado visível, mesmo com forma diferente, são um highlight sobreposto, não uma substituição — não coloque emuncertain_hidden; apenas quando o conteúdo ou motivo não corresponder, escrevauncertain_hidden(com os recortes de ambos os lados).missingdeve ser modelado a partir do item mais completo no mesmo grupo (por exemplo, item selecionado tem base + highlight + label), e cada item irmão que carece de um desses componentes deve ser listado, incluindo o highlight. Uma única linha de lista com estilo especial é apenas uma instância dessa linha; não infira estados ausentes para outras linhas, nem infira umnormalausente para esta linha, a menos que o design tenha conjuntos completos de variantes para cada linha. Ao selecionar o alvo de exportação, verifique se o grupo pai mais próximo do elemento (ou o grupo que representa o elemento) tem efeitos de camada (como sombra projetada). Se o efeito estiver no grupo, mas as folhas internas não tiverem, escolha umeffect_modepara essa parte (veja slicing.md "Efeitos de grupo: assar ou renderizar pela engine"):baked(padrão) —layer_id/select_idsusam o ID do grupo, o efeito é assado na imagem, a caixa visível inclui o efeito, a caixa lógica não;engine—select_idsusam as subcamadas, oseffect_paramsdo grupo são copiados paraengine_effects, renderizados pela engine, a imagem não tem pixels de efeito. Cada parte com efeito escreve uma linhaeffect_reason. Se as regras do projeto ou o usuário especificarem um modo, siga-o. A única coisa proibida é selecionar apenas subcamadas sem registrar o efeito (o efeito desaparece silenciosamente). Proibido inventar. Elementos repetidos: primeiro determine se são reutilizáveis com base no propósito da UI, no senso comum de UI de jogos (fundos de linha de lista, molduras de avatar, botões do mesmo estilo, medalhas de classificação, ícones de moeda, barras de progresso geralmente são reutilizados; imagens de avatar são conteúdo em tempo de execução e devem ser separadas da moldura e marcadas complaceholder: true; nomes/pontuações/números são texto dinâmico) e nas evidências dereuse_candidates.json: se deve ser reutilizado, exporte uma única imagem e cada instância escrevereuse_of: <nome compartilhado>(o nome compartilhado não inclui número de instância); se não corresponder ao efeito, primeiro suspeite que a decisão está errada e apenas separe as instâncias inconsistentes; se a evidência lógica for forte, mas não corresponder, ou se avatar e moldura estiverem combinados no PSD, escreva emreuse_decisions(evidência, problema, imagens de comparação, opções) e deixe para o usuário decidir; por padrão, exporte separado antes da decisão. Nomeie comomodulo_tipo_proposito_estado(minúsculas; peças compartilhadas omitem o segmento de estado). Não use diretamente o nome da camada do PSD. Tipos:image|nine_slice|dynamic_text|art_text. - Trava de revisão:
flatten+previewproduzem uma prévia anotada e JSON (tags comfx:baked/fx:engine, e efeitos de engine desenham uma faixa estimada para facilitar a mudança de modo pelo usuário durante a revisão;flattenlista partes que perderiam efeitos emeffect_issues). O usuário modifica o JSON e confirma; ostatuspermanecepending_reviewaté a confirmação.previewpula caixas delimitadoras invertidas ou vazias com um aviso, não interrompe. - Exportação (
.psjs): O script codifica apenas umCONFIG_URL, lê os caminhos do JSON do trabalho. Exporta PNG 1x porlayer_id/select_ids:bakedseleciona o grupo, o efeito é assado na imagem;engineseleciona as subcamadas e as mescla, a imagem não contém efeitos do grupo. Instâncias comreuse_ofexportam apenas uma imagem compartilhada; as outras instâncias registram apenas os bounds.dynamic_textnão produz imagem, apenas exporta propriedades de texto;art_textproduz imagem.
…
[truncado para tradução]