Tilemancer

Creazione di Nodi Custom in Tilemancer

marcosecchi Strumenti Grafici 0 Comments

In questo post analizzeremo la metodologia per creare nuovi nodi in Tilemancer. Per una panoramica sul software, rimando al post dedicato.

Nota: il seguente articolo fa riferimento alla versione 0.2.0

  I nodi di Tilemancer sono scritti in Lua un linguaggio semplice da imparare ma abbastanza potente da essere utilizzato da diversi software per il game development.

Come è Composto un Nodo Tilemancer

Per essere considerato come nodo di Tilemancer, un file .lua deve possedere due metodi:

  • init() che inizializza il nodo
  • apply() che viene chiamato ogni volta che il nodo va aggiornato, ad esempio quando vengono variati i parametri

Creando un file di questo genere:

ed inserendolo nella cartella Nodes di Tilemancer, sarà possibile visualizzarlo nella lista, come elemento vuoto (senza nome) e la stessa cosa succederà una volta che sarà inserito nel canvas.

Empty Node

Fig. 1 – Un nodo vuoto

Il Metodo init()

All’interno del metodo init() è possibile effettuare una serie di chiamate di inizializzazione, alcune delle quali pressoché obbligatorie per il buon funzionamento del nodo: analizziamole nel dettaglio.

setName(name)

Questo metodo assegna un nome al nodo, che verrà utilizzato per identificare l’elemento all’interno della lista dei nodi e come titolo del nodo nel Canvas.

  • name: il nome del nodo
setDesc(description)

Assegna al nodo un testo descrittivo.

  • description: il testo della descrizione, visualizzato nel canvas quando si effettua un rollover sull’elemento nella lista dei nodi
setSize(width, height)

Assegna le dimensioni al nodo, una volta posizionato nel canvas.

  • width: la larghezza del nodo una volta visualizzato nel canvas
  • height: l’altezza del nodo una volta visualizzato nel canvas
  Gli elementi al di fuori di questo rettangolo, non saranno sensibili alle interazioni: se quindi posizionate un parametri oltre l’altezza del rettangolo (come mostrato in fig. 2), questo verrà visualizzato, ma non sarà possibile modificarlo.

Out of Bounds

Fig. 2 – Non è possibile interagire con un parametro al di fuori del nodo

addInput(name, y)

Aggiunge un elemento di input al nodo.

  • name: l’etichetta visualizzata
  • y: la posizione verticale dell’input sulla sinistra del nodo
addParameter(name, description, y, default, min, max, showPercent)

Aggiunge un parametro al nodo.

  • name: l’etichetta visualizzata
  • description: il testo della descrizione, visualizzato nel canvas quando si effettua un rollover sull’elemento
  • y: la posizione verticale dell’input sulla sinistra del nodo
  • default: il valore di partenza del parametro (effettuando doppio click sull’etichetta, il parametro verrà reinizializzato su questo valore)
  • min: il valore minimo del parametro
  • max: il valore massimo del parametro
  • showPercent: se assegnato a true, visualizzerà il carattere % a fianco del valore del parametro
addInputParameter(name, description, y, default, min, max, showPercent)

Aggiunge un parametro al nodo, ma con la possibilità di ricevere il valore come input.

  • name: l’etichetta visualizzata
  • description: il testo della descrizione, visualizzato nel canvas quando si effettua un rollover sull’elemento
  • y: la posizione verticale dell’input sulla sinistra del nodo
  • default: il valore di partenza del parametro (effettuando doppio click sull’etichetta, il parametro verrà reinizializzato su questo valore)
  • min: il valore minimo del parametro
  • max: il valore massimo del parametro
  • showPercent: se assegnato a true, visualizzerà il carattere % a fianco del valore del parametro
addOutput(y)

Aggiunge un elemento di output al nodo, comprensivo della sua anteprima al centro del nodo stesso.

  • y: la posizione verticale dell’input sulla destra del nodo
addCRamp(y)

Aggiunge un componente per la selezione dei colori.

  • y: la posizione verticale dell’elemento all’interno del nodo

Nota: questo metodo è specifico del nodo Colorizer e difficilmente avrebbe un utilizzo altrove. Viene riportato solo per completezza.

  Ogni volta che si effettua una chiamata a addInput, addParameter, addInputParameter, l’elemento corrispondente viene inserito in una lista in modo crescente (il primo elemento avrà indice 0). Il valore dell’elemento potrà essere recuperato successivamente, durante l’esecuzione di apply(), tramite questo indice.

  Ogni volta che si effettua una chiamata a addOutput, l’elemento corrispondente viene inserito in una lista in modo crescente (il primo elemento avrà indice 0). Il valore dell’elemento potrà essere modificato successivamente, durante l’esecuzione di apply(), tramite questo indice.

