Quindi cos'è questa nuova possibilità di scrivere i propri nodi?
Da un certo punto di vista possiamo dire che abbiamo semplicemente aggiunto il supporto del linguaggio C# nel vostro ambiente di svvvviluppo preferito.
Perché anche se non vi vedete come sviluppatori, in realtà quando usate vvvv state già programmando, solo che lo state facendo graficamente; soprattutto state generando dei nodi quando create moduli o subpatch.
Quindi da ora in avanti avete una possibilità in più per generare dei nodi, graficamente e con il testo.
Per semplificare la terminologia utilizzata, ci riferiremo ai nodi generati graficamente come "patch", ed ai nodi generati tramite testo scritto come "plugin".
Una delle nuove prospettive (tra le tante) che vi offre vvvv è quella di scrivere plugin in maniera dinamica, facilitando così il vostro ingresso nella programmazione in C#.
Perché dovreste usare C#?
Innanzitutto ci sono dei compiti nella programmazione che sono più semplici, veloci o comunque più prestanti in C#, dato che ogni linguaggio di programmazione ha i suoi pro e contro.
Possiamo aggiungere inoltre che ci sono cose che non possono essere realizzate con una patch, come ad esempio usare alcune potenti librerie .NET e chiamarne i metodi direttamente.
Per patchare un nuovo nodo, usereste la combo Ctrl + Shift + P per inserire una patch vergine all'interno di un'altra patch, continuando con il generare alcuni IOBox per i dati in ingresso ed uscita, dandogli un nome e connettendoli ai nodi: esattamente come nel normale flusso di lavoro di una patch di vvvv.
Per scrivere un nuovo nodo non c'è una scorciatoia da tastiera. Abbiamo pensato che fosse più semplice cominciare con un modello molto semplice che presenta già pin Input ed Output.
Non genereremo un file di testo, ma tramite il NodeBrowser sceglieremo un nodo: ad esempio Template (Value).
A questo punto potrete notare come il nodo possieda già una funzionalità, infatti moltiplica l'Input per due. Clic destro sul nodo, si apre una nuova finestra che mostra il codice del plugin (esattamente la stessa procedura per mostrare il contenuto di un modulo o di una subpatch).
Non è possibile modificare un template, è necessario clonarlo: doppio clic sinistro, cercate template e selezionate tenendo premuto Ctrl.
Nella finestra di dialogo scegliete un nuovo nome.
Potrete modificare il nome, name, la categoria, category o la versione, version, in qualsiasi momento, quando clonate un template. Questa è la maniera più conveniente di eseguire questo passaggio. Sotto la superficie, tutta una serie di entità come file, cartelle, classi ed informazioni vengono rinominate; usate perciò questa funzione senza preoccuparvi troppo, dato che basterà un clic per correggere il tutto.
L'ultima cosa che vi serve è una piccola idea. Per cominciare, pensiamo in termini numerici, values, di colori, colors, o di stringhe di testo, strings.
Un piccolo nodo che esegue una logica semplice richiederebbe fino a cinque nodi in una patch.
Connettete IOBox ai pin di Input ed Output per controllare istantaneamente i vari cambiamenti che seguono al salvataggio del file .cs (Ctrl + S nell'editor di codice). Salvate la vostra patch di prova nella directory del progetto, che potrebbe essere vvvv\plugins\IlMioPluginDinamico e chiamatela IlMioPluginDinamico (Category Version) help.v4p.
L'editor di codice supporta il code folding: questo significa che potete mostrare\nascondere certe regioni del vostro codice cliccando sulle icone -\+ alla sinistra del codice.
Le regioni sono contrassegnate con
#region SOMEREGION #endregion SOMEREGION
dove SOMEREGION sta per qualsiasi nome di regione (che può includere spazi).
Il template presenta le regioni "usings", "PluginInfo" and "fields & pins".
L'editor usa automaticamente certi colori e stili di carattere per rendere il codice più leggibile.
In generale si può dire che il tipo di token decide quale colore o stile di carattere viene usato.
Dopo un po' di tempo beneficerete di questa risposta immediata, dato che mostra se il codice sia ben formattato.
La prima caratteristica del linguaggio C# con la quale vi confronterete è lo spazio dei nomi, namespaces. Con namespaces si intende un sistema per strutturare l'enorme collezione di librerie .NET e quelle di vvvv.
Non è necessario conoscere tutte queste librerie, è sufficiente conoscere e comprendere il concetto.
Per fare un paragone, si può pensare agli animali ed a come vengono classificati secondo la classificazione scientifica.
Potete immaginare anche una struttura gerarchica generica:
Vehicle.Car.VW.Polo
Si parte dal generale per arrivare ad un elemento specifico; i punti indicano il passaggio da uno stadio ad un altro.
Tutte le entità in .NET possono essere raggiunte da un percorso globale, che consiste in una combinazione di namespaces, nella quale l'entità viene definita, e del nome dell'entità.
VVVV.PluginInterfaces.V2.ISpread<bool>
VVVV.PluginInterfaces.V2 è lo spazio dei nomi nel quale si definisce "ISpread<bool>" (uno spread di booleane).
Le dichiarazioni using esistono per ridurre il codice, perché consente di inserire solo ISpread<bool>. Perché funzioni, è necessario usare lo spazio dei nomi VVVV.PluginInterfaces.V2 una volta all'inizio del codice.
Per ora notate come solo alcuni namespace standard vengono usati. Due di questi fanno parte dello spazio dei nomi di .NET:
using System; using System.ComponentModel.Composition;
e 5 namespace di vvvv:
using VVVV.PluginInterfaces.V1; using VVVV.PluginInterfaces.V2; using VVVV.Utils.VColor; using VVVV.Utils.VMath; using VVVV.Core.Logging;
Qui troverete altri namespace per gli esperimenti futuri: Spazio dei Nomi.
Anche il vostro nuovo nodo è un entità definita in un spazio dei nomi. Dato che si tratta di un nodo, manteniamo lo spazio dei nomi "VVVV.Nodes".
namespace VVVV.Nodes { }
Per il momento, va assolutamente bene accettare il concetto di spazio dei nomi ed accantonarlo, ma solo per proseguire nel tutorial.
Notate come le parentesi {} marcano un blocco di codice e come tutto il resto del file rimanga all'interno del blocco di codice dello spazio dei nomi VVVV.Nodes.
I blocchi di codice sono necessari per strutturare il codice ed è veramente comune che i blocchi siano nidificati, nested. Viene quindi inteso come buon stile indentare il codice usando la tabulazione, per rendere più evidente la natura nidificata di questa struttura agli umani (che di solito si fanno sfuggire le parentesi {}).
[PluginInfo(Name = "Template", Category = "Value", Help = "Basic template with one value in/out", Tags = "")]
PluginInfo fa parte della dichiarazione del nodo: stabilisce che la classe definita più in basso è un nodo. Solo classi che sono contrassegnate da tale contrassegno, saranno elencate nel NodeBrowser.
Consultate inoltre Attributi di PluginInfo.
Un nodo è una classe, ed una classe è un blocco di costruzione di base in C#. Si tratta giusto di parentesi attorno a dati e codice; ne avete bisogno per scrivere i nodi.
La parte dati: in maggioranza Input ed Output del nodo.
[Input("Input", DefaultValue = 1.0)] ISpread<double> FInput;
Come nella dichiarazione dell'intero nodo, abbiamo ancora
Tenete presente che campi senza il contrassegno, signature, di pin possono avere perfettamente senso. Si tratterebbe quindi di una parte privata di dati, di cui possiamo avere bisogno per fare i calcoli, ma che non vogliamo mostrare all'utente sotto forma di pin.
Quando doveste cambiare idea, volendo fornire all'utente qualcosa di configurabile, potrete inserire un contrassegno di Input pin: l'utente avrà quindi un pin con cui affaccendarsi.
Potreste anche voler mostrare alcuni pre-calcoli all'utente: aggiungete quindi un contrassegno di Output pin sopra il campo dati ed il nodo avrà un altro pin di Output.
[Output("Step 2 in big Calculation")]
Per il contrassegno di un pin è obbligatorio specificare se è di Input o di Output, e dargli un nome. Tutti gli ulteriori attributi sono opzionali.
Come configurare i pin: Attributi del Pin.
ISpread<double> FInput; ISpread<double> FOutput;
Qui sopra vedete la dichiarazione C# di Input ed Output in Template.
Alla sinistra c'è il tipo, type, di dato del pin (ISpread<double>), a destra il nome C# interno, che normalmente inizia con "F", che sta per Field, campo.
La dichiarazione segue lo schema FieldType FieldName;, TipoDelCampo NomeDelCampo.
Notate come nel nostro esempio il tipo di dati per Input ed Output sia lo stesso: solo uno spread di double.
Un double è un numero in virgola mobile (termine informatico), che è un numero reale (termine matematico) che è semplicemente un numero (per tutti). Consultate altri template per lavorare con spread di altri tipi di dati (come le stringhe).
In generale diciamo che tutti gli Input ed Output sono del tipo ISpread<T>, dove T sta per il tipo dell'elemento che può essere:
e così via.
Solo campi del tipo ISpread<T> (con qualsiasi T) possono essere convertiti in pin aggiungendo il contrassegno di pin.
[Import()] ILogger Flogger;
ILogger è una interfaccia tramite cui si può chiamare il metodo Log(). Un metodo è qualcosa che fa qualcosa, in questo caso scrivere in un nodo Renderer (TTY): così Flogger può essere facilmente usato per restituire qualche informazione utile al debug.
Abbiamo appena imparato che un metodo C# fa qualcosa.
Ma anche il nostro nodo dovrebbe fare qualcosa, in effetti, no?
public void Evaluate(int SpreadMax) { }
dichiara un nuovo metodo.
Molti metodi possono essere dichiarati in una classe.
Il metodo Evaluate è ancora una volta qualcosa di speciale in vvvv. Viene chiamato quando i valori di Output sono necessari.
E sono necessari quando
Potete controllare come il nodo sia "in valutazione", evaluating, seguendo questi passaggi:
Dovreste vedere che il nodo esegue gli ordini solo quando gli è richiesto l'Output, che è necessario a causa del suggerimento; quindi il metodo Evaluate viene chiamato, che risulta anche nell'invio di messaggi al nodo Renderer (TTY) (vedi sotto). Spostando il cursore, si ferma la richiesta di logging e quindi Evaluate non viene più chiamato.
Se volete assicurarvi che il nodo viene chiamato ad ogni frame (indipendentemente che i valori in Output siano necessari), aggiungerete un attributo a PluginInfo:
[PluginInfo(..., AutoEvaluate = true)]
Quindi tutto ciò che volete che il vostro nodo faccia, sta nel metodo Evaluate tra le parentesi.
FOutput.SliceCount = SpreadMax;
dice che la dimensione dello spread di Output dovrebbe essere uguale al maggiore di tutti gli spread in Input, e dato che per il momento abbiamo un solo Input, gli spread in ingresso ed uscita avranno lo stesso slicecount.
for (int i = 0; i < SpreadMax; i++) FOutput[i] = FInput[i] * 2;
Per ciascuna slice calcola l'Output moltiplicando la slice in Input per due.
Tenete presente che potete fare altro nel loop "for". Avrete bisogno ancora una volta di un blocco di codice:
for (int i = 0; i < SpreadMax; i++) { someCommand; otherCommand; }
Flogger.Log(LogType.Debug, "Logging to Renderer (TTY)");
scrive alcuni messaggi per il debug sulla console.
Di norma, userete il logging per testare se alcune parti di codice siano state eseguite (ad esempio, dentro un'istruzione if).
Dynamic Plugin Tutorials: Things you can try out to get into c# programming
Learn C#
anonymous user login
~4h ago
~7d ago
~6d ago
~7d ago
~21d ago
~1mth ago
~1mth ago
~1mth ago
~1mth ago
~1mth ago