Nui basic example

From NWN Lexicon
Jump to navigationJump to search

Intro

Here is a basic example of a small NUI Window.

1. Create a new file called : `nui_example.nss` using contents below.

2. Then Setup OnNuiEvent as such:

#include "nui_example"
	void main()
	{
		object oPlayer = NuiGetEventPlayer();
		int nToken	   = NuiGetEventWindow();
		string sEvent  = NuiGetEventType();
		string sElement   = NuiGetEventElement();
		int nIndex	   = NuiGetEventArrayIndex();
		string sWindowId  = NuiGetWindowId(oPlayer, nToken);

		if (sWindowId == NUIEXAMPLE_WINDOW_ID)
		{
			NUIExample_Events();
			return;
		}
	}


3. Finally you need to call ```NUIExample_NewWindow(oPlayer);``` from something. This could be an Item's Unique Power, or Placeable a OnUsed Event, etc.


You should hopefully see your new window now:

Code

"nui_example.nss"

#include "nw_inc_nui"

// This is our window id, it's used to differentiate between NUI Windows
const string NUIEXAMPLE_WINDOW_ID = "nui_example";

// This creates our new window.  You can call this from anywhere.
// Examples would be: Module (item) OnActivateItem, Placeable OnUsed, Module OnPlayerChat, etc.
void NUIExample_NewWindow(object oPlayer);


// This will refresh data on window.
// This depends on application, but should be called anytime you think the state has changed.
void NUIExample_Update(object oPlayer, int nToken = -1);

// This handles events.
// This should be called from OnNuiEvent
// https://nwnlexicon.com/index.php?title=OnNuiEvent
/* Example:
	#include "nui_example"
	void main()
	{
		object oPlayer = NuiGetEventPlayer();
		int nToken	   = NuiGetEventWindow();
		string sEvent  = NuiGetEventType();
		string sElement   = NuiGetEventElement();
		int nIndex	   = NuiGetEventArrayIndex();
		string sWindowId  = NuiGetWindowId(oPlayer, nToken);

		if (sWindowId == NUIEXAMPLE_WINDOW_ID)
		{
			NUIExample_Events();
			return;
		}
	}
*/
void NUIExample_Events();


// Helper function for debugging.
// Log it however you want.
void LogMessage(string sMessage)
{
	// WriteTimestampedLogEntry(sMessage);
	SendMessageToPC(GetFirstPC(), sMessage);
}

void NUIExample_Events()
{
	// Get all our inputs.
	object oPlayer	 = NuiGetEventPlayer();
	int nToken		 = NuiGetEventWindow();
	string sEvent	 = NuiGetEventType();
	string sElement	 = NuiGetEventElement();
	int nIndex		 = NuiGetEventArrayIndex();
	string sWindowId = NuiGetWindowId(oPlayer, nToken);

	// Not our window!
	if (sWindowId != NUIEXAMPLE_WINDOW_ID)
	{
		LogMessage("NUIExample_Events called for wrong window, expecting: " + NUIEXAMPLE_WINDOW_ID + " but got: " + sWindowId);
		return;
	}

	// If events aren't working, log what is going on.
	// If you don't see a bunch of stuff, then likly it's not being called from OnNuiEvent correctly.
	// LogMessage("NUIExample: sElement: " + sElement + " sEvent: " + sEvent);

	// Here is all our events, we need to sort out what to do, depending on Event and Element.

	switch (HashString(sEvent))
	{
		case ("blur"):
		{
		}
		break;
		case ("click"):
		{
		}
		break;
		case ("close"):
		{
		}
		break;
		case ("focus"):
		{
		}
		break;
		case ("mousedown"):
		{
		}
		break;
		case ("mousescroll"):
		{
		}
		break;
		case ("mouseup"):
		{
			// Yikes, switch inside a switch.
			// But this filters Event mouseup by Element with these Ids (in this case, buttons mostly)
			// Ie, when a user is done clicking a button, process what to do for that button type.
			switch (HashString(sElement))
			{
				case ("buttonUpdate"):
				{
					// They want to call an update.
					NUIExample_Update(oPlayer, nToken);
					return;
				}
				break;
				case ("buttonCancel"):
				{
					// They want to close a window.
					NuiDestroy(oPlayer, nToken);
					return;
				}
				break;
			}
		}
		break;
		case ("open"):
		{
		}
		break;
		case ("range"):
		{
		}
		break;
		case ("watch"):
		{
		}
		break;
		default:
		{
			LogMessage("NUIExample: Unknown event occured: " + sEvent + " Element: " + sElement);
		}
		break;
	}
}


