Difference between revisions of "EasyDialog"

From Second Life Wiki
Jump to navigation Jump to search
(Created page with "= EasyDialog = Free to use in any context for any reason. Provided by Pazako Karu Easy to use system for taking on secure dialogs. Simplifies listens and contextual informati...")
 
(Undo revision 1216959 by Pazako Karu (talk) brainfart)
Tag: Undo
 
(7 intermediate revisions by the same user not shown)
Line 1: Line 1:
= EasyDialog =
Free to use in any context for any reason. Provided by Pazako Karu
Free to use in any context for any reason. Provided by Pazako Karu


Easy to use system for taking on secure dialogs. Simplifies listens and contextual information greatly into gets and sets.
Take on high-security dialogs the easy way!
Simplifies listens and contextual information greatly into gets and sets. Each dialog uses a new listen, a new channel, and listens only to the originator of the dialog. Any use of a dialog will trigger self-clean garbage collection of old listens and values.


Any use of a dialog will trigger self-clean garbage collection of old listens and values.
Caveats: If the last person to dialog chose to Ignore or close without a getDialog response, 1 listen event will remain in queue and active until another person touches it. This is not generally a problem, and this will be rare. If this trivial amount of lag is a problem (its a very specific listen, least possible lag), run cleanDialogs() on a timer after click events or after special events like reset.


Example use case below.
Example use case below.


<source lang="lsl2">
<syntaxhighlight lang="lsl2">
list DIALOG_DATA;
list DIALOG_DATA;
setDialog(key id, string caption, list buttons, integer context) // Creates a listen and a dialog
setDialog(key id, string caption, list buttons, integer context) // Creates a listen and a dialog
Line 32: Line 32:
     return context; // Return the context
     return context; // Return the context
}
}
</source>
cleanDialogs()
{  // Removes our listens and clears data
    integer index; // Time, Id, Listen, Context
    for (index = 2; index < llGetListLength(DIALOG_DATA); index+=4)
        llListenRemove((integer)DIALOG_DATA[index]);
    DIALOG_DATA=[];
}
</syntaxhighlight>
 
= Example use =
= Example use =
Context is useful for creating sub-menus without complicating the listen logic. As you can have a precheck of context, you can keep simple "Yes" and "No" answers, rather than the often-used trope of including special characters with each menu option. No additional variables or flags are necessary.  
Context is useful for creating sub-menus without complicating the listen logic. As you can have a precheck of context, you can keep simple "Yes" and "No" answers, rather than the often-used trope of including special characters with each menu option. No additional variables or flags are necessary.  
<source lang="lsl2">
 
Think of 'context' the same as a 'listen handle', except it is set when you call a dialog, so you know the source and <b>context</b> of what your listen is handling.
 
<syntaxhighlight lang="lsl2">
integer context_pancake = 1;
integer context_pancake = 1;
integer context_pie = 2;
integer context_pie = 2;
Line 46: Line 57:
     listen(integer channel, key id, string message)
     listen(integer channel, key id, string message)
     {
     {
         integer context = getDialog(id);
         integer context = getDialog(id); // This gets our context number back, and cleans up the listen event
         if(context == context_pancake) // They like pancakes!
         if (context == context_pancake) // Do they like pancakes?
         {
         { // Notice here we know the dialog is about pancakes, so we can use Yes/No exactly
             if (message == "Yes")
             if (message == "Yes")
                 llRegionSayTo(llGetOwner(), 0, "Glad to hear it!");
                 llRegionSayTo(llGetOwner(), 0, "Glad to hear it!");
Line 54: Line 65:
                 setDialog(llGetOwner(), "Sorry, how about pie?", ["Yes", "No"], context_pie);
                 setDialog(llGetOwner(), "Sorry, how about pie?", ["Yes", "No"], context_pie);
         }
         }
         else if (context == context_pie) // They like pie!
         else if (context == context_pie) // They didn't like pancakes, how about pie? (sub-menu from "No" earlier)
         {
         { // And here we know the dialog is about pie.
             if (message == "Yes")
             if (message == "Yes")
                 llRegionSayTo(llGetOwner(), 0, "Pie is my second favorite!");
                 llRegionSayTo(llGetOwner(), 0, "Pie is my second favorite!");
Line 63: Line 74:
     }
     }
}
}
</source>
</syntaxhighlight>