Il Metodo apply()

All’interno del metodo apply() verranno effettuate tutte le operazioni che produrranno la texture in uscita. Analizziamo in dettaglio le operazioni disponibili.

getTileSize()

Ritorna le dimensioni scelte dall’utente per la texture generata.

getValue(index, x, y, divider)

Recupera il valore dell’input o parametro che si trova ad un determinato indice. Il metodo ritorna i valori normalizzati a 0-1 del colore (RGB) di un pixel in una determinata posizione.

  • index: l’indice dell’elemento nella lista degli input e parametri
  • x: la coordinata x del pixel da leggere. Nel caso la posizione sia al di fuori delle dimensioni della texture, verrà effettuato un wrap around
  • y: la coordinata y del pixel da leggere. Nel caso la posizione sia al di fuori delle dimensioni della texture, verrà effettuato un wrap around
  • divider: il divisore applicato al valore calcolato (viene utilizzato solamente se il valore analizzato è un parametro)
SetPixel(index, x, y, r, g, b)

Recupera l’output che si trova ad un determinato indice e setta i valori RGB di un determinato pixel.

  • index: l’indice dell’elemento nella lista degli output
  • x: la coordinata x del pixel da scrivere. Nel caso la posizione sia al di fuori delle dimensioni della texture, verrà effettuato un wrap around
  • y: la coordinata y del pixel da scrivere. Nel caso la posizione sia al di fuori delle dimensioni della texture, verrà effettuato un wrap around
  • r: il valore per il rosso (normalizzato a 0-1)
  • g: il valore per il verde (normalizzato a 0-1)
  • b: il valore per il blu (normalizzato a 0-1)
colorize()

Utilizzato in stretta connessione con addCRamp(y), colorizza la texture in ingresso che si trova all’indice 0 nella lista degli input.

Nota: questo metodo è specifico del nodo Colorizer e difficilmente avrebbe un utilizzo altrove. Viene riportato solo per completezza. Utilizzato in modo scorretto, potrebbe mandare in crash il programma.

Tutorial: Creare un Selettore di Input

In questo breve tutorial, ci proponiamo di creare un nodo che permetta, data una serie di input, di selezionarne uno come uscita, come se fosse una sorta di interruttore a più stati.

Creazione del file

Per prima cosa creiamo un file di testo chiamato switcher.lua, che andremo a salvare nella cartella Nodes di Tilemancer.

All’interno di esso creiamo i due metodi init() e function apply():

Setup del Nodo

All’interno del metodo init() andremo ad inserire, oltre ad i vari elementi necessari per l’inizializzazione, anche tre valori di input, un valore di output ed un parametro, che fungerà da selettore:

Come è possibile notare, sono stati inseriti i vari elementi.

  Tilemancer non discrimina tra nodi creati dall’utente e nodi preinstallati: per una più facile lettura consiglio di inserire, prima del nome, un carattere identificativo, come un underscore _.

  Lo sviluppatore di Tilemancer, Led, invece di inserire i valori finali delle dimensioni, utilizza le somme delle altezze degli elementi che verranno inseriti. Questo gli permette di aggiornare velocemente il nodo qualora dovesse aggiungere o rimuovere qualche elemento durante lo sviluppo.

Se lanciamo Tilemancer, vedremo il nodo elencato nella lista e, cliccandoci sopra, lo potremo posizionare nel canvas (anche se al momento non effettuerà nessuna operazione).

Tilemancer Switcher

Fig. 3 – Il nodo _Switcher

Processare la Texture

Il nostro nodo non dovrà fare altro che produrre come texture in uscita, l’input indicato dal parametro Selection.

Come è possibile vedere, per prima cosa andremo a leggere le dimensioni della texture, per poi creare un ciclo che vada a leggere ogni singolo pixel (utilizzerete questa operazione molto spesso…).
Subito dopo, recuperiamo l’indice selezionato tramite:

index = getValue(3, x, y, 1.0)

(il parametro Selection è al quarto posto, quindi con indice 3).

La linea di codice successiva:

cr, cg, cb = getValue(index, x, y, 1.0)

recupera i valori RGB del pixel selezionato (per la texture selezionata).
Il passaggio successivo è banale: si tratta semplicemente di settare in uscita i colori appena letti.

Tilemancer Switcher

Fig. 3 – Il nodo in azione