Comment démarrer la programmation dans Adobe Illustrator. Deuxième partie

Cet article est une continuation de la première partie , où le script Expand Clipping Mask a été présenté et décrit en détail ce qu'il fait et comment il le fait, ainsi que les principes de base de la création de tels programmes en général. Dans cette partie, je vais continuer l'histoire de la façon d'ajouter de nouvelles fonctionnalités au programme afin d'obtenir un «produit fini» de la «pièce». Ici, vous ne pouvez pas vous passer d'une immersion plus approfondie dans le domaine, qui est l'une des conditions nécessaires à la création d'un produit à part entière. Alors, commencez la plongée!


Les primitives graphiques suivantes peuvent être utilisées comme contour de masque dans Adobe Illustrator: un contour simple (chemin), un contour composite (chemin composé), une forme composite (forme composée) et des objets texte (texte et texte ponctuels sur le chemin). Pour le moment, le script ne fonctionne qu'avec des contours simples, comme le montre le code ci-dessous, où PathItem est un appel à l'élément 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; }; }; 

Avant cela, nous avons déclaré la variable clipPath , mais ne lui avons pas attribué de valeur.


  var clipPath; 

Cela signifie que sa valeur n'a pas encore été déterminée, c'est-à-dire ce n'est undefined . Si nous sélectionnons maintenant un masque dont le contour sera, disons, Chemin composé et exécutons le script, le programme produira une erreur sur la dernière ligne de la partie fonctionnelle du script,


  clipPath.remove(); 

puisque la condition dans la boucle ne sera pas remplie, la variable clipPath restera undefined et il est impossible d'appliquer la méthode remove() à quelque chose d'indéfini. Pour éviter cette situation, nous ferons ce qui suit: définissez clipPath sur null , ce qui, contrairement à undefined , est déjà quelque chose de plus spécifique que vous pouvez au moins vérifier.


Réfléchissons à la façon de déterminer si un chemin composé est le contour de notre masque. Lorsque je dis «réfléchissons», cela signifie que je suggère de consulter la documentation et de trouver la propriété dont nous avons besoin. Par analogie avec PathItem nous recherchons la propriété d' clipping . Il s'avère que l'objet CompoundPathItem n'a pas une telle propriété, mais il existe une propriété pathItems par laquelle vous pouvez accéder à des contours PathItem simples qui ont la propriété clipping .

Maintenant, nous pouvons transformer nos pensées / recherches en code. Tout d'abord, nous clipPath que clipPath n'a pas été défini dans l'itération précédente, puis nous copions le bloc de code déjà écrit et y apportons de petites modifications.


  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; }; }; }; 

En fait, les modifications n'affecteront qu'une seule ligne. Comme nous pouvons le voir ici, 'PathItem' est devenu 'CompoundPathItem', et une nouvelle construction a été ajoutée, 'pathItems [0]', avec laquelle nous nous référons à l'élément de chemin composé.


 if (sel[0].pageItems[i].typename == 'CompoundPathItem' && sel[0].pageItems[i].pathItems[0].clipping == true) { 

Voici le bloc fonctionnel de code qui a été créé jusqu'à présent.


  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; }; }; }; 

Le prochain «patient» est la forme composée. Ici ça devient assez intéressant! Dans la documentation, nous ne trouvons pas du tout un tel objet. Que faire Tout d'abord, définissons à quelle classe d'objets il appartient. Pour le savoir, nous allons écrire un petit code auxiliaire, que nous jetterons ensuite. Comme mentionné dans la première partie , nous n'abordons pas la question des outils utilisés pour écrire / déboguer du code. Par conséquent, supposons qu'il s'agit d'un fichier distinct, qui va ensuite simplement à la corbeille. Le code sera le suivant:


 var obj = app.activeDocument.selection[0]; alert(obj.typename); 