Latest revision as of 15:45, 31 July 2024

Free to use in any context for any reason. Provided by Pazako Karu

Take on high-security dialogs the easy way! Simplifies listens and contextual information greatly into gets and sets. Each dialog uses a new listen, a new channel, and listens only to the originator of the dialog. Any use of a dialog will trigger self-clean garbage collection of old listens and values.

Caveats: If the last person to dialog chose to Ignore or close without a getDialog response, 1 listen event will remain in queue and active until another person touches it. This is not generally a problem, and this will be rare. If this trivial amount of lag is a problem (its a very specific listen, least possible lag), run cleanDialogs() on a timer after click events or after special events like reset.

Example use case below.

list DIALOG_DATA;
setDialog(key id, string caption, list buttons, integer context) // Creates a listen and a dialog
{   getDialog(id); // Clean up beforehand
    if (llList2Integer(DIALOG_DATA, -3) > llGetTime()) // Clear old
    {   integer i;
        for (i = 0; i < llGetListLength(DIALOG_DATA); i++)
            llListenRemove((integer)DIALOG_DATA[i+2]);
        DIALOG_DATA = []; // If the last timed out, all are invalid
    }
    integer channel = -(integer)llFrand(DEBUG_CHANNEL);
    DIALOG_DATA += [llGetTime()+60, id, llListen(channel, llKey2Name(id), id, ""), context]; // Time, ID, Listen Handle, context
    llDialog(id, caption, buttons, channel);
}
integer getDialog(key id)
{   integer index = llListFindList(DIALOG_DATA, [id]); // Finds the dialog, if it exists
    integer context = (integer)DIALOG_DATA[index+2]; // Context that the dialog was sent in, integer
    if (~index) // If it does...
    {   llListenRemove(llList2Integer(DIALOG_DATA, index+1)); // Remove the listen
        DIALOG_DATA = llDeleteSubList(DIALOG_DATA, index-1, index+1); // Free the memory
    }
    else context = -1; // If it doesn't exist, return nothing
    return context; // Return the context
}
cleanDialogs()
{   // Removes our listens and clears data
    integer index; // Time, Id, Listen, Context
    for (index = 2; index < llGetListLength(DIALOG_DATA); index+=4)
        llListenRemove((integer)DIALOG_DATA[index]);
    DIALOG_DATA=[];
}

Example use

Context is useful for creating sub-menus without complicating the listen logic. As you can have a precheck of context, you can keep simple "Yes" and "No" answers, rather than the often-used trope of including special characters with each menu option. No additional variables or flags are necessary.

Think of 'context' the same as a 'listen handle', except it is set when you call a dialog, so you know the source and context of what your listen is handling.

integer context_pancake = 1;
integer context_pie = 2;
default
{
    state_entry()
    {
        setDialog(llGetOwner(), "Do you like pancakes?", ["Yes", "No"], context_pancake);
    }
    listen(integer channel, key id, string message)
    {
        integer context = getDialog(id); // This gets our context number back, and cleans up the listen event
        if (context == context_pancake) // Do they like pancakes?
        { // Notice here we know the dialog is about pancakes, so we can use Yes/No exactly
            if (message == "Yes")
                llRegionSayTo(llGetOwner(), 0, "Glad to hear it!");
            else if (message == "No")
                setDialog(llGetOwner(), "Sorry, how about pie?", ["Yes", "No"], context_pie);
        }
        else if (context == context_pie) // They didn't like pancakes, how about pie? (sub-menu from "No" earlier)
        { // And here we know the dialog is about pie.
            if (message == "Yes")
                llRegionSayTo(llGetOwner(), 0, "Pie is my second favorite!");
            else if (message == "No")
                llRegionSayTo(llGetOwner(), 0, "I guess we dont have much in common :(");
        }
    }
}