Print Modified Values, plugin for Designer

Ir a la versión en Español

I present you my first plugin for Adobe Substance 3D Designer: “Print Modified Values”. It’s going to be a long post, so I’m going to divide it into several sections:

  • How to install it
  • How to use it
  • Some comments and known limitations
  • Brief production diary – Problems that have arisen and how they have been solved

The purpose of this plugin is to add a Comment, as a “child” of a node, containing the information of those parameters that have been modified.

In February 2023 I will teach a Designer course in my town (I will share more information soon) and in the preparation of the contents for that course I immediately realized how useful this tool would be. I searched and asked around, but found nothing, so I got down to work myself.

After a lot of work, here you have the first version. I hope it will be useful, especially to those of you who like to spread the word by sharing screenshots of your Graphs. It is certainly saving me a lot of work, hopefully more than it has taken me to create it… 🤪 In any case I have learned a lot, not only about Designer API, but also about the internal structure of the application itself.


⬇️ Download “Print Modified Values”

DISCLAIMERS

SHORT: I have done my best to create a stable and robust tool. But use with caution, please. I recommend to create a copy of your graph before proceed to comment your nodes using this tool.

LONG: THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


How to install it

Once you have downloaded and unzipped the ZIP file, move the main folder “print_modified_values” (which also contains a .json file and another subfolder folder with the same name) to where you normally have other Designer plugins installed.

If you have never done it I recommend you to use this directory:

/Users/NAME/Documents/Adobe/Adobe Substance 3D Designer/python/sduserplugins/

Then start Designer, open Preferences / Projects, click on the vertical tab “User project” (inside Configuration / Project Files) and then on the horizontal tab Python. Click on the little + icon on the right and add the above directory. And as indicated in yellow, once this is done you will have to restart Designer.

Once Designer is restarted, the plugin should be loaded. But just in case, open Tools / Plugin Manager and check that the checkbox of our plugin is enabled. Doing this, by the way, you can activate or deactivate any plugin.

Plugin Manager

As soon as you install it, you will not see it appear in your top bar. To do this you must first create a new Substance Graph. Do it. Now you will see 2 new little buttons appear in the toolbar: the one without color can activate or deactivate the presence of the other one, in orange.

How to use it

It is very simple: suppose we have a Splatter Circular node that we have modified and we want to write down what parameters we have changed. We simply select it and click the little orange button. Automatically a Comment node will be added as a “child” of our Splatter (“child” means that when we move the node, the comment is moved with it).

You can also use “Q” as a keyboard shortcut instead of the button, as it is much more agile. I have chosen that letter because it evokes “Query” (ask the node about its own parameters). If you don’t like this shortcut or it conflicts with another one you already have, you can change it by editing the __init__.py file located inside the “print_modified_values” subfolder. But be careful not to touch anything else, if you don’t know what you are doing 😉.

Some comments and known limitations

One at a time

You can only add comments one at a time, do not select several nodes at once. It would not be very difficult to change the code to make it comment several nodes at a time, but for the moment I prefer to keep it this way, for several reasons. Among others, because if it gets stuck with one node, it would stop the whole process. I have also found that as we add comments we have to move the nodes to make room for others so that they do not overlap, so it is convenient to go one by one. In addition, when selecting several nodes, if we increase too much the number of them, we could start to “overload” the program.

“All by default”

When a node has not been modified, a Comment indicating “All by default” is also added. Even if I end up deleting it later, in principle I prefer it to work this way, because that way I am more sure that it has been processed correctly. If I didn’t add any Comment, I couldn’t be sure if it’s because it’s all by default or because there has been some internal error. When the plugin encounters a problem, it stops, giving an error and doesn’t add anything. That can only be seen if we open the console. I’ve also found that I’d rather see an “All by default” than see nothing, because otherwise I wouldn’t be sure if maybe I forgot to comment out that node…

Why does it sometimes do nothing?

In some nodes (SVG, Bitmap, FX-Map, Inputs… and likely some other) you will get a “Non supported” comment or maybe it does nothing. Actually it does, and what happens is that it gives us an error, as you can see in the console. There are many possible types of data structures. At the moment it covers all those that are within these groups: Enumerators, Arrays, Int, Int2, Float, Float2, Float3, Float4, ColorRGBA, Bool, String and Texture. But I am sure that I have left out some typology… 

