Bon, c’est quoi cette feature qui permet d’écrire des nodes ?
Une façon de voir les choses serait de dire qu’on a juste ajouté le support du C# à votre environnement de développement favvvvori. Parce que même si vous ne vous voyez pas comme un développeur, vous programmez déjà : vous le faites juste de façon visuelle. Et vous construisez déjà vos propres nodes en créant des sous-patches ou des modules.
C’est juste que désormais, vous disposez de deux façons de les créer : les patcher visuellement ou les écrire sous forme de code.
Pour ne pas avoir à utiliser les termes "visuellement", "textuellement", "node vvvv" ou "node C#", on utilisera seulement "patch" et "plugin". Un plugin n’est ni plus ni moins qu’une node écrite sous forme de code.
La nouveauté, c’est la façon dont vous pouvez écrire vos plugins : dynamiquement dans vvvv, ce que devrait vous faciliter la tâche pour vous mettre au C#.
Maintenant, pourquoi vous devriez utiliser C# ?
Premièrement, il y a certaines tâches en programmations qui sont plus simples, plus rapides ou plus performantes en C#, chaque langage de programmation ayant ses avantages et ses inconvénients. Deuxièmement, il y a des choses que vous ne pourrez pas faire en patchant, comme par exemple utiliser les librairies hyper puissantes du framework .NET et appeler ses méthodes directement.
Pour « patcher » une nouvelle node, vous feriez CTRL+MAJ+P pour placer un patch vide dans votre patch courant, y créeriez quelques IOBoxes pour vos entrées/sorties, vous leur donneriez un nom et les connecteriez pour faire votre sauce dans votre sous-patch/module.
Pour « écrire » une nouvelle node, il n’y a pas de raccourci permettant de créer un plugin C# vide. Nous avons pensé qu’il serait plus simple de commencer par un template hyper simple disposant déjà d’une entrée et d’une sortie.
Donc au lieu de créer un fichier texte vide, commencez par sélectionner une node template comme Template(Value). Après l’avoir créée, vous verrez qu’elle marche déjà : elle multiplie son entrée par deux. Un clic-droit dessus vous en montrera le contenu (exactement de la même manière qu’un clic-droit sur un sous-patch ouvre ledit patch). Gardez à l’esprit que vous ne pouvez pas modifier un template : vous devez le cloner. Pour ce faire, ouvrez le node-browser avec un double-clic gauche dans votre patch, commencez à taper « tem » et choisissez le template à cloner en appuyant sur CTRL.
Dans la boîte de dialogue, choisissez un nom.
Vous pouvez à tout moment choisir un nouveau nom, une nouvelle catégorie ou définir une nouvelle version en clonant votre node. C’est la façon la plus pratique de renommer un plugin de façon cohérente. Sous le capot, plusieurs entités comme les fichiers, les dossiers et les infos sont renommées, donc utilisez cette feature et n’ayez pas peur de donner des noms débiles à vos plugins : vous avez un moyen hyper rapide de changer ça …
La dernière chose dont vous aurez besoin est une petite idée. Pour débuter, pensez en terme de valeurs, de couleurs ou de strings (chaînes de caractères). Un plugin répondant à une logique simple, et qui ne nécessiterait pas plus de 5 nodes dans un patch.
Connectez des IOBoxes sur les entrées et sorties de votre plugin pour voir comment la sortie se met à jour après avoir modifiée et sauvegardé (CTRL+S dans l’éditeur de code) votre fichier .cs. Sauvegardez votre patch de test dans le dossier de votre projet se trouvant dans dans vvvv\plugins\VotrePlugin et nommez-le "VotrePlugin (Category Version) help.v4p".
L’éditeur de code supporte le "code folding". Cela signifie juste que vous pouvez cacher/montrer certains bouts de votre code en utilisant les boutons -/+ situés à gauche de l’éditeur.
Les regions sont délimitées par :
#region UNEREGION #endregion UNEREGION
Où UNEREGION peut avoir n’importe-quel nom (et peut comporter des espaces).
Le template dispose de base des regions "usings", "PluginInfo" et "fields & pins".
L’éditeur de code va automatiquement utiliser certaines couleurs et types de police pour faciliter la lecture de votre code.
Après un certain temps vous trouverez ce retour d’info très utile, puisqu’il vous indique que votre code est bien formaté.
La première feature du C# à laquelle vous êtes confrontés est le namespace. Les namespaces sont simplement une façon de structurer l’énorme collection de librairies .NET, et celles de vvvv.
Pas besoin de connaître toutes ces librairies, vous devez juste comprendre le concept.
Vous pouvez comparer ça aux animaux et à leur classification. Vous n’avez pas besoin de connaître tous les animaux pour comprendre le truc. Classification scientifique des espèces
Vous pouvez aussi voir ça comme une structure hiérarchique :
Vehicule.Voiture.Peugeot.205
On va du moins spécifique au plus spécifique, les points marquant les sous-dossiers.
Toutes les entités de .NET peuvent être atteintes via un chemin d’accès étant la combinaison des namespaces dans lesquels l’entité est définie, et le nom de cette entité.
VVVV.PluginInterfaces.V2.ISpread<bool>
VVVV.PluginInterfaces.V2 est le namespace où ISpread<bool> (un spread de booléens) est défini.
Les usings sont là pour vous faire taper moins de code et vous permettre par exemple de n’écrire que ISpread<bool>. Pour que ça marche, vous devez utiliser (use) le namespace (VVVV.PluginInterface.V2) au début de votre code.
Dans ce template, notez que seulement quelques namespaces standart sont utilisés. Deux de .NET :
using System; using System.ComponentModel.Composition;
et cinq de vvvv
using VVVV.PluginInterfaces.V1; using VVVV.PluginInterfaces.V2; using VVVV.Utils.VColor; using VVVV.Utils.VMath; using VVVV.Core.Logging;
En voilà quelques-uns pour vos expérimentations futures : namespaces.
De la même manière, votre nouvelle node est une entité définie dans un namespace. Vu que c’est une node, on garde le namespace VVVV.Nodes.
namespace VVVV.Nodes { }
Pour le moment, il n’y a aucun problème à accepter et ignorer tous ces trucs sur les namespaces, et continuer la lecture de ce tutoriel.
Gardez juste en tête que les accolades { et } marquent un bloc de code, et que tout le reste du fichier est compris dans le bloc du namespace VVVV.Nodes.
De manière générale, les blocs de code sont nécessaires pour structurer votre programme, et il est très fréquent qu’ils soient imbriqués. Par conséquent, il est de bon goût d’indenter le code compris dans les blocs grâce à TAB, afin que la structure en soit plus évidente aux yeux des humains (qui, en général, ne sont pas très sensibles aux accolades).
[PluginInfo(Name = "Template", Category = "Value", Help = "Basic template with one value in/out", Tags = "")]
La partie Plugin Info sert à déclarer votre node. Elle signifie que la classe définie plus loin sera une node. Seules les classes introduites par une signature PluginInfo seront listées dans le nodebrowser.
Plus d’attributs PluginInfo
Une node est une classe, et une classe un bloc très basique en C#. Il s’agit juste d’accolades autour de données et de code. C’est ce dont vous aurez besoin pour écrire une node !
La partie « données » : les entrées et sorties de votre node (en grande partie).
[Input("Input", DefaultValue = 1.0)] ISpread<double> FInput;
Comme dans la declaration de la node, nous avons
Notez qu’un field sans signature de pin peut parfaitement faire sens. Il s’agit alors de données privées dont vous avez besoin pour vos calculs mais que vous ne voulez pas montrer à l’utilisateur de votre node.
Si vous changez d’avis et voulez rendre ce field configurable par l’utilisateur, vous n’avez qu’à placer une signature “inputpin” et vous pourrez alors recevoir des données de l’utilisateur.
Vous pouvez aussi avoir besoin de montrer des calculs. Pour ce faire, ajoutez une signature “outputpin“ sous le field et la node aura une nouvelle pin de sortie.
[Output("Step 2 in big Calculation")]
Il est obligatoire de spécifier si la pin sera une entrée ou une sortie, et de lui donner un nom. Les autres attributs sont optionnels.
Comment configure les pins : Pin Attributes
ISpread<double> FInput; ISpread<double> FOutput;
Ci-dessus, vous pouvez voir la déclaration en C# brut d’une entrée et d’une sortie dans le Template.
A gauche, vous voyez le type de la pin (ISpred<double>), et à droite le nom interne à C# (FInput, FOutput), qui commence par un "F" comme "field".
La déclaration doit coller au schéma FieldType FieldName;
Notez que dans notre exemple, le type de donnée pour l’entrée et la sortie est le même : juste un spread de doubles (ISpread<double>). Un double est un nombre à virgule flottante (en termes informatiques), qui est également un nombre réel (en termes mathématiques), qui n’est en fait rien d’autre qu’un nombre (pour tout le monde). N’hésitez pas à regarder d’autres templates pour voir comment faire des choses avec d’autres spreads (comme un spread de strings par exemple).
En général, on dit que toutes les entrées et sorties sont de type ISpread<T> où T signifie le type, et qui peut être :
Et ainsi de suite.
Seuls les fields de type ISpread<T> (avec n’importe-quel « T ») peuvent devenir des pins avec une signature de pins.
[Import()] ILogger Flogger;
ILogger est une interface sur laquelle vous pouvez appeler la méthode Log(). Une méthode, c’est un truc qui fait quelque-chose, dans le cas de Log() : écrire dans un Renderer (TTY). Flogger peut s’avérer très utile pour débugger vos programmes.
Nous venons juste d’apprendre qu’une méthode C# fait quelque chose.
Justement, ne voulions-nous pas que nos nodes fassent quelque chose ?
public void Evaluate(int SpreadMax) { }
déclare une nouvelle méthode.
Vous pouvez déclarer plusieurs méthodes dans vos classes.
La méthode Evaluate est une feature spéciale de vvvv. Elle est appelée lorsque les valeurs de sortie de la node sont nécessaires.
Elles sont nécessaires lorsque
Vous pouvez vérifier que votre node n’évalue que lorsque son output est nécessaire en suivant ces étapes :
Vous devriez constater que la node ne fait ce qu’on lui demande que quand sa sortie est nécessaire : elle l’est à cause du tooltip, du coup, Evaluate est appelée, ce qui résulte en une série de message dans le Renderer (TTY) (expliqué plus loin). Le fait de ne plus survoler la pin stoppe l’envoi de messages dans le TTY et démontre par conséquent qu’Evaluate n’est plus appelée.
Si vous voulez vous assurer que la node n’est appelée qu’à chaque frame (indépendamment du fait que sa valeur soit nécessaire), il vous faudra ajouter un attribut à PluginInfo :
[PluginInfo(..., AutoEvaluate = true)]
Tout ce que vous voulez que votre node fasse doit être placé dans la méthode Evaluate, entre ses accolades.
FOutput.SliceCount = SpreadMax;
nous dit que la taille du spread de sortie doit être égale au plus gros spread de toutes les entrées. Etant donné que pour l’instant nous n’avons qu’une seule entrée, les spreads d’entrée et de sortie auront le même slicecount.
for (int i = 0; i < SpreadMax; i++) FOutput[i] = FInput[i] * 2;
Pour chaque slice, calculer la sortie en multipliant la slice d’entrée par deux.
Notez que l’on pourrait en faire plus dans la boucle for. Cependant, vous auriez une fois encore besoin d’un bloc de code :
for (int i = 0; i < SpreadMax; i++) { someCommand; otherCommand; }
Flogger.Log(LogType.Debug, "Logging to Renderer (TTY)");
écrit des messages de debug dans la console.
De manière générale, vous utiliserez tout ce qui concerne le log pour vérifier que du code ait bien été exécuté (par exemple à l’intérieur d’un if).
Dynamic Plugin Tutorials: Des choses à essayer pour se lancer dans la programmation en C#
Learn C#
anonymous user login
~4h ago
~7d ago
~7d ago
~7d ago
~21d ago
~1mth ago
~1mth ago
~1mth ago
~1mth ago
~1mth ago