Dans la première ligne, nous créons un lien vers l'objet sélectionné, dans la seconde - nous affichons un message sur son type. Sélectionnez le contour du masque dans Adobe Illustrator, c'est-à-dire le même objet Compound Shape et exécutez le script. Dans la boîte de message, nous voyons que la forme composée est un PluginItem. Nous nous débarrassons du code auxiliaire, revenons à nouveau à la documentation, mais nous ne trouvons pas la propriété d'écrêtage ou pathItems dans PluginItem. En général, rien qui nous aiderait à indiquer sans équivoque que cet objet est le contour du masque. À partir du script, vous ne pouvez même pas déterminer de quel type de plug-in il s'agit. Un module externe et c'est tout!


C'est une embuscade! - vous hurlez dans vos cœurs. Et le cerveau travaille fiévreusement, espérant résoudre un problème insoluble. Et puis, après avoir parcouru toutes les options possibles et impossibles, vous appuyez désespérément sur Del et supprimez la forme composée détestée. Et ici, du coin de l'œil sur la palette Layers , vous remarquez qu'après cette action, le conteneur de masque, qui était Clip Group , est devenu simplement Group . Qu'est-ce que cela pourrait signifier Et le fait que la propriété clipped de l'objet clipped de true devenu false . La voici, une solution qui pourrait fonctionner! Bien sûr, cela est, dans l'ensemble, un hack, mais quelle différence cela fait-il s'il aide à déterminer le circuit souhaité.

L'algorithme pour déterminer le contour de masque représenté par l'objet Compound Shape sera alors le suivant: itérer sur tous les objets de masque dans une boucle et lorsque nous trouvons PluginItem, supprimez-le et vérifiez si la propriété clipped du conteneur de masque a changé. Si c'est devenu false , alors c'est notre circuit. La seule chose pour que ce hack fonctionne est de mettre à jour DOM Illustrator après avoir supprimé l'objet, ce qui peut être fait en utilisant la méthode app.redraw() . Ensuite, vous devez toujours vous rappeler de renvoyer l'objet distant, ce qui est fait par la méthode app.undo() .


Voici le code du chemin de la forme composée:


  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(); } }; }; }; 

Maintenant, de toutes les options possibles pour le type d'objets qui peuvent être le contour du masque, seul le texte (ou TextFrameItem , dans la terminologie des références de script d'illustrateur ) TextFrameItem . Nous revenons à la documentation encore et encore, nous n'y trouvons pas les propriétés de clipping . Mais cette fois, nous ne nous inquiétons plus tant de cela et découvrons calmement que TextFrameItem a une propriété kind qui détermine le type de l'objet texte ( TextType ). Nous constatons qu'il peut y avoir trois types: AREATEXT, POINTTEXT et PATHTEXT. Le premier type ne nous intéresse pas, car il ne peut pas être utilisé comme contour de masque, et les deux autres sont toujours aussi intéressants. Il ne reste plus qu'à trouver un hack qui nous aidera à déterminer maintenant non pas le contour, mais l'objet texte, qui est le contour du masque. Et ce hack sera l'équipe, Convertir en type de zone, qui convertira POINTTEXT en AREATEXT. Comme pour la forme composée, une modification implicite de la propriété clipped .


Par conséquent, le code d'un TextFrameItem de type POINTTEXT sera le suivant:


  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(); } }; }; }; 

Il ne reste qu'un TextFrameItem type PATHTEXT. Malheureusement, lors de la conversion de PATHTEXT en AREATEXT, la propriété clipped change pas. Mais puisque c'est le dernier candidat possible pour le titre "masque de contour", il est possible d'utiliser exactement son comportement. Autrement dit, nous vérifions qu'après avoir exécuté la commande Convert To Area Type , la propriété clipped reste true . Ci-dessous se trouve le code d'un TextFrameItem de type 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(); } }; }; }; 

Ainsi, si nous assemblons des morceaux de code écrits séquentiellement, y compris un bloc de vérifications, nous obtiendrons un tel code, dont l'exécution, comme indiqué dans la première partie de l' article, implémentera l'action de la nouvelle commande Expand Clipping Mask dans 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 ('  !'); }; 

Vous pouvez y mettre fin. Non, un point-virgule, c'est mieux.


J'espère qu'avec ces articles, je vous ai aidé à vous rapprocher un peu de votre objectif - commencer la programmation dans Adobe Illustrator. Merci de votre attention!

Source: https://habr.com/ru/post/fr452614/


All Articles