For example, when the API gives us the info of a certain Position Random value, it does it this way:

('Position Random', 'SDValueFloat2(float2(0.17365,0.3249))')

And the plugin takes care of converting this to a much more readable and rounded one:

Position Random 0.17 0.32

And it is very likely that for a certain Property “x” of a certain Node “y” a data type is used that I have not covered in my code. Or maybe the error is due to some other reason, you never know…

Anyway, after using it for a few days in many graphs, I can tell you that it works great 99% of the time and has not caused me a single crash or application destabilization problem.

The shortcut “Q” no longer works

What I have seen very occasionally, is that suddenly the keyboard shortcut stops working (although the button still works). As I say it is very occasionally, and I have not managed to find out why it happens, a very rare thing. One way to get it back without restarting the application is to open the Plugin Manager, deactivate and re-activate the plugin. And then select or create a new Graph for it to load again. Then the keyboard shortcut will work again.

Brief production diary

The creation of this plugin has been a small odyssey. To begin with, I’m not a programmer, I don’t even consider myself a real hobbyist. My only experience with code has been creating some Python scripts for Modo and it’s been quite a few years… So from the beginning I ran into a lot of problems, mostly due to my total inexperience with the Designer API, but also some due to certain limitations of it and of course to my poor experience with Python itself (I can’t get to grips with the concepts of “Classes” and the constant use of “Self”).

In case any of you are interested in the more technical side of these matters, here is a sort of “production diary”.

Issue 1

I intended to query the selected node to find out what its default parameters were and put them in a dictionary. Then find out the current parameters -some modified and some not-, create a second dictionary, to finish comparing both dictionaries and see where the differences were (that is, only the modified parameters). Looking in the Designer API documentation I see that there is a getDefaultValue() so I try to use it, but no matter how many times I try, I can’t get it to give me those default values. Either I get error messages or “none” (!?) results.

So I go to the Substance Designer Discord where I know there is a good atmosphere, support and you can even chat with Adobe staff. After a few laps, an Adobe employee, alias est, confirms what I feared:

“Looking at our code, it seems default values for properties are not correctly implemented for some types of graphs. I created a ticket in our issue tracker to fix this in the future. A not very nice alternative for now could be to create a new node, get the property values and then delete the node”.

Oh my goodness, falling at the first hurdle! It’s bad luck, my first plugin and we start with problems….

So to continue, for the moment I decide to add a second “virgin” node to use it as a reference. Logically the goal is to do it in the code itself, but first let’s see if it works by adding it by hand.

Issue 2

The idea now is to select first the virgin node, then the modified one and create the two dictionaries and then compare them. I am making progress, but soon I realize that sometimes I get the information from the “wrong node”. The problem lies in a new limitation of the program that I already guessed and the good est confirms me again:

“Selections in Designer are not ordered. There are no guarantees about the order of selected items.”

That is, even if I select first the virgin node and then the modified one, Designer does not retain that information. It simply creates an array with the selected nodes, but without knowing in which order. So there is no way to be sure which is the virgin and which is the modified.

This is a bummer, but I’m still moving forward, because when I learn how to add the reference node automatically I will be able to solve it, I want to believe. Thanks to the help of another Adobe employee, Luca Giarrizzo, I manage to turn what until then was just basic code pasted into the Python Editor of Designer into a real plugin.

Issue 3

Once I have the plugin assembled and I manage to solve some other things (like the correct ordering of the parameters, so that they appear the same as in the node) I focus on trying to add the reference node internally, through code. And again I run into an obstacle.

I quickly learn that adding an Atomic Node is as simple as:

sdSBSCompGraph.newNode('sbs::compositing::blend') — It works.

However, if I try to do the same with an Instance Node:

sdSBSCompGraph.newNode('sbs::compositing::shape') — It doesn’t works.

Once again, good old est comes to the rescue to confirm that it’s not that simple:

