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:

Nui example.png

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);
}