Dialog pagination not quite there
|
Celty Westwick
Registered User
Join date: 24 Jun 2006
Posts: 145
|
07-19-2009 13:32
I'm trying to add a third page to a dialog menu, it "works", except for one thing. Any number in inventory under the specified maximum works for pages 1 and 2. However, for the 3rd page it must be the 32 or 33, neither more nor less, or a 3rd page fails. create_menus() { integer numberOfLandmarks = llGetInventoryNumber(INVENTORY_LANDMARK); i = 0; MENU1 =[]; MENU2 =[]; MENU3 =[]; if (numberOfLandmarks <= 12) { for (; i < numberOfLandmarks; ++i) { MENU1 += llGetSubString(llGetInventoryName(INVENTORY_LANDMARK, i), 0, 12); } } else if (numberOfLandmarks > 12 & numberOfLandmarks <= 22) { for (; i < 11; ++i) { MENU1 += llGetSubString(llGetInventoryName(INVENTORY_LANDMARK, i), 0, 12); } if (numberOfLandmarks > 21) numberOfLandmarks = 22; for (; i < numberOfLandmarks; ++i) { MENU2 += llGetSubString(llGetInventoryName(INVENTORY_LANDMARK, i), 0, 12); } MENU1 += ">"; MENU2 += "<"; } else if (numberOfLandmarks > 22 & numberOfLandmarks <= 33) { for (; i < 11; ++i) { MENU1 += llGetSubString(llGetInventoryName(INVENTORY_LANDMARK, i), 0, 12); } if (numberOfLandmarks >= 22) numberOfLandmarks = 21; for (; i < numberOfLandmarks; ++i) { MENU2 += llGetSubString(llGetInventoryName(INVENTORY_LANDMARK, i), 0, 12); } if (numberOfLandmarks <= 33 )// numberOfLandmarks = 32; for (; i < numberOfLandmarks; ++i) { MENU3 += llGetSubString(llGetInventoryName(INVENTORY_LANDMARK, i), 0, 12); } MENU1 += ">>"; MENU2 += "<<"; MENU2 += ">>>"; MENU3 += "<<<"; } }
I'd like to get it to function so that any number under the max works, and any number over stops at 3 pages of menus, regardless.
|
Jesse Barnett
500,000 scoville units
Join date: 21 May 2006
Posts: 4,160
|
07-19-2009 14:15
if (numberOfLandmarks <= 33 )//
_____________________
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
|
Celty Westwick
Registered User
Join date: 24 Jun 2006
Posts: 145
|
07-19-2009 15:07
Jesse, if you mean remove the line: if (numberOfLandmarks <= 33 )//
It behaves the same, still does not work when i did that.
|
EF Klaar
Registered User
Join date: 11 Jun 2007
Posts: 330
|
07-19-2009 16:43
I don't know if it's any use to you, but this is a basic script I use for selecting courtesy flags for my boat. It's putting textures into the the menu rather than landmarks, but the principle is the same. As it stands, there is no limit to the number of flags it can deal with, and I didn't bother with a "<< BACK" button either, but those should be fairly easy to add if needed. Also, in flagrant contravention of best practice, it keeps a listen permanently open, but this is deliberate to allow me to select a flag using chat, which is sometimes easier than trying to click on objects and menu buttons when things get busy. integer menu_channel = 1; integer next_flag; integer number_of_flags; list flags;
DoMenu (integer start_flag) { list buttons; if ((number_of_flags - start_flag + 1) > 12) { buttons = llList2List (flags, start_flag, start_flag + 10) + ["MORE >>"]; next_flag = start_flag + 11; } else buttons = llList2List (flags, start_flag, number_of_flags - 1); llDialog (llGetOwner (), "Select a courtesy flag:", buttons, menu_channel); }
default { state_entry () { llListen (menu_channel, "", llGetOwner (), ""); }
touch_start (integer number) { if (llDetectedKey (0) == llGetOwner ()) { integer index = 0; flags = []; number_of_flags = llGetInventoryNumber (INVENTORY_TEXTURE); while (index < number_of_flags) flags += llGetInventoryName (INVENTORY_TEXTURE, index++); DoMenu (0); } }
listen (integer channel, string name, key id, string message) { if (message == "MORE >>") DoMenu (next_flag); else if (llListFindList (flags, [message]) > -1) { llSetTexture (message, 2); llSetTexture (message, 4); } } }
|
Innula Zenovka
Registered User
Join date: 20 Jun 2007
Posts: 1,825
|
07-19-2009 17:00
I started to understand how do multi-page menus -- and I am eternally grateful to both Hewee Zetkin and Jesse Barnett for their examples (and for a lot else, of course) -- from studying this thread /54/94/235155/1.html
|
Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
|
07-19-2009 17:44
and the missing dynamic that I mentioned in that thread but never got around to linking....  code could really use some clean up... I was doing much more quick and dirty back then.
_____________________
| | . "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... | - 
|
Celty Westwick
Registered User
Join date: 24 Jun 2006
Posts: 145
|
07-20-2009 00:48
Thanks EF, Innula, and Void. I agree Innula - don't know how many times Jesse and Void have either helped with an answer to an issue directly or by a previous post, but I'd be lost without them. I sometimes feel like Hansel ("Oh no, where's those breadcrumbs, Gretel!"  . In fact, this script was done with Jesse and Void leading me progressively through issues: /54/83/323971/1.htmlI love the result, I just got the bug to "improve" the menuing for more pages. I would like to retain bi-directional navigation. I was hoping to just fix the 3rd page issue on that code, as it's part of a that larger script. May need to look into a bigger redo though, based on your help. I'll try to tinker. I assume, Void, you did a "more" button approach rather than "forward" / "back" buttons due to then having to code in when they are necessary on a particular page? It's very slick - love the alphabetical ordering on the menu. I can see where with the ordering a back button is less necessary. I did try converting it for use as a landmark giver as a starting point, and ran into the 1-24 characters right away. I tried trimming the name length: string vStrTemp; while (~(--i)) { vStrTemp = llGetSubString(llGetInventoryName(INVENTORY_LANDMARK, i), 0, 12); if (llStringLength( vStrTemp ) < 25) { gLstButtons = (list)vStrTemp + gLstButtons; } else { --vIntNotes; } } and that works as far as the button names displaying but breaks them from actually working, giving the error - Object: Unable to give inventory: 'No item named '> Furniture Adagio'.'. My guess from previous similar issue would be to add a llListFindList later in your script in the listen but my head can't see how on your code that would work, I better get some sleep 
|
Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
|
07-20-2009 04:56
you're on the right track with it... and yeah I figured if it's in order, why go back (since then I've been variously hounded about that) another reasons is that adding the page number to the dialog allowed for mutiple avs to be served dialogs with different pages at the same time (not that I couldn't ad the page number for a back button)
since it does work on the alphabetic ordering, if you search for the button in the button list, the index there will match the index in inventory, and you grab the full name that way =)
_____________________
| | . "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... | - 
|
Jesse Barnett
500,000 scoville units
Join date: 21 May 2006
Posts: 4,160
|
07-20-2009 06:59
I will have a chance to look at it closer later but for now and starting with this section:
else if (numberOfLandmarks > 22 & numberOfLandmarks <= 33)
That could be written as just:
else if (numberOfLandmarks > 22
You are redefining and capping the number of Lms here:
if (numberOfLandmarks >= 22) numberOfLandmarks = 21; for (; i < numberOfLandmarks; ++i)//Change to hard coded: for (; i < 22; ++i)
You already know that the number is above 22 because of your if test so there is no need to cap it here. Instead you should be capping it at 32 BUT your if test for that was faulty which is what I was pointing to earlier:
if (numberOfLandmarks <= 33 )//
That is telling your script that if you have LESS then and should be written instead as a MORE then test.
_____________________
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
|
Jesse Barnett
500,000 scoville units
Join date: 21 May 2006
Posts: 4,160
|
07-20-2009 07:07
And to make it less confusing try it like this?: create_menus() { integer numberOfLandmarks = llGetInventoryNumber(INVENTORY_LANDMARK); i = 0; MENU1 =[]; MENU2 =[]; MENU3 =[]; if (numberOfLandmarks <= 12) { for (; i < numberOfLandmarks; ++i) { MENU1 += llGetSubString(llGetInventoryName(INVENTORY_LANDMARK, i), 0, 12); } } else if (numberOfLandmarks > 12 & numberOfLandmarks <= 22) { for (; i < 11; ++i) { MENU1 += llGetSubString(llGetInventoryName(INVENTORY_LANDMARK, i), 0, 12); } for (; i < numberOfLandmarks; ++i) { MENU2 += llGetSubString(llGetInventoryName(INVENTORY_LANDMARK, i), 0, 12); } MENU1 += ">"; MENU2 += "<"; } else if (numberOfLandmarks > 22) { for (; i < 11; ++i) { MENU1 += llGetSubString(llGetInventoryName(INVENTORY_LANDMARK, i), 0, 12); } for (; i < 22; ++i) { MENU2 += llGetSubString(llGetInventoryName(INVENTORY_LANDMARK, i), 0, 12); } if (numberOfLandmarks > 32) numberOfLandmarks = 32; for (; i < numberOfLandmarks; ++i) { MENU3 += llGetSubString(llGetInventoryName(INVENTORY_LANDMARK, i), 0, 12); } MENU1 += ">>"; MENU2 += "<<"; MENU2 += ">>>"; MENU3 += "<<<"; } }
_____________________
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
|
Celty Westwick
Registered User
Join date: 24 Jun 2006
Posts: 145
|
07-20-2009 10:00
Jesse inserted that code and got an error of - "llDialog: all buttons must have label strings", when navigating to the second page which fails to appear. I see what you mean about the double filtering , it's just what I wound up with in experimenting, and actually the if (numberOfLandmarks <= 33 )//
is not necessary. This works just the same as the original:
else if (numberOfLandmarks > 22) { for (; i < 11; ++i) { MENU1 += llGetSubString(llGetInventoryName(INVENTORY_LANDMARK, i), 0, 12); } if (numberOfLandmarks >= 22) numberOfLandmarks = 21; for (; i < numberOfLandmarks; ++i) { MENU2 += llGetSubString(llGetInventoryName(INVENTORY_LANDMARK, i), 0, 12); } numberOfLandmarks = 32; for (; i < numberOfLandmarks; ++i) { MENU3 += llGetSubString(llGetInventoryName(INVENTORY_LANDMARK, i), 0, 12); } MENU1 += ">>"; MENU2 += "<<"; MENU2 += ">>>"; MENU3 += "<<<";
It works any any number of landmarks less than 22, but again the 3rd page must be in that small range or fails if more or less. If I try inserting: if (numberOfLandmarks > 32) the 3rd page will fail though inserting: if (numberOfLandmarks < 32) will function but not make it work any better.
|
Jesse Barnett
500,000 scoville units
Join date: 21 May 2006
Posts: 4,160
|
07-20-2009 11:12
Tested and works in world: integer i; key detKey; list MENU1; list MENU2; list MENU3;
create_menus(){ integer numberOfLandmarks = llGetInventoryNumber(INVENTORY_LANDMARK); i = 0; MENU1 =[]; MENU2 =[]; MENU3 =[]; if (numberOfLandmarks <= 12) { for (; i < numberOfLandmarks; ++i) { MENU1 += llGetSubString(llGetInventoryName(INVENTORY_LANDMARK, i), 0, 12); } } else if (numberOfLandmarks > 12 & numberOfLandmarks <= 22) { for (; i < 11; ++i) { MENU1 += llGetSubString(llGetInventoryName(INVENTORY_LANDMARK, i), 0, 12); } for (; i < numberOfLandmarks; ++i) { MENU2 += llGetSubString(llGetInventoryName(INVENTORY_LANDMARK, i), 0, 12); } MENU1 += ">"; MENU2 += "<<"; } else if (numberOfLandmarks > 22) { for (; i < 11; ++i) { MENU1 += llGetSubString(llGetInventoryName(INVENTORY_LANDMARK, i), 0, 12); } for (; i < 21; ++i) { MENU2 += llGetSubString(llGetInventoryName(INVENTORY_LANDMARK, i), 0, 12); } if (numberOfLandmarks > 32) numberOfLandmarks = 32; for (; i < numberOfLandmarks; ++i) { MENU3 += llGetSubString(llGetInventoryName(INVENTORY_LANDMARK, i), 0, 12); } MENU1 += ">"; MENU2 += "<<"; MENU2 += ">>"; MENU3 += "<<<"; } } default { state_entry() { create_menus(); llListen(-99, "", "", ""); } touch_start(integer total_number) { detKey = llDetectedKey(0); llDialog(detKey, "menus", MENU1, -99); } listen(integer channel, string name, key id, string msg) { if (msg == "<<" || msg == "<<<") { llDialog(detKey, "menus", MENU1, -99); } else if (msg == ">") { llDialog(detKey, "menus", MENU2, -99); } else if (msg == ">>") { llDialog(detKey, "menus", MENU3, -99); } else { llOwnerSay(msg); } } changed(integer change) { if (change && CHANGED_INVENTORY) { create_menus(); } } }
_____________________
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
|
Jesse Barnett
500,000 scoville units
Join date: 21 May 2006
Posts: 4,160
|
07-20-2009 11:26
WOW it sucks getting old I knew this thread looked familiar and finally had to search back to find this thread: /54/83/323971/1.htmlGlad to see you still learning and experimenting Celty!!!!!
_____________________
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
|
Celty Westwick
Registered User
Join date: 24 Jun 2006
Posts: 145
|
07-20-2009 16:21
LOL, well I did put that URL in this thread  . Ohh, that code does work great, added in the menuID's, made the variable names consistent to get it to function with the rest of the script and whoot, there it is! I see the change in logic you used. It's also a more elegant, compact way to do it than I was using. Yes learning, I'm working on adding a new level of spells for my wands and staffs, and thought hmm I need to make the menu for this better (that one is sensor based rather than inventory but has a single dialog page), which led to saying hmm, start with improving that other project menu, then convert it for sensor use... So here I am. I'll play with Void's version as well to see if I can get it working as well, if nothing else because I'll learn more by trying to understand how you both approach it. Going to send you two a sample of the two projects when they are complete to let you see the results. Thanks yet again 
|
Celty Westwick
Registered User
Join date: 24 Jun 2006
Posts: 145
|
07-21-2009 00:18
Void, here's what I did to modify your menu approach as a landmark giver rather than notecards, with name lengths taken care of: //--// v7-D Notecard Giver with MultiPage Dialog Support //-- Free from Void Singer... credit appreciated... credits appreciated more // Modified slightly for Landmarks by Celty string LM; integer lmIdx;
string cSTR_MESSAGE = "Landmarks:\n Choose a button to recieve a copy..."; integer cINT_DIALOG_CHANNEL = -41; list gLstButtons;
//-- return a page full of results to llDialog list vfParseButtons( integer vIntPage ) { list vLstReturn; integer vIntLength = llGetListLength( gLstButtons ); integer vIntStart = llAbs(vIntPage) * 11;
//-- sanity check if (vIntLength - vIntStart > 0) { //-- test for last full page if (vIntLength - vIntStart > 12) { vLstReturn += llList2List( gLstButtons, vIntStart + 9, vIntStart + 10 ); //-- format "MORE" button if (vIntPage < 10) { vLstReturn += ["MORE (0" + (string)(vIntPage + 1) + ")"]; } else { vLstReturn += ["MORE (" + (string)(vIntPage + 1) + ")"]; } //-- reorder/fill-out list vLstReturn += llList2List( gLstButtons, vIntStart + 6, vIntStart + 8 ); vLstReturn += llList2List( gLstButtons, vIntStart + 3, vIntStart + 5 ); vLstReturn += llList2List( gLstButtons, vIntStart, vIntStart + 2 );
//-- last page scenario } else { integer i = vIntLength - 1; //-- correct order by full rows for (i; i - 2 >= vIntStart; i -= 3) { vLstReturn += llList2List( gLstButtons, i -2, i ); } //-- add any leftovers if (i >= vIntStart) { vLstReturn += llList2List( gLstButtons, vIntStart, i ); } } } return vLstReturn; }
default { state_entry() { llOwnerSay( "Retrieving Note List..." ); integer vIntNotes = llGetInventoryNumber(INVENTORY_LANDMARK); integer i = vIntNotes;
//-- add the name of each notecard to the list (alpha order) string vStrTemp; while (~(--i)) { // Trim those those landmark names for buttons on vStrTemp vStrTemp = llGetSubString(llGetInventoryName(INVENTORY_LANDMARK, i), 0, 12); if (llStringLength( vStrTemp ) < 25) { gLstButtons = (list)vStrTemp + gLstButtons; } else { --vIntNotes; } } llOwnerSay( (string)vIntNotes + " Notes Available. Notecard Giver Started" ); state vsWorking; } }
state vsWorking { touch_start( integer vIntTouched ) { llListen( cINT_DIALOG_CHANNEL, "", llDetectedKey( 0 ), "" ); llSetTimerEvent( 30.0 ); //-- set timeout for listen //-- send dialog page 0 to user that touched me llDialog( llDetectedKey( 0 ),cSTR_MESSAGE, vfParseButtons( 0 ), cINT_DIALOG_CHANNEL ); }
//-- listen for response from user listen( integer vIntChannel, string vStrName, key vKeyID, string vStrMessage ) { //-- if the more button is pressed, send the next dialog page if (llGetSubString( vStrMessage, 0, 5 ) == "MORE (") { llSetTimerEvent( 30.0 ); llDialog( vKeyID,cSTR_MESSAGE,vfParseButtons( (integer)llGetSubString( vStrMessage, 6, 7 ) ),cINT_DIALOG_CHANNEL ); //-- or give them a notecard on the button they pressed } else { // Tie those trimmed button names back to data lmIdx = llListFindList(gLstButtons, (list) vStrMessage); LM = (llGetInventoryName(INVENTORY_LANDMARK, lmIdx)); llGiveInventory( vKeyID, LM ); } }
timer() { //-- turn off timer because SL keeps it between state changes llSetTimerEvent( 0.0 ); state vsListenKill; }
changed( integer vBitChanged ) { //-- reset the script if either the inventory or owner change if (vBitChanged & (CHANGED_OWNER | CHANGED_INVENTORY)) { llOwnerSay( "Owner/Inventory Changed, Resetting..." ); llResetScript(); } } }
state vsListenKill { state_entry() { //-- just here to turn off all active listens and go back state vsWorking; } }
Took me awhile to figure out, but the answer to trimming turned out simpler than I thought it would be. Very quick code you wrote even with alot of items in inventory.
|
Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
|
07-21-2009 06:59
looks good, and very similar to what I'dve done myself... (which is amazing considering how often I go crosseyed looking at my own code... yes it's true)
_____________________
| | . "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... | - 
|
Celty Westwick
Registered User
Join date: 24 Jun 2006
Posts: 145
|
07-21-2009 11:19
Runs in circles trying to add a "back" button, drops dizzy.
|