“Content from the library or graphs in the explorer that you want to instanciate into a graph are not nodes, they are node instances (of a graph). The process to instance a graph into another graph is a bit convoluted today. Basically you need to open the package that contains the graph you want to instance, get an SDPackage, find the SDGraph that you want to instance and call SDGraph.newInstanceNode(sdGraphToInstance). We would like to make this process easier in a future version of Designer.”

After thinking about it and watching some tutorial I manage to find out how to add an Instance Node. For example, for a Shape it would be:

resource_dir = sd_application.getPath(SDApplicationPath.DefaultResourcesDir)
file_path = os.path.join(resource_dir, 'packages', 'pattern_shape.sbs')
package = sd_pkg_mgr.loadUserPackage(file_path)
resource = package.findResourceFromUrl('shape')
graph.newInstanceNode(resource)

Great! I know how to add any type of node.

Issue 4

But, wait a minute, there is still an important question: I only know how to add a node if I know beforehand whether it is Atomic or Instance, and also if I have two pieces of information: its Package and its Graph Instance.

So the first thing is to find out all the information of the (modified) node that we have selected, to be able to add another one like it, but virgin. I dedicate a considerable amount of time to the subject… and I don’t manage to find it out. I ask it again in the Discord channel… twice… and I don’t get any answer.

I spend a couple of days studying the video tutorial “Intro to Plugin Creation in Substance Designer” by one of the biggest Genius in Designer, Ben Wilson, and searching for information on my own… but finally I can’t figure it out.

In addition, I also detect a new problem: when I add an Instance Node with the code I have pasted above (learned from Ben’s tutorial) I detect that apart from adding the node to my current Graph it also opens the original Package of the node in the Explorer. Which means that I will also have to learn how to close it (which seems obvious but I can’t find it how).

And there are still more problems, not so serious, but I don’t want to drag this out too long. So, tired as I am, I give up. I can’t dedicate any more time to this…

As I had already shown on Twitter some screenshots of the plugin in action, even with that limitation of having to add an extra virgin node to use it as a reference, I decide to share it as I have it. And I even go as far as writing this post explaining all the problems and asking for help to try to improve it. That was on Sunday afternoon, November 13.

And suddenly there was light!

But Monday arrives, and when I had already decided to share it that way, as I say, suddenly a guy named Divyansh, another Discord user, answers me and gives me a good clue of how to continue. Finally I learn how to obtain the Package and the Graph Instance of the selected node.

Soon, already by private, the good Luca Giarrizzo also answers all my doubts, and little by little I see how to solve the problems: to know if the node I have selected is Atomic or Instance; to know how to continue operating with the two nodes, the original modified and the virgin reference, without having to select them; I discover myself how to delete the package that opens automatically and how to delete the reference node itself once its dictionary has been obtained…

Little by little I am polishing many things, especially how to get that instead of receiving an integer “3” when we have selected a certain parameter from a drop menu, to extract the information that this really corresponds to a “Multiply” mode, thanks to the use of Enumerators, to deal with certain inconsistencies in the assignment of integers in those same Enumerators, to know how to create dictionaries on the fly, “live”, interrogating different Properties of the node, to adapt the information we get from Levels if it acts in Grayscale or Color mode, etc., etc.

So finally, after a lot of work and detours (you don’t want to know the amount of hours and days I’ve spent on this…) I managed to make the plugin work exactly as I wanted it to. It only remains to test it for a few more days, preparing those training materials I was talking about at the beginning, and finally share it with the rest of users. Because I don’t feel like keeping something like this for myself, nor do I want to ask for money for it. There are many generous people who altruistically share a lot of useful information and resources, without asking for anything in return. And that’s something I like to participate in.

So finally I hope you too will find it as useful as I find it 🙂

Print Modified Values, plugin para Designer

Go to English version

Os presento mi primer plugin para Adobe Substance 3D Designer: “Print Modified Values”. Va a ser un post largo, así que lo voy a dividir en varias secciones:

  • Cómo instalarlo
  • Cómo usarlo
  • Algunos comentarios y limitaciones conocidas
  • Breve diario de producción – Los problemas que han ido surgiendo y cómo se han resuelto

