IT/Introduzione allo scripting della GUI

From Multi Theft Auto: Wiki
Revision as of 00:01, 11 June 2008 by Atti (talk | contribs) (Un tutorial per creare una finestra di login)

Una funzionalità molto importane di MTA è quella di poter scriptare delle GUI (Graphic User Interface - Interfaccia Grafica per l'Utente) personalizzate. La GUI consiste di finestre, pulsanti, campi di modifica, caselle di controllo... Essi possono essere mostrati mentre un player sta giocando, e possono essere usati al posto dei normali comandi per l'input/output.

GUI del pannello da Admin

Un tutorial per creare una finestra di login

In questo tutorial creeremo una semplice finestra di login, con due campi ed un pulsante. La finestra appare quando un giocatore entra nel server, e quando il pulsante viene premuto, il giocatore spawna. Il tutorial continuerà la gamemode che abbiamo iniziato nell'Introduzione allo Scripting. Daremo anche un'occhiata allo scripting lato client.

Disegnare la finestra

Tutte le GUI devono essere scriptate lato client, dunque potrebbe essere conveniente riunirle tutte in una cartella separata. Dunque, quando hai creato una cartella a tuo piacimento, creiamo un file "gui.lua", e in questo file scriveremo una funzione che disegni la finestra:

function CreaFinestraLogin()
	local X = 0.375
	local Y = 0.375
	local Larghezza = 0.25
	local Altezza = 0.25
	wdwLogin = guiCreateWindow(X, Y, Larghezza, Altezza, "Log In", true)
end

Come forse avrai notato, le coordinate che abbiamo inserito sono in percentuale, in questo caso rispetto all'intero schermo. Significa che 0 corrisponde all'estremità destra dello schermo, 1 a quella sinistra, e 0,5 la metà esatta. Questo è applicato non solo alla X e alla Y, ma anche alla larghezza e all'altezza della finestra (se "Larghezza" fosse 0.5, la finestra sarebbe larga esattamente la metà dello schermo). In seguito aggiungeremo le scritte ("username:" e "password:"), i campi di modifica e la casella di controllo. Sostituiamo la funzione con la sua versione completa:

function CreaFinestraLogin()
	local X = 0.375
	local Y = 0.375
	local Larghezza = 0.25
	local Altezza = 0.25
	wdwLogin = guiCreateWindow(X, Y, Larghezza, Altezza, "Log In", true)

	X = 0.0825
	Y = 0.2
	Larghezza = 0.25
	Altezza = 0.25
	guiCreateLabel(X, Y, Larghezza, Altezza, "Username", true, wdwLogin)
	Y = 0.5
	guiCreateLabel(X, Y, Larghezza, Altezza, "Password", true, wdwLogin)
	
	X = 0.415
	Y = 0.2
	Larghezza = 0.5
	Altezza = 0.15
	edtUser = guiCreateEdit(X, Y, Larghezza, Altezza, "", true, wdwLogin)
	
        Y = 0.5
	edtPass = guiCreateEdit(X, Y, Larghezza, Altezza, "", true, wdwLogin)
	guiEditSetMaxLength(edtUser, 50)
	guiEditSetMaxLength(edtPass, 50)
	
	X = 0.415
	Y = 0.7
	Larghezza = 0.25
	Altezza = 0.2
	btnLogin = guiCreateButton(X, Y, Larghezza, Altezza, "Log In", true, wdwLogin)
	
	guiSetVisible(wdwLogin, false)
end

Nota che ogni componente GUI che abbiamo creato è figlio della finestra, e per farlo abbiamo specificato l'elemento genitore (wdwLogin, in questo caso) quando abbiamo creato il componente:

guiCreateLabel(X, Y, Larghezza, Altezza, "Password", true, wdwLogin)

Questo è molto utile, perché quando in seguito dovremo controllare l'intero set di GUI, potremo riferirci direttamente all'elemento genitore. Ad esempio:

guiSetVisible(wdwLogin, false) --nasconde tutti gli elementi GUI creati finora, perché il giocatore li veda solo al momento opportuno. 

Usare la funzione che abbiamo scritto

La funzione CreaFinestraLogin è pronta, ma sarà inutile finchè non la chiameremo. Si raccomanda di creare tutti gli elementi GUI quando lo script lato client è caricato, nasconderli, e poi mostrarli al giocatore quando serve. Pertanto, creeremo un event handler legato all'evento "onClientResourceStart" per creare la finestra:

addEventHandler("onClientResourceStart", getResourceRootElement(getThisResource()), 
	function ()
		CreaFinestraLogin()
	end
)	

Vorremmo quindi che la finestra apparisse quando il giocatore entra nella partita, usando lo stesso evento "onClientResourceStart". Adesso l'event handler risulterà simile a questo:

addEventHandler("onClientResourceStart", getResourceRootElement(getThisResource()), 
	function ()
		CreaFinestraLogin()

                outputChatBox("Benvenuto nel server, per favore effettua il login.")

	        if (wdwLogin ~= nil) then
		         guiSetVisible(wdwLogin, true)
	        end 

	        showCursor(true)
	        guiSetInputEnabled(true)
	end
)	

Abbiamo effettuato un controllo prima di chiamare la funzione guiSetVisible, in modo da verificare l'esistenza di wdwLogin: anche se esso non è un elemento valido, in ogni caso non otterremo un errore. La funzione showCursor ti dà controllo sul tuo mouse, e guiSetInputEnabled serve ad assicurarsi che mentre stai scrivendo nella GUI, lettere come "A", "S", "D", "W", "T" non muoveranno il tuo personaggio o chiuderanno la finestra GUI. Nel prossimo passo, faremo in modo che il bottone funzioni come desideriamo.

Scriptare il pulsante

Quando il giocatore clicca su qualsiasi parte della GUI, verrà chiamato l'evento "onClientGUIClick" per il componente GUI su cui hai cliccato. Quindi, se clicchi sul pulsante, puoi aggiungere un event handler legato al pulsante:

addEventHandler("onClientGUIClick", pulsante, funzione, false)

Nel nostro script, abbiamo bisogno di un event handler legato solo al pulsante. Quando viene cliccato, il client dirà al server di spawnare il player. Recuperate il codice dell'"onClientResourceStart" dalla precedente sezione, e aggiungete la linea successiva DOPO che la funzione CreaFinestraLogin() è chiamata:

addEventHandler("onClientGUIClick", btnLogin, clientConfermaLogin, false)

L'event handler deve essere aggiunto qui perché dobbiamo essere certi che la variabile btnLogin contenga il pulsante che ci serve. Non puoi legare un evento a un elemento che non esiste. Ti sarai reso conto che abbiamo bisogno della funzione "clientConfermaLogin", come è scritto nella riga di sopra (ricordate che questa funzione va sempre PRIMA dell'event handler a cui si riferisce).