void NUIExample_Update(object oPlayer, int nToken = -1)
{
	// If caller doesn't have our token, be nice and look it up for them.
	if (nToken == -1)
	{
		nToken = NuiFindWindow(oPlayer, NUIEXAMPLE_WINDOW_ID);
	}

	// Window isn't open, so let's not spend time processing updates.
	if (nToken == 0)
	{
		return;
	}


	// This is our only update for now.
	// For Nui Id "labelMain" it will update it's value with a random number between 1 and 100.
	NuiSetBind(oPlayer, nToken, "labelMain", JsonString(IntToString(Random(100) + 1)));
}

void NUIExample_NewWindow(object oPlayer)
{
	// This checks if window is already open.  If so, we want to close it and create a new one.
	// You CAN have multiple windows of same time, but most use cases if you just want one instance?
	int nToken = NuiFindWindow(oPlayer, NUIEXAMPLE_WINDOW_ID);
	if (nToken != 0)
	{
		NuiDestroy(oPlayer, nToken);
	}


	/////////////////////////////////////////
	// Build the main root pane here
	/////////////////////////////////////////

	// This is going to be our entire window that is passed into NuiWindow.
	json jRoot = JsonArray();


	json jRow;
	// Build the first row
	{
		// Create an array to hold our first row.
		jRow = JsonArray();

		// Create a label, notice it uses bind "labelMain", instead of static value.
		json jLabelMain = NuiLabel(NuiBind("labelMain"), JsonInt(NUI_HALIGN_CENTER), JsonInt(NUI_VALIGN_MIDDLE));


		// Add our label to the row
		jRow = JsonArrayInsert(jRow, jLabelMain);

		// Apply a Layout too it (you can't have widgets hanging about, outside of layout groups)
		jRow = NuiRow(jRow);

		// Finally we add our finalize row to our main root window.
		jRoot = JsonArrayInsert(jRoot, jRow);
	}

	// Build the second row
	{
		// Same as before, start with a fresh array to hold our row data.
		jRow = JsonArray();

		// Make two buttons.
		// Notice they have NuiId!  If you want to capture events on widgets they MUST have an ID
		json jButtonUpdate = NuiId(NuiButton(JsonString("Update")), "buttonUpdate");
		json jButtonCancel = NuiId(NuiButton(JsonString("cancel")), "buttonCancel");


		// Same as first row, but we goign to add a spacer, then both buttons.
		jRow = JsonArrayInsert(jRow, NuiSpacer());
		jRow = JsonArrayInsert(jRow, jButtonUpdate);
		jRow = JsonArrayInsert(jRow, jButtonCancel);


		// again, wrap all the widgets up in a nice group layout.
		jRow = NuiRow(jRow);
		// then add to main root
		jRoot = JsonArrayInsert(jRoot, jRow);
	}


	///////////////////////////////////////////
	// Build final group
	///////////////////////////////////////////

	// Again, needs a group layout, his is just one big column for window (with 2 rows inside it)
	jRoot = NuiCol(jRoot);

	/////////////////////////////////////////
	// Create new window here
	/////////////////////////////////////////

	// Creates new window and gets token.
	json jNuiWindow = NuiWindow(jRoot, NuiBind("windowtitle"), NuiBind("geometry"), NuiBind("resizable"), NuiBind("collapsed"), NuiBind("closable"), NuiBind("transparent"), NuiBind("border"), JsonBool(TRUE));
	nToken			= NuiCreate(oPlayer, jNuiWindow, NUIEXAMPLE_WINDOW_ID);

	// Good example of how to use bings. "windowtitle" is just a place holder.  We want to update it here.
	NuiSetBind(oPlayer, nToken, "windowtitle", JsonString("NUI Example"));

	// x, y, width, height.
	// -1.0f, -1.0f, means to "center" the new NUI Window.  Otherwise you can manually place it were you wish.
	NuiSetBind(oPlayer, nToken, "geometry", NuiRect(-1.0f, -1.0f, 512.0f, 512.0f));

	NuiSetBind(oPlayer, nToken, "collapsed", JsonBool(FALSE));
	NuiSetBind(oPlayer, nToken, "resizable", JsonBool(TRUE));
	NuiSetBind(oPlayer, nToken, "closable", JsonBool(TRUE));
	NuiSetBind(oPlayer, nToken, "transparent", JsonBool(FALSE));
	NuiSetBind(oPlayer, nToken, "border", JsonBool(TRUE));

	// Refesh the data after window is made.
	NUIExample_Update(oPlayer);
}