El propósito de este plugin es el de añadir un Comment como “hijo” del nodo que tengamos seleccionado y que contenga la información de aquellos parámetros que han sido modificados.

En febrero de 2023 voy a dar un curso de Designer en mi ciudad (pronto compartiré más información) y en la preparación de los contenidos para ese evento me di cuenta de lo útil que sería esta herramienta. Busqué y pregunté, pero no encontré nada, así que me puse yo mismo manos a la obra.

Después de bastante trabajo, aquí tenéis la primera versión. Espero que os sea útil, especialmente a aquellos que os gusta divulgar compartiendo capturas de vuestros Graphs. A mí desde luego me está ahorrando mucho trabajo, espero que más del que me ha tomado crearlo… 🤪 En cualquier caso he aprendido mucho, no solo sobre API de Designer, sino también acerca de la propia estructura interna de la aplicación.


⬇️ Bajar “Print Modified Values”

AVISO LEGAL

Versión corta: He hecho todo lo posible para crear una herramienta estable y robusta. Pero úsala con precaución, por favor. Recomiendo crear una copia de tu archivo antes de proceder a comentar sus nodos utilizando este plugin.

Versión larga: EL SOFTWARE SE PROPORCIONA “TAL CUAL”, SIN GARANTÍA DE NINGÚN TIPO, EXPRESA O IMPLÍCITA, INCLUIDAS, ENTRE OTRAS, LAS GARANTÍAS DE COMERCIABILIDAD, IDONEIDAD PARA UN FIN DETERMINADO Y NO INFRACCIÓN. EN NINGÚN CASO LOS AUTORES O LOS TITULARES DE LOS DERECHOS DE AUTOR SERÁN RESPONSABLES DE NINGUNA RECLAMACIÓN, DAÑO U OTRA RESPONSABILIDAD, YA SEA EN UNA ACCIÓN CONTRACTUAL, EXTRACONTRACTUAL O DE OTRO TIPO, QUE SURJA DE, O ESTÉ RELACIONADA CON EL SOFTWARE O EL USO U OTRAS OPERACIONES CON EL SOFTWARE.


Cómo instalarlo

Una vez bajado y descomprimido el ZIP, trasladad la carpeta principal “print_modified_values” (que a su vez contiene un fichero .json y otra subcarpeta con el mismo nombre) a donde normalmente tengáis instalados otros plugins de Designer.

Si nunca lo habéis hecho, os recomiendo usar el siguiente directorio:

/Users/NOMBRE/Documents/Adobe/Adobe Substance 3D Designer/python/sduserplugins/

Luego arrancáis Designer, abrís Preferencias / Projects, pincháis en el tab vertical “User project” (dentro de Configuration / Project Files) y luego en el tab horizontal Python. Pincháis en el iconito + de la derecha y añadís el directorio anterior. Y tal como indica en amarillo, una vez hecho esto tendréis que reiniciar Designer.

Una vez reiniciado Designer ya debería estar cargado el plugin. Pero por si acaso abrís Tools / Plugin Manager y comprobáis que el checkbox de nuestro plugin está marcado. De esta manera, por cierto, podéis activar o desactivar cualquier plugin.

Plugin Manager

Nada más instalarlo todavía no lo veréis aparecer en vuestra barra superior. Para ello es necesario que primero creéis un nuevo Substance Graph. Hacedlo. Ahora veréis aparecer 2 nuevos botoncitos en la barra de herramientas: el que no tiene color puede activar o desactivar la presencia del otro, en naranja.

Cómo usarlo

Es muy sencillo: supongamos que tenemos un nodo Splatter Circular que hemos modificado y queremos anotar qué parámetros hemos cambiado. Simplemente lo seleccionamos y pulsamos el botoncito naranja. Automáticamente se nos añadirá un nodo Comment como “hijo” de nuestro Splatter (“hijo” significa que al mover el nodo, el comentario se traslada con él)