function clientConfermaLogin(tasto)
	if tasto == "left" then
		
		triggerServerEvent("ConfermaLogin", getRootElement(), guiGetText(edtUser), guiGetText(edtPass))
		guiSetInputEnabled(false)
		guiSetVisible(wdwLogin, false)
		showCursor(false)
	end
end

La variabile "tasto" è passata dall'event handler, ed è una stringa contenente il nome del tasto del mouse premuto ("left" [sinistra] o "right" [destra]). Qui tocchiamo anche un nuovo concetto, gli eventi personalizzati. Essi possono essere chiamati dallo stesso lato (da server a server, da client a client), o possono servire da mezzo di comunicazione tra i due lati (da server a client, o viceversa). Qui usiamo la funzione triggerServerEvent per chiamare un evento personalizzato gestito dal server , "ConfermaLogin".

A questo punto abbiamo tutto il codice che ci serve, lato client. Sul lato server, ricordiamo che nella mode che abbiamo spawneremo i players nel momento in cui entrano nella partita:

function joinHandler()
	local x,y,z
	x = 1959.55
	y = -1714.46
	z = 10
	spawnPlayer(source, x, y, z)
	fadeCamera(source, true)
	outputChatBox("Benvenuto nel mio server!", source)
end
addEventHandler("onPlayerJoin", getRootElement(), joinHandler)

Tuttavia, visto che dovremo spawnare il player quando il pulsante viene premuto, basterà sostituire l'evento "onPlayerJoin" con l'evento personalizzato chiamato dallo script lato client. Replace the above code with the following:

function joinHandler(username, password)
	local x,y,z
	x = 1959.55
	y = -1714.46
	z = 10
        if (source) then
	      spawnPlayer(source, x, y, z)
	      fadeCamera(source, true)
	      outputChatBox("Benvenuto nel mio server!", source)
        end
end

addEvent("ConfermaLogin", true)
addEventHandler("ConfermaLogin", getRootElement(), joinHandler)

Nota che il secondo argomento della funzione addEvent (quello col valore "true") specifica se l'evento può essere chiamato dall'altro lato, ed evidentemente dobbiamo attivarlo, perché l'evento personalizzato in questo caso viene chiamato dal client. La variabile "source" in questo caso identifica il client che ha causato l'evento, cioé che ha fatto chiamare la funzione.

Infine, non dimentichiamo di includere il nuovo file gui.lua nel meta.xml della resource principale:

<script src="client/gui.lua" type="client" />

A questo punto, abbiamo un semplice sistema di login che spawna il giocatore quando il pulsante "login" è premuto. Possiamo anche usare l'username e la password inviati dalla funzione triggerServerEvent per verificare l'identità del giocatore prima di spawnarlo.