User:ANSI Soderstrom/Extended Dialog Example
Leave a comment
Extended Dialog Example
Some People in SL are asking me, how would myself realize a extended dialog menu (with timeout, dynamic content, sort-option, ...)
Before i invent the wheel every week new, i will post my "best" code here, so in future i can simply refer to this page.
<lsl> // Extended Dialog Example for your Items // (C) 09/2010 ANSI Soderstrom
// First, let us define some example choices... list TEST_DIALOG_CHOICES = ["A","B","C","1","2","3","a","b","c","test1","test3","test2"];
float TimeOut = 30; // (in Seconds) We need a Timeout for the Listener, not least because laaaaag. float maxButtons = 12; // How many Buttons shall we have per Page ? (12 is the maximum)
integer Sort = TRUE; // Should i Sort the List ? (Logically) 0..9 --> a...b --> A...B integer Sort_Ascending = TRUE; // (TRUE = Ascending, FALSE = Descending) permute the list vertically. Have only Effect if Sort == TRUE;
integer CHANNEL; // We need a global channel... integer PAGE; // ...and a global memory for the actual Pagenumber
key LastMenuUser; // ...and don´t forget who is the actual controluser.
list CreateNavigation(integer PAGES) {
list navi = ["No Clue"]; if((PAGE < 1 || PAGE == PAGES) && PAGES != 1) { PAGE = PAGES; navi += ["<<<","FIRST"]; } else if((PAGE > PAGES || PAGE == 1) && PAGES != 1) { PAGE = 1; navi += ["LAST",">>>"]; } else if (PAGES != 1) { navi += ["<<<",">>>"]; } if(PAGES==1) { navi += [" "," "]; } return navi;
}
list Padding(integer FillUp) {
list PlaceHolder; if(FillUp<0) { do { PlaceHolder += ["~"]; // Nr# 126 in ASCII Table (Highest one, will be ever the last Letter in List?) ++FillUp; } while(FillUp!=0); } return PlaceHolder;
}
CreateMenu(key id, list menu) {
if(Sort) { menu = llListSort(menu,1,Sort_Ascending); } integer PAGES = llCeil(llGetListLength(menu)/(maxButtons-3)); list NAVIGATION = CreateNavigation(PAGES); integer length = (integer)maxButtons-llGetListLength(NAVIGATION); list NEW_MENU = llList2List(menu,(PAGE*length-length),(PAGE*length-1)) + Padding(llGetListLength(menu)-(PAGE*length)); llDialog(id, "(Page " + (string)PAGE + "/" + (string)PAGES + ")\n \nSelect your Height",NAVIGATION + NEW_MENU, CHANNEL);
}
default {
state_entry() { // prevent errormessages if(maxButtons > 12) { maxButtons = 12; } // Let us scramble the List... (...as example) TEST_DIALOG_CHOICES = llListRandomize(TEST_DIALOG_CHOICES,1); // and clear the timerview llSetText("",<1,1,1>,1); } touch_start(integer i) { // If we touch in this state, iam sure we are on the first Page PAGE = 1; // Let us find a random channel CHANNEL = -llRound(llFrand(1000000)); // remember for the user LastMenuUser = llDetectedKey(0); // All done, we have the point to create our first menupage CreateMenu(LastMenuUser,TEST_DIALOG_CHOICES); // and for better code reading, we use a new state ! state Dialog; }
}
state Dialog {
state_entry() { // Listen to the opened channel llListen(CHANNEL,"",NULL_KEY,""); // and count the time down to our timeout llSetTimerEvent(1); } listen(integer channel, string name, key id, string message) { // if we have clicked a menuchoice, we can find the answer from the dialog here if(~llListFindList(TEST_DIALOG_CHOICES,[message])) { // for debugging, tell us our choice llSay(0, "Your Choice : " + message); // and back to standby state default; } else { // we have clicked a Navigation button, find out which button ... if(message == "<<<" || message == "BACK") { --PAGE; } else if(message == ">>>") { ++PAGE; } else if(message == "FIRST") { PAGE = 1; } else if(message == "LAST") { PAGE = llCeil(llGetListLength(TEST_DIALOG_CHOICES)/(maxButtons-3)); } else { // ... or for confusing, abort all :) (will reached with the "No Clue"-Button) state default; } // if we click a button, be sure we reset the timercount and start a new timeout-counter llResetTime(); // We are still in the listen event, so we can draw a new menu CreateMenu(id,TEST_DIALOG_CHOICES); } } touch_start(integer i) { // listen only to the control-user and give him the chance to draw a new menu if one page is not appearing... if(llDetectedKey(0) == LastMenuUser) { CreateMenu(llDetectedKey(0),TEST_DIALOG_CHOICES); } } timer() { // draw the timeout-counter on the prim llSetText((string)(llRound(TimeOut - llGetTime())) + " seconds left",<1,1,1>,1); // and tell us if we run out of time... if(llGetTime() > TimeOut) { llSay(0,"Dialog expired"); // back to standby state default; } }
} </lsl>