También podéis usar “Q” como atajo de teclado en lugar del botón, pues es mucho más ágil. He elegido esa letra porque evoca a “Query” (preguntar al nodo sobre sus propios parámetros). Si no os gusta ese atajo o entra en conflicto con otro que ya teníais, lo podéis cambiar editando el archivo __init__.py situado dentro de la subcarpeta “print_modified_values”. Pero cuidado no toquéis ninguna otra cosa, si no sabéis lo que estáis haciendo 😉

Algunos comentarios y limitaciones conocidas

De uno en uno

Solo se pueden añadir Comments de uno en uno, no seleccionéis varios nodos de golpe. No sería muy difícil cambiar el código para hacer que comente varios nodos de vez, pero de momento prefiero mantenerlo así, por varias razones. Entre otras, porque si con un nodo se atasca, se pararía todo el proceso. También he comprobado que conforme añadimos los comentarios tenemos que ir moviendo los nodos para ir haciendo un poco más de espacio para que no se solapen, así que conviene ir uno por uno. Además, al seleccionar varios nodos, si nos pasamos de cantidad, podríamos empezar a “sobrecargar” el programa.

“All by default”

Cuando un nodo no ha sido modificado se añade igualmente un Comment indicando “All by default”. Aunque luego acabe eliminándolo, en principio prefiero que funcione así, porque de esa forma estoy más seguro de que lo ha procesado correctamente. Si no añadiera ningún Comment, no podría estar seguro de si es porque está todo por defecto o porque ha habido algún error interno. Cuando el plugin encuentra un problema, se detiene, dando un error y no añade nada. Eso solo puede verse si abrimos la consola. También he comprobado que prefiero ver un “All by default” que no ver nada, porque de lo contrario no estaría seguro de si quizás olvidé comentar ese nodo…

¿Por qué a veces no hace nada?

En algunos nodos (SVG, Bitmap, FX-Map, Inputs… y seguro que algún otro) veréis que se añade el comentario “Non supported” o incluso directamente no hace nada. En realidad sí hace, o intenta hacer, y lo que ocurre es que nos da un error, como podéis comprobar en la consola. Existen muchos posibles tipos de estructuras de datos. De momento cubre todos los que están dentro de estos grupos: Enumerators, Arrays, Int, Int2, Float, Float2, Float3, Float4, ColorRGBA, Bool, String y Texture. Pero seguro que me he dejado alguna tipología… 

Por ejemplo, cuando el API nos entrega la info de un cierto valor de Position Random lo hace de esta forma:

('Position Random', 'SDValueFloat2(float2(0.17365,0.3249))')

Y el plugin se encarga de convertir esto a un mucho más legible y redondeado:

Position Random 0.17 0.32

Y es muy probable que para cierta Propiedad “x” de cierto Nodo “y” se use una tipología de dato que no tenga contemplada en mi código. O quizás el error es por algún otro motivo, vete a saber…

De todas formas, tras utilizarlo unos cuantos días en muchos graphs, os puedo decir que funciona de maravilla el 99% de las veces y no me ha causado ni un solo problema de cuelgue o desestabilización de la aplicación.

El atajo “Q” deja de funcionar

Lo que sí he visto muy de vez en cuando, es que de repente deja de funcionar el atajo de teclado (aunque sí sigue haciéndolo el botón). Como digo es muy de ciento a viento, y no he conseguido averiguar por qué ocurre, una cosa muy rara. Una forma de recuperarlo sin necesidad de reiniciar la aplicación es abrir el Plugin Manager, desactivar y volver a activar el plugin. Y entonces seleccionar o crear un nuevo Graph para que se cargue de nuevo. Entonces volverá a funcionar el atajo de teclado.

Breve diario de producción

La creación de este plugin ha sido una pequeña odisea. Para empezar yo no soy programador, ni siquiera me considero un verdadero aficionado. Mi única experiencia con código ha sido creando algunos scripts en Python para Modo y ya hace bastantes años de eso… Así que desde el principio me tropecé con multitud de problemas, la mayor parte debidos a mi total inexperiencia con el API de Designer, pero también alguno debido a ciertas limitaciones del mismo y por supuesto a mi pobre experiencia con el propio Python (no consigo hacerme con los conceptos de “Classes” y el constante uso de “Self”).

