IT/Introduzione allo scripting della GUI

From Multi Theft Auto: Wiki
Revision as of 22:58, 10 June 2008 by Atti (talk | contribs)
Jump to navigation Jump to search
« Torna alla Pagina principale italiana .

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'IT/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. 

Using the function we wrote

The CreateLoginWindow function is done, but it won't do anything until we call it. It is recommended to create all GUI when the client resource starts, hide them, and show them to player later when needed. Therefore, we'll write an event handler for "onClientResourceStart" to create the window:

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

We would like to show the window when the client joins the game, using the same event "onClientResourceStart". Now the event handler looks like:

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

                outputChatBox("Welcome to My MTA DM Server, please log in.  ")

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

	        showCursor(true)
	        guiSetInputEnabled(true)
	end
)	

Note that we have a security check before making the window visible, so that in case the window had not been created, in which case wdwLogin is not a valid element, we don't get an error. The showCursor function gives control to your mouse, and guiSetInputEnabled makes sure when you type in the GUI, certain letters like "A", "S", "D", "W", "T" don't move your character or bring out the chatbox input. In the next step, we'll make the button work as desired.

Scripting the button

When the player clicks on any part of the GUI, the event "onClientGUIClick" will be triggered for the GUI component you clicked on. For instance, if you click on the button, you can add the event handler attached to the button:

addEventHandler("onClientGUIClick", theButtonElement, theHandlerFunction, false)

In our script, we only need the event handler attached to the button. When it's clicked, the client will tell the server to spawn the player. Find the event handler code for "onClientResourceStart" from the previous section, and add the following line right AFTER CreateLoginWindow() is called:

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

The event handler must be added here because it makes sure variable btnLogin contains the actual button. You cannot attach an event to an non-existant element. You should have noticed that we need the "clientSubmitLogin" function, as stated in the line above.

function clientSubmitLogin(button)
	if button == "left" then
		
		triggerServerEvent("SubmitLogin", getRootElement(), guiGetText(edtUser), guiGetText(edtPass))
		guiSetInputEnabled(false)
		guiSetVisible(wdwLogin, false)
		showCursor(false)
	end
end

The variable "button" is passed by the event handler, and it's a string with the name of the button (either "left" or "right"). Here we also hit a new concept, which is custom events. Custom events can be triggered by script from the same side (server to server, or client to client), or from the other side (server to client, or vice versa). Here we use the triggerServerEvent function to trigger a custom event on the server, "SubmitLogin".

At this point we have all the code needed on the client side. On the server side, recall that we are spawning the player as soon as they join, as shown below:

function joinHandler()
	local x,y,z
	x = 1959.55
	y = -1714.46
	z = 10
	spawnPlayer(source, x, y, z)
	fadeCamera(source, true)
	outputChatBox("Welcome to My Server", source)
end
addEventHandler("onPlayerJoin", getRootElement(), joinHandler)

However, since we are going to spawn the player when the button is clicked, we must replace the "onPlayerJoin" event with the custom event triggered by the client script. Replace the above code with the following:

function joinHandler(username, password)
	local x,y,z
	x = 1959.55
	y = -1714.46
	z = 10
        if (client) then
	      spawnPlayer(client, x, y, z)
	      fadeCamera(client, true)
	      outputChatBox("Welcome to My Server", client)
        end
end

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

Note that the second arguement of addEvent function (the one with value "true") specifies whether the event can be triggered by the other side, therefore we need to turn it on since the client is triggering it. Also note the variable "client", it's an internal variable used by MTA to identify the player who triggered the event.

Finally, do not forget to include the new gui.lua file in the meta.xml of the main resource, and label it as a client script:

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

As to this point, we have a basic login window that spawns the player when the "login" button is clicked. You can also use the username and password submitted by the triggerServerEvent function to verify the player's identify before spawning him.