Esta publicação é uma continuação da primeira parte , onde o script Expand Clipping Mask foi apresentado e descrito em detalhes o que e como ele funciona e, ao longo do caminho, foram considerados os princípios básicos da criação de tais programas como um todo. Nesta parte, continuarei a história de como adicionar novas funcionalidades ao programa para obter um "produto final" da "peça de trabalho". Aqui você não pode ficar sem uma imersão mais profunda na área de assunto, que é uma das condições necessárias para criar um produto completo. Então, comece o mergulho!
As seguintes primitivas gráficas podem ser usadas como contorno da máscara no Adobe Illustrator: um contorno simples (Caminho), um contorno composto (Caminho composto), uma forma composta (Forma composta) e objetos de texto (Texto e texto do ponto no caminho). No momento, o script funciona apenas com contornos simples, como pode ser visto no código abaixo, em que PathItem
é uma chamada para o elemento Path.
var clipGroup = sel[0].pageItems.length; for (var i = 0; i < clipGroup; i++) { if (sel[0].pageItems[i].typename == 'PathItem' && sel[0].pageItems[i].clipping == true) { clipPath = sel[0].pageItems[i]; break; }; };
Antes disso, declaramos a variável clipPath
, mas não atribuímos um valor a ela.
var clipPath;
Isso significa que seu valor ainda não foi determinado, ou seja, está undefined
. Se agora selecionarmos uma máscara cujo contorno será, digamos, o Caminho composto e executar o script, o programa produzirá um erro na última linha da parte funcional do script,
clipPath.remove();
como a condição no loop não será atendida, a variável clipPath
permanecerá undefined
e é impossível aplicar o método remove()
a algo indefinido. Para evitar essa situação, faremos o seguinte - defina clipPath
como null
, o que, diferentemente de undefined
, já é algo mais específico que você pode pelo menos verificar.
Vamos pensar em como determinar se algum caminho composto é o contorno da nossa máscara. Quando digo "vamos pensar", significa que sugiro examinar a documentação e encontrar a propriedade de que precisamos. Por analogia com PathItem
estamos procurando a propriedade de clipping
. Acontece que o objeto CompoundPathItem
não possui essa propriedade, mas existe uma propriedade pathItems
através da qual você pode obter contornos simples de PathItem
que possuem a propriedade de clipping
.
Agora podemos transformar nossos pensamentos / pesquisas em código. Primeiro, clipPath
que clipPath
não foi definido na iteração anterior e, em seguida, clipPath
o bloco de código já gravado e fazemos pequenas alterações nele.
if (clipPath == null) { var clipGroup = sel[0].pageItems.length; for (var i = 0; i < clipGroup; i++) { if (sel[0].pageItems[i].typename == 'CompoundPathItem' && sel[0].pageItems[i].pathItems[0].clipping == true) { clipPath = sel[0].pageItems[i]; break; }; }; };
Na verdade, as alterações afetarão apenas uma linha. Como podemos ver aqui, 'PathItem' mudou para 'CompoundPathItem' e uma nova construção foi adicionada, 'pathItems [0]', com a qual nos referimos ao elemento do caminho composto.
if (sel[0].pageItems[i].typename == 'CompoundPathItem' && sel[0].pageItems[i].pathItems[0].clipping == true) {
A seguir, é apresentado o bloco funcional de código criado até o momento.
var clipGroup = sel[0].pageItems.length; for (var i = 0; i < clipGroup; i++) { if (sel[0].pageItems[i].typename == 'PathItem' && sel[0].pageItems[i].clipping == true) { clipPath = sel[0].pageItems[i]; break; }; }; if (clipPath == null) { for (var i = 0; i < clipGroup; i++) { if (sel[0].pageItems[i].typename == 'CompoundPathItem' && sel[0].pageItems[i].pathItems[0].clipping == true) { clipPath = sel[0].pageItems[i]; break; }; }; };
O próximo "paciente" é a forma composta. Aqui fica bem interessante! Na documentação, não encontramos esse objeto. O que fazer Primeiro, vamos definir a qual classe de objetos ele pertence. Para descobrir, escreveremos um pequeno código auxiliar, que depois descartamos. Como mencionado na primeira parte , não abordamos o problema das ferramentas usadas para escrever / depurar código. Portanto, suponha que este seja um arquivo separado, que simplesmente vá para a lixeira. O código será o seguinte:
var obj = app.activeDocument.selection[0]; alert(obj.typename);
Na primeira linha, criamos um link para o objeto selecionado, na segunda - exibimos uma mensagem sobre o tipo. Selecione o contorno da máscara no Adobe Illustrator, ou seja, o mesmo objeto Forma composta e execute o script. Na caixa de mensagem, vemos que a Forma composta é um PluginItem. Nos livramos do código auxiliar, retornamos à documentação novamente, mas não encontramos a propriedade de clipping ou pathItems no PluginItem. Em geral, nada que nos ajude a indicar inequivocamente que esse objeto é o contorno da máscara. No script, você não pode nem determinar que tipo de plug-in é. Algum módulo externo e é isso!
Isso é uma emboscada! - você exclama em seus corações. E o cérebro está trabalhando febrilmente, esperando resolver um problema insolúvel. E então, depois de analisar todas as opções possíveis e impossíveis, você pressiona desesperadamente Del
e exclui a odiada Forma composta. E aqui, pelo canto do olho, na paleta Layers
, você percebe que após essa ação, o contêiner de máscara, que era o Clip Group
, tornou-se apenas Group
. O que isso poderia significar? E o fato de a propriedade clipped
do objeto de clipped
de true
se tornar false
. Aqui está, uma solução que pode funcionar! Obviamente, isso é, em geral, um hack, mas que diferença faz se ajudar a determinar o circuito desejado.
O algoritmo para determinar o contorno da máscara representado pelo objeto Compound Shape será o seguinte: itere sobre todos os objetos da máscara em um loop e, quando encontrarmos o PluginItem, exclua-o e verifique se a propriedade clipped
do contêiner da máscara foi alterada. Se se tornou false
, então este é o nosso circuito. A única coisa para esse hack funcionar é atualizar o Illustrator do DOM depois de excluir o objeto, o que pode ser feito usando o método app.redraw()
. Então você ainda precisa se lembrar de retornar o objeto remoto, o que é feito pelo método app.undo()
.
Abaixo está o código para o caminho da Forma composta:
if (clipPath == null) { for (var i = 0; i < clipGroup; i++) { if (sel[0].pageItems[i].typename == 'PluginItem') { sel[0].pageItems[i].remove(); app.redraw(); if (sel[0].clipped == false) { app.undo(); clipPath = sel[0].pageItems[i]; break; } else { app.undo(); } }; }; };
Agora, de todas as opções possíveis para o tipo de objetos que podem ser o contorno da máscara, apenas o texto (ou TextFrameItem
, na terminologia das referências de script do ilustrador ) TextFrameItem
. Voltamos à documentação várias vezes e não encontramos as propriedades de clipping
lá. Mas desta vez, não nos preocupamos mais com isso e descobrimos com calma que TextFrameItem
possui uma propriedade de kind
que determina o tipo do objeto de texto ( TextType
). Descobrimos que pode haver três tipos: AREATEXT, POINTTEXT e PATHTEXT. O primeiro tipo não é interessante para nós, pois não pode ser usado como contorno de uma máscara, e os outros dois ainda são tão interessantes. Resta apenas encontrar um hack que nos ajudará a determinar agora não o contorno, mas o objeto de texto, que é o contorno da máscara. E esse truque será a equipe, Convert To Area Type, que converterá POINTTEXT em AREATEXT. Assim como no Composto, clipped
uma alteração implícita na propriedade clipped
.
Por conseguinte, o código para um TextFrameItem do tipo POINTTEXT será o seguinte:
if (clipPath == null) { for (var i = 0; i < clipGroup; i++) { if (sel[0].pageItems[i].typename == 'TextFrame' && sel[0].pageItems[i].kind == 'TextType.POINTTEXT') { sel[0].pageItems[i].convertPointObjectToAreaObject(); app.redraw(); if (sel[0].clipped == false) { app.undo(); clipPath = sel[0].pageItems[i]; break; } else { app.undo(); } }; }; };
Existe apenas um TextFrameItem
tipo PATHTEXT restante. Infelizmente, ao converter PATHTEXT em AREATEXT, a propriedade clipped
não muda. Mas, como esse é o último candidato possível ao título "esboço da máscara", é possível usar exatamente esse comportamento. Ou seja, verificamos que, após executar o clipped
Convert To Area Type
, a propriedade clipped
permanece true
. Abaixo está o código para um TextFrameItem do tipo PATHTEXT.
if (clipPath == null) { for (var i = 0; i < clipGroup; i++) { if (sel[0].pageItems[i].typename == 'TextFrame' && sel[0].pageItems[i].kind == 'TextType.PATHTEXT') { sel[0].pageItems[i].convertPointObjectToAreaObject(); app.redraw(); if (sel[0].clipped == true) { clipPath = sel[0].pageItems[i]; break; } else { app.undo(); } }; }; };
Portanto, se reunirmos pedaços de código gravados sequencialmente, incluindo um bloco de verificações, obteremos esse código, cuja execução, conforme declarado na primeira parte da postagem, implementará a ação do novo comando Expandir máscara de recorte no Adobe Illustrator.
#target illustrator if (app.documents.length > 0) { var doc = app.activeDocument; var sel = doc.selection; var clipPath = null; if (sel.length > 0) { if (sel[0].typename == 'GroupItem' && sel[0].clipped == true) { var clipGroup = sel[0].pageItems.length; for (var i = 0; i < clipGroup; i++) { if (sel[0].pageItems[i].typename == 'PathItem' && sel[0].pageItems[i].clipping == true) { clipPath = sel[0].pageItems[i]; break; }; }; if (clipPath == null) { for (var i = 0; i < clipGroup; i++) { if (sel[0].pageItems[i].typename == 'CompoundPathItem' && sel[0].pageItems[i].pathItems[0].clipping == true) { clipPath = sel[0].pageItems[i]; break; }; }; }; if (clipPath == null) { for (var i = 0; i < clipGroup; i++) { if (sel[0].pageItems[i].typename == 'PluginItem') { sel[0].pageItems[i].remove(); app.redraw(); if (sel[0].clipped == false) { app.undo(); clipPath = sel[0].pageItems[i]; break; } else { app.undo(); } }; }; }; if (clipPath == null) { for (var i = 0; i < clipGroup; i++) { if (sel[0].pageItems[i].typename == 'TextFrame' && sel[0].pageItems[i].kind == 'TextType.POINTTEXT') { sel[0].pageItems[i].convertPointObjectToAreaObject(); app.redraw(); if (sel[0].clipped == false) { app.undo(); clipPath = sel[0].pageItems[i]; break; } else { app.undo(); } }; }; }; if (clipPath == null) { for (var i = 0; i < clipGroup; i++) { if (sel[0].pageItems[i].typename == 'TextFrame' && sel[0].pageItems[i].kind == 'TextType.PATHTEXT') { sel[0].pageItems[i].convertPointObjectToAreaObject(); app.redraw(); if (sel[0].clipped == true) { clipPath = sel[0].pageItems[i]; break; } else { app.undo(); } }; }; }; app.executeMenuCommand('releaseMask'); clipPath.remove(); } else { alert (' -!'); }; } else { alert (' !'); }; } else { alert (' !'); };
Aqui você pode pôr um fim a. Não, um ponto e vírgula é melhor.
Espero que, com essas postagens, tenha ajudado você a se aproximar um pouco mais do seu objetivo - começar a programar no Adobe Illustrator. Obrigado pela atenção!