Por si a alguno os interesa la parte más técnica de estos asuntos aquí os dejo con una especie de “diario de producción”.

Problema 1

Inicialmente yo pretendía hacer un query al nodo seleccionado para saber cuáles eran sus parámetros por defecto y agregarlos a un diccionario. Luego averiguar los parámetros actuales —algunos modificados y otros no—, crear un segundo diccionario, para terminar comparando ambos diccionarios y ver dónde estaban las diferencias (es decir, solo los parámetros modificados). Buscando en la documentación de la API de Designer veo que existe un getDefaultValue() así que intento usarlo, pero por muchas vueltas que le doy, no consigo que me entregue esos valores por defecto. O bien obtengo mensajes de error o bien resultados “none” (!?)

Así que voy al Discord de Substance Designer donde sé que hay buen ambiente, soporte e incluso puedes conversar con el personal de Adobe. Tras unas cuantas vueltas, un empleado de Adobe con alias est me confirma lo que temía:

Mirando nuestro código, parece que los valores por defecto de las propiedades no están correctamente implementados para algunos tipos de gráficos. He creado un ticket en nuestro issue tracker para arreglar esto en el futuro. Una alternativa no muy agradable por ahora podría ser crear un nuevo nodo, obtener los valores de las propiedades y luego eliminar el nodo.

¡Vaya por Dios, la primera en la frente! Ya es mala suerte, mi primer plugin y empezamos con problemas…

Así que para continuar, de momento decido añadir un segundo nodo “virgen” para usarlo de referencia. Lógicamente el objetivo es hacerlo en el propio código, pero primero vamos a ver si funciona añadiéndolo a mano.

Problema 2

La idea ahora es seleccionar primero el nodo virgen, luego el nodo modificado y crear los dos diccionarios, para después compararlos. Voy avanzando, pero pronto me doy cuenta de que a veces me da la información del “nodo equivocado”. El problema estriba en una nueva limitación del programa que ya intuyo y el bueno de est me vuelve a confirmar:

“Las selecciones en Designer no están ordenadas. No hay garantías sobre el orden de los elementos seleccionados.”

Es decir, que aunque yo seleccione primero el nodo virgen y luego el modificado, Designer no retiene esa información. Simplemente crea un array con los nodos seleccionados, pero sin saber en qué orden. Así que no hay forma de estar seguros de cuál es el virgen y cual el modificado.

Esto es un fastidio, pero sigo avanzando, pues cuando aprenda a añadir el nodo de referencia automáticamente quiero creer que podré solventarlo. Gracias a la ayuda de otro empleado de Adobe, Luca Giarrizzo, consigo convertir lo que hasta ese momento no era más que código básico pegado en el Python Editor de Designer en un verdadero plugin.

Problema 3

Una vez tengo armado el plugin, consigo resolver algunas otras cosas (como la correcta ordenación de los parámetros, para que aparezcan igual que en el nodo) y me centro en intentar añadir el nodo de referencia internamente, a través de código. Y de nuevo me enfrento con un obstáculo.

Enseguida aprendo que añadir un Atomic Node es tan simple como:

sdSBSCompGraph.newNode('sbs::compositing::blend') — Funciona

Sin embargo, si intento hacer lo mismo con un Instance Node:

sdSBSCompGraph.newNode('sbs::compositing::shape') — No funciona

Otra vez viene el bueno de est al rescate para confirmarme que no es tan sencillo:

“El contenido de la Library o los Graphs del Explorer que se quieren instanciar en un gráfico no son nodos, son instancias de nodos (de un gráfico). El proceso para instanciar un gráfico en otro gráfico es un poco enrevesado hoy en día. Básicamente necesitas abrir el package que contiene el Graph que quieres instanciar, obtener un SDPackage, encontrar el SDGraph que se quiere instanciar y llamar a SDGraph.newInstanceNode(sdGraphToInstance). Nos gustaría facilitar este proceso en una futura versión de Designer.”

Tras darle vueltas y ver algún tutorial consigo averiguar cómo añadir un Instance Node. Por ejemplo, para un Shape sería:

