Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Adding Pagination to my llDialog Script

Cherry Hotaling
Registered User
Join date: 25 Feb 2007
Posts: 86
01-13-2008 10:09
Hello

I created a new thread with this because my other thread was going a bit off the original post.

Ok Im completely stuck on how to add Pagination to this llDialog Script.

If anyone can help with this it should complete my NPC Target button im trying to finish to move on to the rest of my project.

I Wanted to know if anyone can help me add pagination to this script.

(The script sends out a say and other prims with this script in it reply with thier UUIDs and name and you can select that target from the llDialog)\

The original thread is here: /54/44/234328/1.html

Script So Far ( I made some changes so I can have a Player and NPC Detection menus:
Main Script (The button or HUD Button):


integer PING_CHANNEL = -893397710;
string PING_QUERY_NPC = "querynpc";
string PING_RESPONSE_NPC = "responsenpc";
string PING_QUERY_PC = "querypc";
string PING_RESPONSE_PC = "responsepc";
float PING_TIMEOUT_SECONDS = 0.4;
integer MAX_TARGETS = 12;

integer DIALOG_CHANNEL = -893397711;

list NPC_MENU = ["NPC Target", "PC Target"]; // the main menu

list targetKeys = [];
list targetNames = [];
integer nTargets = 0;

giveDialog()
{
list choices = [];
integer i;
for (i = 0; i < nTargets; ++i)
{
string choice = (string)(i+1)+" "+llList2String(targetNames, i);
choices = (choices=[])+choices+choice;
}

llDialog(
llGetOwner(),
"Choose a target",
choices,
DIALOG_CHANNEL
);
}

default
{
state_entry()
{
DIALOG_CHANNEL = (integer)llFrand(2147483647);
llListen(PING_CHANNEL, "", NULL_KEY, PING_RESPONSE_NPC);
llListen(PING_CHANNEL, "", NULL_KEY, PING_RESPONSE_PC);
llListen(DIALOG_CHANNEL, "", llGetOwner(), "";);


}

touch_start(integer total_number)
{
llDialog(llDetectedKey(0), "What do you want to do?", NPC_MENU, DIALOG_CHANNEL); // present dialog on click

}

timer()
{
llSetTimerEvent(0.0);
giveDialog();
}

listen(integer channel, string name, key id, string message)
{




if (channel == PING_CHANNEL && message == PING_RESPONSE_NPC)
{
if (nTargets < MAX_TARGETS &&
llListFindList(targetKeys, [ id ]) < 0)
{
targetKeys = (targetKeys=[])+targetKeys+[ id ];
targetNames = (targetNames=[])+targetNames+[ name ];
++nTargets;

if (nTargets >= MAX_TARGETS)
{
llSetTimerEvent(0.0);
giveDialog();
}
}
}

else if (channel == PING_CHANNEL && message == PING_RESPONSE_PC)
{
if (nTargets < MAX_TARGETS &&
llListFindList(targetKeys, [ id ]) < 0)
{
targetKeys = (targetKeys=[])+targetKeys+[ id ];
targetNames = (targetNames=[])+targetNames+[ name ];
++nTargets;

if (nTargets >= MAX_TARGETS)
{
llSetTimerEvent(0.0);
giveDialog();
}
}
}


if (channel == DIALOG_CHANNEL && message == "NPC Target";)
{
llSay(PING_CHANNEL, PING_QUERY_NPC);
llSetTimerEvent(PING_TIMEOUT_SECONDS);
}
else if (channel == DIALOG_CHANNEL && message == "PC Target";)
{
llSay(PING_CHANNEL, PING_QUERY_PC);
llSetTimerEvent(PING_TIMEOUT_SECONDS);
}
else if (channel == DIALOG_CHANNEL && id == llGetOwner())
{
string spacePos = llGetSubString(" ", 0, -1);
integer index = (integer)(llGetSubString(message, 0, (integer)spacePos-1))-1;
key targetKey = llList2Key(targetKeys, index);
key targetName = llList2Key(targetNames, index);

llSay(0, "Chosen target: "+ (string)targetName +" "+ (string)targetKey);

llResetScript();
}
}
changed(integer change)
{
if (change & CHANGED_OWNER)
{
llResetScript();
}
}
}



The NPC Script:

integer PING_CHANNEL = -893397710;
string PING_QUERY_NPC = "querynpc";
string PING_RESPONSE_NPC = "responsenpc";

default
{
state_entry()
{
llListen(PING_CHANNEL, "", "", PING_QUERY_NPC);
}
listen(integer channel, string name, key id, string message)
{
llSay(PING_CHANNEL, PING_RESPONSE_NPC);
}
}



Thank you very much,
-Cherry Hotaling
Hewee Zetkin
Registered User
Join date: 20 Jul 2006
Posts: 2,702
01-13-2008 12:01
I assume you are asking about the case when there are more than 12 targets to choose from. The idea is usually to have one or two specially labeled buttons (e.g. "prev" and "next";). If those dialog messages are recieved, change the page number in your script and re-offer the dialog with another sub-set of your targets.

There is another way to do it such that you don't have ot keep the page number being viewed in a global variable, though. If you are currently displaying page N, then make the navigation buttons read something more like "< Page (N-1)" and "> Page (N+1)". This takes a little more logic to detect and parse, since they aren't constant strings.

You also have a few choices to make. What do you do when you reach the end of the list? Do you provide navigation buttons when there are less than 13 choices? Keep in mind that you have to know how many actual choices there are on each page so that your pages don't skip or repeat them. A common choice is often to reserve the top three buttons in the dialog for navigation, and only provide 9 choices per page. That way the buttons can be populated correctly even if you choose not to have a "prev" button on the first page, a "next" button on the last page, etc. It can also sometimes be convenient that this allows for another button that might be useful for going up to a main menu or canceling the current operation.
Monica Balut
Beam-Me
Join date: 18 Feb 2007
Posts: 311
01-13-2008 12:12
Not exactly sure what you mean by "pagination". If you mean that clicking a button on one dialog brings up a second one, it's just a matter of listening for that button and calling llDialog again with a new menu. You have to pass it the same id that you got from the listen. So something like this:

CODE

listen(integer channel, string name, key id, string message)
{
if (channel == channel1) // channel for menu 1
{
if (message == setup)
{
llListenControl(L3,TRUE);
llDialog(id, "Please select a function below" ,[cancel,back,help, reset], channel3);
}
else if (message != cancel)
{
...
}
}

[]/php
Cherry Hotaling
Registered User
Join date: 25 Feb 2007
Posts: 86
01-13-2008 16:23
Pagination means being able to click Next or Back to see the next page if theres more then so many peopel etc.

Hewee Zetkin
I have a script I had pagination in it but I cant seem to understand it enough to pull what I need to from it to give me the next page etc.

Is it possible to look at my script as I have now and add the pagination with Back and Next to it?

Thank you for your patience,
-Cherry Hotaling
Hewee Zetkin
Registered User
Join date: 20 Jul 2006
Posts: 2,702
01-13-2008 16:25
It is possible, yes. I'd rather leave it as an excercise for the reader though. Teach a man to fish and all that. I hope I've given some good direction on how to go about it. If you have specific questions, I'm sure this would be a good place to get those answered. Good luck, and have fun! :-)
Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
01-13-2008 17:20
I made a function for paging dialogs from a master list, it's on the forum, dynamic dialog something or rather... it only has next buttons, but it could easily be modified
_____________________
|
| . "Cat-Like Typing Detected"
| . This post may contain errors in logic, spelling, and
| . grammar known to the SL populace to cause confusion
|
| - Please Use PHP tags when posting scripts/code, Thanks.
| - Can't See PHP or URL Tags Correctly? Check Out This Link...
| -
Hewee Zetkin
Registered User
Join date: 20 Jul 2006
Posts: 2,702
01-13-2008 20:45
Here is an example of pure dialog paging. It should work for multiple users (though it has not been fully tested), as it does not store any state related to the dialog. Hopefully you can use this to use this as an example to add similar functionality to your applications.

CODE

//// Constants

list DIALOG_CHOICES =
[ "Hello",
"There",
"Are",
"Blat",
"Apple",
"Orange",
"Who",
"What",
"When", // <- End of page 1
"Where",
"Why",
"How",
"Is",
"Tree",
"Park",
"Weed",
"Hat",
"Sting", // <- End of page 2
"Glamdring",
"Orcrist",
"Bombur",
"Fili",
"Kili",
"Dopey",
"Sneezy",
"Doc",
"Grumpy", // <- End of page 3
"Thorin",
"Sleepy"
];
integer N_DIALOG_CHOICES;
integer MAX_DIALOG_CHOICES_PER_PAGE = 9;
string PREV_PAGE_DIALOG_PREFIX = "< Page ";
string NEXT_PAGE_DIALOG_PREFIX = "> Page ";
string DIALOG_CANCEL_BUTTON = "Cancel";

integer DIALOG_CHANNEL = -1694941610;


//// Functions

integer initialized = FALSE;
init()
{
if (initialized)
{
return;
}
initialized = TRUE;

N_DIALOG_CHOICES = llGetListLength(DIALOG_CHOICES);
}

// Page number starts at one, not zero
giveDialog(key resident, integer pageNum)
{
list buttons;
if (N_DIALOG_CHOICES <= 12)
{
buttons = DIALOG_CHOICES;
} else
{
integer nPages = (N_DIALOG_CHOICES+MAX_DIALOG_CHOICES_PER_PAGE-1)/MAX_DIALOG_CHOICES_PER_PAGE;
if (pageNum < 1 || pageNum > nPages)
{
pageNum = 1;
}
integer firstChoice = (pageNum-1)*MAX_DIALOG_CHOICES_PER_PAGE;
integer lastChoice = firstChoice+MAX_DIALOG_CHOICES_PER_PAGE-1;
if (lastChoice >= N_DIALOG_CHOICES)
{
lastChoice = N_DIALOG_CHOICES;
}

integer prevPage;
integer nextPage;
if (pageNum <= 1)
{
prevPage = nPages;
nextPage = 2;
} else if (pageNum >= nPages)
{
prevPage = nPages-1;
nextPage = 1;
} else
{
prevPage = pageNum-1;
nextPage = pageNum+1;
}

// Put the navigation button row first, so it is always at the bottom of the dialog
buttons = llList2List(DIALOG_CHOICES, firstChoice, lastChoice);
buttons =
(buttons=[])+
[ PREV_PAGE_DIALOG_PREFIX+(string)prevPage,
DIALOG_CANCEL_BUTTON,
NEXT_PAGE_DIALOG_PREFIX+(string)nextPage
]+buttons;
}

llDialog(resident, "Page "+(string)pageNum+"\nChoose one:", buttons, DIALOG_CHANNEL);
}


default
{
state_entry()
{
init();

llListen(DIALOG_CHANNEL, "", llGetOwner(), "");
}

touch_start(integer nDetected)
{
integer i;
for (i = 0; i < nDetected; ++i)
{
giveDialog(llDetectedKey(i), 1);
}
}

listen(integer channel, string name, key id, string message)
{
if (channel == DIALOG_CHANNEL)
{
if (message == DIALOG_CANCEL_BUTTON)
{
return;
} else if (llSubStringIndex(message, PREV_PAGE_DIALOG_PREFIX) == 0)
{
integer pageNum =
(integer)llGetSubString(message, llStringLength(PREV_PAGE_DIALOG_PREFIX), -1);
giveDialog(id, pageNum);
} else if (llSubStringIndex(message, NEXT_PAGE_DIALOG_PREFIX) == 0)
{
integer pageNum =
(integer)llGetSubString(message, llStringLength(NEXT_PAGE_DIALOG_PREFIX), -1);
giveDialog(id, pageNum);
} else
{
llSay(0, name+" chose: '"+message+"'");
}
}
}
}


Edit: Changed llOwnerSay() to a normal llSay() with resident name added (the only bit that wasn't very conducive to multiple-resident use.
Jesse Barnett
500,000 scoville units
Join date: 21 May 2006
Posts: 4,160
01-14-2008 04:07
Here you go Cherry. Very simple and easy to see what is happening. You can also play with it by adding more numbers to "menu" or taking some away. Once you think you have it down then try adding more numbers and create a "third_menu" ;) :

CODE

list menu = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16"];
list first_menu;
list second_menu;

default{
touch_start(integer total_number){
if(llGetListLength(menu) > 12){
first_menu = llList2List(menu, 0, 10) + "Next";
//Remember that a list starts at 0, not 1, so we end
//at 10 to have 11 buttons + the "Next" button
second_menu = "Back" + llList2List(menu, 11, -1);
llDialog("", "Pick a number or Next for more", first_menu, -99);
}
else{
llDialog("", "Pick a number", menu, -99);
}
llListen(-99, "", "", "");
}
listen(integer channel, string name, key id, string message){
if(message == "Next"){
llDialog("", "Pick a number or Back for more", second_menu, -99);
}
else if(message == "Back"){
llDialog("", "Pick a number or Next for more", first_menu, -99);
}
else{
llOwnerSay("You picked number " + message);
}
}
}

Forgive the guys but they always try to make a simple script as complicated as possible. I think it's a "Bells & Whistles" type thing. :rolleyes:
_____________________
I (who is a she not a he) reserve the right to exercise selective comprehension of the OP's question at anytime.
From: someone
I am still around, just no longer here. See you across the aisle. Hope LL burns in hell for archiving this forum
Cherry Hotaling
Registered User
Join date: 25 Feb 2007
Posts: 86
01-14-2008 06:54
Jesse Barnett and Hewee Zetkin thank you so much.

I will play with these today and let you know how I do.

-Cherry
Hewee Zetkin
Registered User
Join date: 20 Jul 2006
Posts: 2,702
01-14-2008 09:25
From: Jesse Barnett
Forgive the guys but they always try to make a simple script as complicated as possible. I think it's a "Bells & Whistles" type thing. :rolleyes:

Hmm. Well, true enough. I did try to set it up to do general paging, so it doesn't matter how many strings are input (and they can even change dynamically). It seemed more appropriate to the original application (from another thread) that way, since the script will have no idea how many nearby objects will respond.
Jesse Barnett
500,000 scoville units
Join date: 21 May 2006
Posts: 4,160
01-14-2008 14:07
From: Hewee Zetkin
Hmm. Well, true enough. I did try to set it up to do general paging, so it doesn't matter how many strings are input (and they can even change dynamically). It seemed more appropriate to the original application (from another thread) that way, since the script will have no idea how many nearby objects will respond.

Actually I said it tongue in cheek. :p With the different scripting styles of everyone, the more examples the better. Usually there is something, someone posted that will get the idea across.
_____________________
I (who is a she not a he) reserve the right to exercise selective comprehension of the OP's question at anytime.
From: someone
I am still around, just no longer here. See you across the aisle. Hope LL burns in hell for archiving this forum
Cherry Hotaling
Registered User
Join date: 25 Feb 2007
Posts: 86
01-15-2008 08:53
Thank you for your examples they were AWESOME!

But I have an issue trying to merge them.

I successfully created another Multiple page Dialog script for pre defined values.

But How do I merge the response from the other prims (The part listen in the givedialog() timer piece)

To give the result I want in the Slightly modded script below?
(I left the list targetNames List with the numbers in it for testing I was doing)

integer PING_CHANNEL = -893397710;
integer DIALOG_CHANNEL = -893397711; // Channel for llDialog to listen and say on
string PING_QUERY_NPC = "querynpc";
string PING_RESPONSE_NPC = "responsenpc";
string PING_QUERY_PC = "querypc";
string PING_RESPONSE_PC = "responsepc";
list menu =["NPC Targets", "PC Targets"];
list targetKeys = [];
list targetNames = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16"];
list first_menu;
list second_menu;




default
{
state_entry()
{
DIALOG_CHANNEL = (integer)llFrand(2147483647);
llListen(DIALOG_CHANNEL, "", "", "";);
}
touch_start(integer total_number)
{
llDialog("", "Pick an NPC or Player Character Target", menu, DIALOG_CHANNEL);

}
listen(integer channel, string name, key id, string message){
if(message == "Next";){
llDialog("", "Pick a number or Back for more", second_menu, DIALOG_CHANNEL);
}
else if(message == "Back";){
llDialog("", "Pick a number or Next for more", first_menu, DIALOG_CHANNEL);
}else if(message == "NPC Targets";){

// NPC Target Response (List all PC Targets that responded to the Ping say. llSay(PING_CHANNEL, PING_QUERY_NPC);
if(llGetListLength(targetNames) > 12){
first_menu = llList2List(targetNames, 0, 10) + "Next";
//Remember that a list starts at 0, not 1, so we end
//at 10 to have 11 buttons + the "Next" button
second_menu = "Back" + llList2List(targetNames, 11, -1);
llDialog("", "Pick a number or Next for more", first_menu, DIALOG_CHANNEL);
}
}else if(message == "PC Targets";){

// PC Target Response (List all PC Targets that responded to the Ping say. llSay(PING_CHANNEL, PING_QUERY_PC);

if(llGetListLength(targetNames) > 12){
first_menu = llList2List(targetNames, 0, 10) + "Next";
//Remember that a list starts at 0, not 1, so we end
//at 10 to have 11 buttons + the "Next" button
second_menu = "Back" + llList2List(targetNames, 11, -1);
llDialog("", "Pick a number or Next for more", first_menu, DIALOG_CHANNEL);
}

}else{
llOwnerSay("You picked number " + message);
}
}

}

Thank you
-Cherry Hotaling
Cherry Hotaling
Registered User
Join date: 25 Feb 2007
Posts: 86
01-15-2008 12:52
For Example This is a mess below.


integer PING_CHANNEL = -893397710;
integer DIALOG_CHANNEL = -893397711; // Channel for llDialog to listen and say on
string PING_QUERY_NPC = "querynpc";
string PING_RESPONSE_NPC = "responsenpc";
string PING_QUERY_PC = "querypc";
string PING_RESPONSE_PC = "responsepc";
list MENU = ["NPC Targets", "PC Targets"]; // the main menu
list targetKeys = [];
list targetNames = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16"];
integer nTargets = 0;
float PING_TIMEOUT_SECONDS = 0.4;
integer MAX_TARGETS = 24;

list first_menu;
list second_menu;

giveDialog()
{
list choices = [];
integer i;
for (i = 0; i < nTargets; ++i)
{
string choice = (string)(i+1)+" "+llList2String(targetNames, i);
choices = (choices=[])+choices+choice;
}

llDialog(llGetOwner(),"Choose a target",choices,DIALOG_CHANNEL);
}


default
{
state_entry()
{
DIALOG_CHANNEL = (integer)llFrand(2147483647);
llListen(PING_CHANNEL, "", NULL_KEY, PING_RESPONSE_NPC);
llListen(PING_CHANNEL, "", NULL_KEY, PING_RESPONSE_PC);
llListen(DIALOG_CHANNEL, "", llGetOwner(), "";);
}
touch_start(integer total_number)
{
llDialog("", "Pick an NPC or Player Character Target", MENU, DIALOG_CHANNEL);

}
listen(integer channel, string name, key id, string message){

if (channel == PING_CHANNEL && message == PING_RESPONSE_NPC)
{
if (nTargets < MAX_TARGETS &&
llListFindList(targetKeys, [ id ]) < 0)
{
targetKeys = (targetKeys=[])+targetKeys+[ id ];
targetNames = (targetNames=[])+targetNames+[ name ];
++nTargets;

if (nTargets >= MAX_TARGETS)
{
llSetTimerEvent(0.0);
giveDialog();
}
}
}
else if (channel == PING_CHANNEL && message == PING_RESPONSE_PC)
{
if (nTargets < MAX_TARGETS &&
llListFindList(targetKeys, [ id ]) < 0)
{
targetKeys = (targetKeys=[])+targetKeys+[ id ];
targetNames = (targetNames=[])+targetNames+[ name ];
++nTargets;

if (nTargets >= MAX_TARGETS)
{
llSetTimerEvent(0.0);
giveDialog();
}
}
}



if(message == "Next";){
llDialog("", "Pick a number or Back for more", second_menu, DIALOG_CHANNEL);
}
else if(message == "Back";){
llDialog("", "Pick a number or Next for more", first_menu, DIALOG_CHANNEL);
}

else if(message == "NPC Targets";){

llSay(PING_CHANNEL, PING_QUERY_NPC);
llSetTimerEvent(PING_TIMEOUT_SECONDS);

// NPC Target Response (List all PC Targets that responded to the Ping say. llSay(PING_CHANNEL, PING_QUERY_NPC);
if(llGetListLength(targetNames) > 12){
first_menu = llList2List(targetNames, 0, 10) + "Next";
//Remember that a list starts at 0, not 1, so we end
//at 10 to have 11 buttons + the "Next" button
second_menu = "Back" + llList2List(targetNames, 11, -1);
llDialog("", "Pick a number or Next for more", first_menu, DIALOG_CHANNEL);
}
}else if(message == "PC Targets";){

// PC Target Response (List all PC Targets that responded to the Ping say. llSay(PING_CHANNEL, PING_QUERY_PC);

if(llGetListLength(targetNames) > 12){
first_menu = llList2List(targetNames, 0, 10) + "Next";
//Remember that a list starts at 0, not 1, so we end
//at 10 to have 11 buttons + the "Next" button
second_menu = "Back" + llList2List(targetNames, 11, -1);
llDialog("", "Pick a number or Next for more", first_menu, DIALOG_CHANNEL);
}

}else{
llOwnerSay("You picked number " + message);
}
}
timer()
{
llSetTimerEvent(0.0);
giveDialog();
}

}







How Do I logically merge this:

if(llGetListLength(targetNames) > 12){
first_menu = llList2List(targetNames, 0, 10) + "Next";
second_menu = "Back" + llList2List(targetNames, 11, -1);

With this:

if (nTargets < MAX_TARGETS &&
llListFindList(targetKeys, [ id ]) < 0)
{
targetKeys = (targetKeys=[])+targetKeys+[ id ];
targetNames = (targetNames=[])+targetNames+[ name ];
++nTargets;

Because It needs to know the amount of calls from the prims to generate the pages right? Obviously the way it stands now it opens 2 Dialogs one with the numbers and the one with the Call back from a pim.

Thanks
-Cherry Hotaling
Hewee Zetkin
Registered User
Join date: 20 Jul 2006
Posts: 2,702
01-15-2008 14:05
You'll want to increase or remove the maximum number of targets. Most likely you'll always wait the timeout period to mark the end of the responses, instead of also ending when you get a certain number. If you look at the paged menu script I posted above, you'll see the paging/dialog bit doesn't depend on the size of the list of choices (I mean, it USES the size, but it doesn't assume it is any particular value, other than being non-zero). You'll have to change the function to use your variables rather than those in the example, or perhaps to accept the list of choices as a parameter.
Cookie Bertone
Music & Audio
Join date: 13 May 2006
Posts: 13
03-22-2008 16:23
Hat's off to Jesse Barnett (see above). His idea worked (almost perfectly) for me.