User:ANSI Soderstrom/Extended Dialog Example

From Second Life Wiki
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

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);
       // Reset the timer...
       llResetTime();
   }    
   
   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>