resource_dir = sd_application.getPath(SDApplicationPath.DefaultResourcesDir)
file_path = os.path.join(resource_dir, 'packages', 'pattern_shape.sbs')
package = sd_pkg_mgr.loadUserPackage(file_path)
resource = package.findResourceFromUrl('shape')
graph.newInstanceNode(resource)

¡Genial, ya sé cómo añadir cualquier tipo de nodo!

Problema 4

Pero, un momento, todavía queda una cuestión importante: solo sé cómo añadir un nodo si de antemano conozco si es Atomic o Instance, y también si tengo dos datos: su Package y su Graph Instance.

Así que lo primero es averiguar toda esa info del nodo (modificado) que tengamos seleccionado, para poder añadir otro igual, pero virgen. Le dedico bastante tiempo al tema… y no consigo averiguarlo. Vuelvo a preguntarlo en el canal de Discord… por dos veces… y no obtengo ninguna respuesta.

Me paso un par de días estudiando el vídeo tutorial “Intro to Plugin Creation in Substance Designer” de uno de los mayores cracks de Designer, Ben Wilson, y buscando información por mi cuenta… pero finalmente no consigo averiguarlo.

Además, también detecto un nuevo problema: cuando añado un Instance Node usando el código que he pegado arriba (aprendido del tutorial de Ben) detecto que además de añadirse el nodo a mi Graph actual también se abre el Package original del nodo en el Explorer. Lo cual significa que también tendré que aprender a cerrarlo (cosa que parece obvia pero no logro encontrar).

Y todavía aparecen más problemas, no tan graves, pero no quiero alargar esto demasiado. Así que ya cansado, tiro la toalla. No puedo dedicarle más tiempo a esto…

Como ya había enseñado en Twitter algunas capturas del plugin en acción, aún con esa limitación de tener que añadir un nodo extra virgen para usarlo de referencia, decido compartirlo tal como lo tengo. E incluso llego a escribir este post explicando todos los problemas y pidiendo ayuda para intentar mejorarlo. Eso fue el domingo 13 de noviembre por la tarde.

¡Y de repente se hizo la luz!

Pero llega el lunes, y cuando ya había decidido compartirlo de esa forma, como digo, de repente un tal Divyansh, otro usuario de Discord, me responde y me da una buena pista de cómo seguir. Por fin aprendo cómo obtener el Package y el Graph Instance del nodo seleccionado.

Enseguida, ya por privado, el bueno de Luca Giarrizzo también contesta a todas mis dudas, y poco a poco voy viendo cómo resolver los problemas: saber si el nodo que tengo seleccionado es Atomic o Instance; saber como seguir operando con los dos nodos, el original modificado y la referencia virgen, sin necesidad de seleccionarlos; yo mismo descubro cómo eliminar el package que se abre automáticamente y cómo eliminar el propio nodo de referencia una vez obtenido su diccionario…

Poco a poco voy puliendo muchas cosas, especialmente cómo conseguir que en lugar de recibir un número entero “3” cuando tenemos seleccionado cierto parámetro de un drop menú, extraer la información de que eso corresponde realmente a un modo “Multiply”, gracias al uso de los Enumerators, lidiar con ciertas inconsistencias en la asignación de enteros en esos mismos Enumerators, saber cómo crear diccionarios sobre la marcha, “en vivo”, interrogando a distintas Properties del nodo, conseguir adaptar la información que obtenemos de Levels si este actúa en modo Grayscale o Color,  etc, etc

Así que finalmente, tras mucho trabajo y rodeos (no queráis saber la cantidad de horas y días que he dedicado a esto…) consigo hacer que el plugin funcione exactamente como yo quería. Solo queda probarlo durante unos días más, preparando esos materiales formativos de los que os hablaba al principio, y ya por fin compartirlo con el resto de usuarios. Porque una cosa así no me apetece guardarla para mí solo, ni tampoco pedir dinero por ella. Hay mucha gente generosa que comparte de forma altruista cantidad de información y recursos de muchísima utilidad, sin pedir nada a cambio. Y eso es algo de lo que me gusta participar.

Así que finalmente espero que vosotros también lo encontréis tan útil como a mí me lo parece 🙂