Une application de dessin sans le “undo” (annuler ou retour arrière ? en fait je sais pas trop, je n’utilise jamais mon ordi en français) c’est très handicapant, d’autant que je conçois Paintual comme une plateforme d’essai, ce qui implique forcément faire et défaire.

J’ai révisé tout le code des grands cycles de l’application:
– workflow (qui contenait VIOME [le gestionnaire direct des actions de l’utilisateur] qui a disparu depuis) qui détermine les actions de l’application selon les séquences d’actions de l’utilisateur (clics de souris, déplacements, sélection d’outils, etc.);
– le DrawingBoard (le plan de travail) en deux parties : la surface de dessin (PaintualCanvas) comme telle et son enveloppe (le DrawingBoard) avec les barres de défilement et le contrôle de zoom;
– et la VisualPropertyPage, le panneau d’édition des propriétés des outils de dessin, généré dynamiquement selon l’exposition des paramètres/propriétés des effets et outils au moyen d’attributs et de la réflexion.

Trois cycles qui s’imbriquent et qui me donnent souvent des maux de tête. C’est un peu bête que ça soit si compliqué puisque ce sont trois concepts que j’ai créés et développés progressivement au fur et à mesure que je voulais ajouter des fonctionnalités à l’application. Petit ménage, donc, qui a fait du bien et qui m’a réconforté quant à leur relative complexité/simplicité selon le point de vue.

Alors ça devenait facile d’ajouter le si nécessaire Undo : suffit d’une pile d’historique de travail qui enregistre les différentes actions de l’utilisateur. Pour simplifier, une action consiste soit en un tracé complet avec la souris ou le stylet (cliquer, glisser, relâcher l’outil) ou l’application d’un effet. Cliquer sur Undo reviendrait simplement à afficher l’image d’avant modification et d’enlever une action de la pile d’historique de travail.

Au travail : construction de la pile de type LIFO (Last In, First Out, c’est-à-dire que la série des entrées est séquentielle et chronologique [du plus ancien au plus récent] mais que le retrait ne peut se faire que du plus récent vers le plus ancien)… ça existe déjà tout fait dans le .NET Framework, tant mieux. Créer une classe d’item d’historique qui contient l’image entière avant modification et le type d’outil utilisé pour la modification.

Simple. Ça ne marche pas.

À la première action correspond une première entrée dans la pile, c’est assez évident. Si on clique sur Undo, mais j’avais fait le code de sorte qu’en enlevant un élément de la pile je réaffichais l’image contenue dans l’élément précédent de la pile. Hors, il n’y a pas d’élément précédent. Donc, ajout d’un élément d’historique de départ, un canevas vide.

Erreur de code où je créais deux éléments d’historique : un pour le tracé et un autre pour la sélection d’un outil ou d’un effet. Perdu une heure là-dessus.

Autre erreur : l’accumulation indéfinie de copies d’images “clichés en cours de travail” gonfle dans la mémoire de l’ordi à un rythme stupéfiant (en mémoire les images sont décompressées; le moindre petit jpg est en fait un gros monstre). Bon, il faut pour l’instant limiter la pile à, disons, 10 degrés de retour. Mais ça signifie que je dois retirer le plus vieil élément mais la pile n’est pas conçue comme ça. Sans compter que le premier élément doit rester puisque c’est l’état d’origine du dessin avant toute modification.

Moins simple qu’il n’y paraît mais c’est à peu près fonctionnel.

J’ai à repenser les détails. La beauté de la chose, cependant, c’est l’intégration incroyablement facile de l’historique dans le Workflow comme si, dès le départ, j’avais prévu le coup, ce qui n’est pas du tout le cas !

À mettre en place aussi c’est la compression des images de chaque étape. Deux choses à appliquer:
– déterminer les zones qui ont changé et n’enregistrer que des portions d’images. Déjà là il y a une réduction considérable de la taille mais la détection prend du temps, donc il faut transférer le travail dans une queue de thread pour ne pas bloquer l’interface, ce qui veut dire aussi savoir détecter la fin du travail dans le thread pour savoir quand on peut retirer un élément de l’historique après qu’il ait été effectivement enregistré;
– sauvegarder les images d’étapes dans des fichiers temporaires sur disque afin de libérer la précieuse mémoire de l’ordi (avec 32 GB de RAM j’ai la paix pour un bout avec de petites images, mais avec les formats de 6000 x 6000 pixels qui me permettent une finesse de détails intéressante, la mémoire se sature rapidement).

Donc je focus sur cette fonctionnalité jusqu’à satisfaction.

Entre temps, je vous laisse avec GLIC , qui roule sous Processing, et dont je veux incorporer certaines fonctionnalités dans Paintual avec, éventuellement si possible, de pouvoir “GLICquer” certaines portions d’une image avec des outils de dessin, soit du glitch-painting. Pour avoir parcouru le code de GLIC, ça sera un assez long travail.