Difference between revisions of "User:ANSI Soderstrom/Extended Dialog Example"

From Second Life Wiki
Jump to navigation Jump to search
 
(6 intermediate revisions by the same user not shown)
Line 4: Line 4:
== Extended Dialog Example ==
== Extended Dialog Example ==


Some People in SL are asking me, how woud myself realize a extended dialog menu (with timeout, dynamic content, sort-option, ...)
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 ibn future i can simply refer to this page.
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>
<lsl>
Line 12: Line 12:
// (C) 09/2010 ANSI Soderstrom
// (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"];
list TEST_DIALOG_CHOICES = ["A","B","C","1","2","3","a","b","c","test1","test3","test2"];


float      TimeOut        =  30;    // seconds
float      TimeOut        =  30;    // (in Seconds) We need a Timeout for the Listener, not least because laaaaag.
float      maxButtons      =  12;    // How many Buttons
float      maxButtons      =  12;    // How many Buttons shall we have per Page ? (12 is the maximum)


integer    Sort            =  TRUE; // Should i Sort the List ?
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;


// Have only Effect if Sort == TRUE;
integer CHANNEL;                        // We need a global channel...
integer     ReverseUp2Down  =  FALSE;
integer PAGE;                           // ...and a global memory for the actual Pagenumber


integer CHANNEL;
key LastMenuUser;                       // ...and don´t forget who is the actual controluser.
integer PAGE;
 
key LastMenuUser;
   
   
list CreateNavigation(integer PAGES) {
list CreateNavigation(integer PAGES) {
Line 56: Line 55:


CreateMenu(key id, list menu) {
CreateMenu(key id, list menu) {
    if(Sort) {
        menu = llListSort(menu,1,Sort_Ascending);
    }
     integer PAGES = llCeil(llGetListLength(menu)/(maxButtons-3));
     integer PAGES = llCeil(llGetListLength(menu)/(maxButtons-3));
     list NAVIGATION = CreateNavigation(PAGES);
     list NAVIGATION = CreateNavigation(PAGES);
Line 65: Line 67:
default {
default {
     state_entry() {
     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);  
         llSetText("",<1,1,1>,1);  
     }
     }
      
      
     touch_start(integer i) {
     touch_start(integer i) {
        // If we touch in this state, iam sure we are on the first Page
         PAGE = 1;
         PAGE = 1;
        // Let us find a random channel
         CHANNEL = -llRound(llFrand(1000000));
         CHANNEL = -llRound(llFrand(1000000));
        // remember for the user
         LastMenuUser = llDetectedKey(0);
         LastMenuUser = llDetectedKey(0);
        // All done, we have the point to create our first menupage
         CreateMenu(LastMenuUser,TEST_DIALOG_CHOICES);  
         CreateMenu(LastMenuUser,TEST_DIALOG_CHOICES);  
         llResetTime(); 
         // and for better code reading, we use a new state !
         state Dialog;
         state Dialog;
     }
     }
Line 80: Line 93:
state Dialog {
state Dialog {
     state_entry() {
     state_entry() {
        // Listen to the opened channel
         llListen(CHANNEL,"",NULL_KEY,"");
         llListen(CHANNEL,"",NULL_KEY,"");
        // and count the time down to our timeout
         llSetTimerEvent(1);
         llSetTimerEvent(1);
        // Reset the timer...
        llResetTime();
     }     
     }     
      
      
     listen(integer channel, string name, key id, string message) {
     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])) {
         if(~llListFindList(TEST_DIALOG_CHOICES,[message])) {
            // for debugging, tell us our choice
             llSay(0, "Your Choice : " + message);
             llSay(0, "Your Choice : " + message);
            // and back to standby
             state default;
             state default;
         } else  {
         } else  {
            // we have clicked a Navigation button, find out which button ...
             if(message == "<<<" || message == "BACK") {
             if(message == "<<<" || message == "BACK") {
                 --PAGE;
                 --PAGE;
Line 98: Line 119:
                 PAGE = llCeil(llGetListLength(TEST_DIALOG_CHOICES)/(maxButtons-3));
                 PAGE = llCeil(llGetListLength(TEST_DIALOG_CHOICES)/(maxButtons-3));
             } else {
             } else {
                // ... or for confusing, abort all :) (will reached with the "No Clue"-Button)
                 state default;   
                 state default;   
             }
             }
            // if we click a button, be sure we reset the timercount and start a new timeout-counter
             llResetTime();
             llResetTime();
            // We are still in the listen event, so we can draw a new menu
             CreateMenu(id,TEST_DIALOG_CHOICES);     
             CreateMenu(id,TEST_DIALOG_CHOICES);     
         }
         }
Line 106: Line 130:
      
      
     touch_start(integer i) {
     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) {
         if(llDetectedKey(0) == LastMenuUser) {
             CreateMenu(llDetectedKey(0),TEST_DIALOG_CHOICES);   
             CreateMenu(llDetectedKey(0),TEST_DIALOG_CHOICES);   
Line 112: Line 137:
      
      
     timer() {
     timer() {
        // draw the timeout-counter on the prim
         llSetText((string)(llRound(TimeOut - llGetTime())) + " seconds left",<1,1,1>,1);
         llSetText((string)(llRound(TimeOut - llGetTime())) + " seconds left",<1,1,1>,1);
        // and tell us if we run out of time...
         if(llGetTime() > TimeOut) {
         if(llGetTime() > TimeOut) {
             llSay(0,"Dialog expired");
             llSay(0,"Dialog expired");
            // back to standby
             state default;
             state default;
         }
         }

Latest revision as of 23:21, 28 September 2010

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>