Notecard Reading
|
|
Haruki Watanabe
llSLCrash(void);
Join date: 28 Mar 2007
Posts: 434
|
09-15-2008 03:48
I'm not really sure whether I understand your question correctly, but I give it a try anyway...  Let's say, you have a list like: list colors = ["Red", <1.0, 0.0, 0.0>, "Blue", <0.0, 1.0, 0.0>, "Green", <0.0, 0.0, 1.0>]; So what you want now is having the text-values in the buttons of your dialog and once the user picks a color having the according color-vector chosen. That's when llList2ListStrided comes in handy... ( http://www.lslwiki.net/lslwiki/wakka.php?wakka=llList2ListStrided)
// Just code-snippets, assuming, you know how to use llDialog ;)
// Build up the menu for the dialog
list dlgMenu = llList2ListStrided(colors, 0, -1, 2);
// Present the dialog to the user
llDialog(userKey, "Please choose a color", dlgMenu, dlgChannel);
// The listener for the dialog-menu
listen(integer channel, string name, key id, string message){
integer pos = llListFindList(dlgMenu, [message]; // Determine the list-position of the chosen element
vector color = llList2Vector(colors, pos + 1); // the color-vector is found at pos + 1 in our color-list
}
HTH 
|
|
Jodie Suisei
Lost In LSL Code
Join date: 6 Oct 2006
Posts: 66
|
09-15-2008 10:31
I am rather familiar with basic dialogs but for the purpose of what i am attemping is to learn some more advanced dialogs for example in the code below that i will post is i was attempting to take my notecard read information and put that onto the dialog buttons but in all honestly this wiki isnt that great of a guide to use but its the only thing i could find that was both near impossible to understand fully and a pain to not break it but alas i managed to make it cause a script error not sure what i did wrong with it but here it is lol Object: llDialog: all buttons must have label strings is the error it gives me pfft was only playing around with it obviously i did something to cause the error but i cant find it only pops up when i click the next page buttons but on the whole it displays my read notecard which is simply name Anything with a bunch of words in nothing massivly complicated just so i could get it working properly.
string msg = "Please make a choice.";
list Anything; integer channel_dialog; integer listen_id; key ToucherID; key kQuery;
string iNoteCardName = "Anything";
integer iLine; integer iSkip; //if not offering a back button, there are 3 things to change: //MAX_DIALOG_CHOICES_PER_PG, and 2 code lines in the giveDialog function. //It is noted in the function exactly where and how to change these. integer N_DIALOG_CHOICES; integer MAX_DIALOG_CHOICES_PER_PG = 8; // if not offering back button, increase this to 9 string PREV_PG_DIALOG_PREFIX = "< Page "; string NEXT_PG_DIALOG_PREFIX = "> Page "; string DIALOG_DONE_BTN = "Done"; string DIALOG_BACK_BTN = "<< Back"; string SlideShowCurrent; integer pageNum; giveDialog(key ID, integer pageNum) { list buttons; integer firstChoice; integer lastChoice; integer prevPage; integer nextPage; string OnePage; N_DIALOG_CHOICES = llGetListLength(Anything); if (N_DIALOG_CHOICES <= 10) { buttons = Anything; OnePage = "Yes"; } else { integer nPages = (N_DIALOG_CHOICES+MAX_DIALOG_CHOICES_PER_PG-1)/MAX_DIALOG_CHOICES_PER_PG; if (pageNum < 1 || pageNum > nPages) { pageNum = 1; } integer firstChoice = (pageNum-1)*MAX_DIALOG_CHOICES_PER_PG; integer lastChoice = firstChoice+MAX_DIALOG_CHOICES_PER_PG-1; if (lastChoice >= N_DIALOG_CHOICES) { lastChoice = N_DIALOG_CHOICES; } if (pageNum <= 1) { prevPage = nPages; nextPage = 2; } else if (pageNum >= nPages) { prevPage = nPages-1; nextPage = 1; } else { prevPage = pageNum-1; nextPage = pageNum+1; } buttons = llList2List(Anything, firstChoice, lastChoice); } // FYI, this puts the navigation button row first, so it is always at the bottom of the dialog list buttons01 = llList2List(buttons, 0, 2); list buttons02 = llList2List(buttons, 3, 5); list buttons03 = llList2List(buttons, 6, 8); list buttons04; if (OnePage == "Yes") { buttons04 = llList2List(buttons, 9, 11); } buttons = buttons04 + buttons01 + buttons02 + buttons03; if (OnePage == "Yes") { buttons = [ DIALOG_DONE_BTN, DIALOG_BACK_BTN ]+ buttons; //omit DIALOG_BACK_BTN in line above if not offering } else { buttons =(buttons=[])+ [ PREV_PG_DIALOG_PREFIX+(string)prevPage, DIALOG_BACK_BTN, NEXT_PG_DIALOG_PREFIX+(string)nextPage, DIALOG_DONE_BTN]+buttons; //omit DIALOG_BACK_BTN in line above if not offering } llDialog(ID, "Page "+(string)pageNum+"\nChoose one:", buttons, channel_dialog); } CancelListen() { llListenRemove(listen_id); llSetTimerEvent(0); } default { state_entry() { kQuery = llGetNotecardLine(iNoteCardName, iLine); channel_dialog = ( -1 * (integer)("0x"+llGetSubString((string)llGetKey(),-5,-1)) ); } touch_start(integer total_number) { ToucherID = llDetectedKey(0); listen_id = llListen( channel_dialog, "", ToucherID, ""); pageNum = 1; giveDialog(ToucherID, pageNum); } dataserver (key query_id, string data) { if (query_id == kQuery) { if (data != EOF) { if ( llGetSubString(data, 0, 1) != "//") { Anything += [data]; } iSkip++; iLine++; kQuery = llGetNotecardLine(iNoteCardName, iLine); } } } listen(integer channel, string name, key id, string choice) { //here, you need to only: //1. implement something that happens when the back button is pressed, or omit back button //2. Go to the else event. That is where any actual choice is. Process that choice. if (choice == "-") { giveDialog(ToucherID, pageNum); } else if ( choice == DIALOG_DONE_BTN) { CancelListen(); return; } else if (choice == DIALOG_BACK_BTN) { CancelListen(); //go back to where you want } else if (llSubStringIndex(choice, PREV_PG_DIALOG_PREFIX) == 0) { pageNum = (integer)llGetSubString(choice, llStringLength(PREV_PG_DIALOG_PREFIX), -1); giveDialog(ToucherID, pageNum); } else if (llSubStringIndex(choice, NEXT_PG_DIALOG_PREFIX) == 0) { pageNum = (integer)llGetSubString(choice, llStringLength(NEXT_PG_DIALOG_PREFIX), -1); giveDialog(ToucherID, pageNum); } else { llSay(0, "You chose " + choice); } } }
my question is i have looked through the forum and even got copies of the MLP and a few other bits and peices to see how there dialog is laid out so i could try to learn how to adapt this not easy to adapt monster into something i can use effectvly all the excercise and learning im doing is trying to get the choices displayed onto buttons so then i can put in the listen event when that button is pressed to send a basic link message to another script to do something  so for example if the button was name Candy it would send link message carrying that message and for example change a texture on a prim to the colour candy. is there a much easier to understand dialog lay out on getting the notecard contents displayed onto a button open source i could pick to bits other than this wiki if so any links would be great or ideas on how i can trim this wiki script down and get it to do what i want would be great also 
|
|
Haruki Watanabe
llSLCrash(void);
Join date: 28 Mar 2007
Posts: 434
|
09-15-2008 13:24
Don't know whether I fixed it, but TextMate found some errors... here's the new code:
//string msg = "Please make a choice."; // **** this is never used in the script
list Anything;
integer channel_dialog; integer listen_id; key ToucherID;
key kQuery;
string iNoteCardName = "Anything";
integer iLine; integer iSkip; //if not offering a back button, there are 3 things to change: //MAX_DIALOG_CHOICES_PER_PG, and 2 code lines in the giveDialog function. //It is noted in the function exactly where and how to change these.
integer N_DIALOG_CHOICES; integer MAX_DIALOG_CHOICES_PER_PG = 8; // if not offering back button, increase this to 9 string PREV_PG_DIALOG_PREFIX = "< Page "; string NEXT_PG_DIALOG_PREFIX = "> Page "; string DIALOG_DONE_BTN = "Done"; string DIALOG_BACK_BTN = "<< Back"; //string SlideShowCurrent;
integer gPageNum; //****** this is declared in the giveDialog-function as well - so it might cause errors
giveDialog(key ID, integer PageNum) { list buttons; integer firstChoice; // ***** Was again declared further down in this function integer lastChoice; // ***** Was again declared further down in this function integer prevPage; integer nextPage; string OnePage;
N_DIALOG_CHOICES = llGetListLength(Anything);
if (N_DIALOG_CHOICES <= 10) { buttons = Anything; OnePage = "Yes"; }
else { integer nPages = (N_DIALOG_CHOICES+MAX_DIALOG_CHOICES_PER_PG - 1)/MAX_DIALOG_CHOICES_PER_PG;
if (PageNum < 1 || PageNum > nPages) { PageNum = 1; }
firstChoice = (PageNum - 1)*MAX_DIALOG_CHOICES_PER_PG; lastChoice = firstChoice + MAX_DIALOG_CHOICES_PER_PG - 1;
if (lastChoice >= N_DIALOG_CHOICES) { lastChoice = N_DIALOG_CHOICES; }
if (PageNum <= 1) { prevPage = nPages; nextPage = 2; }
else if (PageNum >= nPages) { prevPage = nPages - 1; nextPage = 1; }
else { prevPage = PageNum - 1; nextPage = PageNum + 1; } buttons = llList2List(Anything, firstChoice, lastChoice); } // FYI, this puts the navigation button row first, so it is always at the bottom of the dialog list buttons01 = llList2List(buttons, 0, 2); list buttons02 = llList2List(buttons, 3, 5); list buttons03 = llList2List(buttons, 6, 8); list buttons04;
if (OnePage == "Yes") { buttons04 = llList2List(buttons, 9, 11); }
buttons = buttons04 + buttons01 + buttons02 + buttons03;
if (OnePage == "Yes") { buttons = [ DIALOG_DONE_BTN, DIALOG_BACK_BTN ]+ buttons; //omit DIALOG_BACK_BTN in line above if not offering }
else { buttons =(buttons=[])+ [ PREV_PG_DIALOG_PREFIX+(string)prevPage, DIALOG_BACK_BTN, NEXT_PG_DIALOG_PREFIX+(string)nextPage, DIALOG_DONE_BTN]+buttons; //omit DIALOG_BACK_BTN in line above if not offering } // ****** Invoke a new listener and a new timer listen_id = llListen( channel_dialog, "", ID, ""); llSetTimerEvent(30); llDialog(ID, "Page "+(string)gPageNum+"\nChoose one:", buttons, channel_dialog); }
CancelListen() { llListenRemove(listen_id); llSetTimerEvent(0); }
default { state_entry() { kQuery = llGetNotecardLine(iNoteCardName, iLine);
channel_dialog = ( -1 * (integer)("0x"+llGetSubString((string)llGetKey(),-5,-1)) ); }
touch_start(integer total_number) { CancelListen(); // ******* it is good practice to remove a listener before using it - it might still be there from the last touch ToucherID = llDetectedKey(0); listen_id = llListen( channel_dialog, "", ToucherID, ""); gPageNum = 1; giveDialog(ToucherID, gPageNum); // ****** Always set a TimerEvent, in case the user hits the «ignore»-button llSetTimerEvent(60.0); }
dataserver (key query_id, string data) { if(query_id == kQuery) { if (data != EOF) { // ****** just in case you have empty lines in your notecard (most likely the last one) // ****** check for empty lines in the returned data if ( llGetSubString(data, 0, 1) != "//" && llStringTrim(data, STRING_TRIM) != "") { Anything += [data]; }
iSkip++; // ***** What's this for? iLine++; kQuery = llGetNotecardLine(iNoteCardName, iLine); } } }
listen(integer channel, string name, key id, string choice) { // ******* ALWAYS Remove the listener and the timer - will be invoked again if the user continues to use the menu CancelListen(); // ******* NOTE: Using the global ToucherID in the listen-event bears some risk // ******* if - in the meantime - another user clicked on the object, the ToucherID // ******* will be replaced with the new toucher-id, thus the new user doesn't start // ******* from the beginning but continues to use the menu where the last toucher // ******* left it... // ******* so I recommend using the id that's been returned by the listen-event' //here, you need to only: //1. implement something that happens when the back button is pressed, or omit back button //2. Go to the else event. That is where any actual choice is. Process that choice. if (choice == "-") { giveDialog(id, gPageNum); }
else if ( choice == DIALOG_DONE_BTN) { //CancelListen(); //return; // ********* return to where? you're not inside a function! }
else if (choice == DIALOG_BACK_BTN) { CancelListen(); //go back to where you want }
else if (llSubStringIndex(choice, PREV_PG_DIALOG_PREFIX) == 0) { gPageNum = (integer)llGetSubString(choice, llStringLength(PREV_PG_DIALOG_PREFIX), -1); giveDialog(id, gPageNum); }
else if (llSubStringIndex(choice, NEXT_PG_DIALOG_PREFIX) == 0) { gPageNum = (integer)llGetSubString(choice, llStringLength(NEXT_PG_DIALOG_PREFIX), -1); giveDialog(id, gPageNum); }
else { llSay(0, "You chose " + choice); } } timer(){ // No answer given or user hit «ignore» CancelListen(); } }
There's something important in LSL: When you write something like «myVar-1» the -1 doesn't get deducted from myVar but will be treated as a negative number... So this will produce false outputs. ALWAYS put a space between the minus sign and the 1 if you want to deduct it!!! Note the lines marked with // ****** in the code, that's where I made changes... One important part is in your dataserver-event. You do check for comments (llGetSubString(data, 0, 1) != "//"  but you don't check for empty lines. It happens a lot, that one accidently adds an empty line at the end of the notecard by hitting «enter» again after doing the last entry (we're used to finish entries in whatever form with an «enter»). This ends up being an empty line in the notecard. Your script adds this empty line to the «Anything»-list and thus, there'll be one button with an empty label. Note: Don't use «Anything» as a variable name. Use meaningful variable names as it helps keeping track of what's happening in the code...  And - on a slightly off-topic sidenote: what about using some punctuation in your postings? I'm honestly having a hard time reading 10 Lines with no comma or full stop in it. I had to read it almost three times until I really understood the meaning...
|
|
Jodie Suisei
Lost In LSL Code
Join date: 6 Oct 2006
Posts: 66
|
09-15-2008 13:54
My apologies about the punctuation im dyslexic with words and its usually a hard time even for myself to type and checking stuff though for errors typing isnt my strong point. As for back onto topic thank you for going through the script it was just something i peiced together from the wiki to try out the dialog buttons with the actual names from the card on. I do have a few example scripts with the dialog choices in numbers but no real wiki or other open source dialogs based on what im trying to do, Additionally when the button is pressed the message sent from that specific button i wanted to use for a link message. For example Button says lets say Candy User clicks button the message picked up in the listen is just candy and i can then send that message through the linked message function and a reciever says ooooh candy message and changes a texture or whatever else its set. I have basic knowledge of link messages and basic dialogs from hard scripted in lists so what im trying to do it learn how to get buttons based on note card lines. the wiki multipage is ok for reference but in itself i have found to be clumsy and i did notice myself alot of code left in it even on the wiki that just didnt do anything  . What i will do now is pick through the script and get rid of all the stuff i personally wouldnt use and change a few things and see what the end result is but on the whole i just dont like the idea of the page number listed on the buttons. Is there anyway i can trim that off same with the page number being list the top? Edit Ok played witht he scritp quite a bit i think can i probably write out something i can read and recognised based on this and incorporate what i have learnt into it as it stand this wiki version is just basically annoying me lol.
|
|
Jodie Suisei
Lost In LSL Code
Join date: 6 Oct 2006
Posts: 66
|
09-16-2008 02:58
From: Haruki Watanabe Let's say, you have a list like:
list colors = ["Red", <1.0, 0.0, 0.0>, "Blue", <0.0, 1.0, 0.0>, "Green", <0.0, 0.0, 1.0>];
So what you want now is having the text-values in the buttons of your dialog and once the user picks a color having the according color-vector chosen. I wasnt very clear with what i was asking so i will try to be more specific my own fault on that part. // comments with **** at the end is where im trying to peice in the parts to make the dialog button and the vector work when your click the button from the notecard data. Notecard is laid out like this i called it _Colour for the sake of thats what it is for  Black, <0,0,0> // Colour Name Then A Comma Then The Associated vector White, <1,1,1> Yellow, <1,1,0> Green, <0,1,0> Cyan, <0,1,1> Blue, <0,0,1> Magenta, <1,0,1> Red, <1,0,0> Purple, <0.5,0,0.5> Orange, <1.0.5,0> Pink, <1,0.5,0.5>
This is my corrected dataserver using the tips you provided about trimming off dead lines
default { state_entry() { kQuery = llGetNotecardLine(iNoteCardName, iLine); // Notecard iNoteCardNamed Is _Colours in Global and Our line Counter } dataserver (key query_id, string data) { if (query_id == kQuery) { if (data != EOF) { if ( llGetSubString(data, 0, 1) != "//" && llStringTrim(data, STRING_TRIM) != "") { // This Is Where I Would Like To Seperate The Name And The Vectors From The Read Card. **** See Below For What I Did Try } iLine++; kQuery = llGetNotecardLine(iNoteCardName, iLine); } else // else event is here as once i got the script doing what i wanted, to then add a few bits in for example OwnerSay messaging and anything else that needs to be proccessed in the data server event. to inform what the dataserver event is upto. {
} } }
// Snipped lines
I have tried llGetSubString to seperate the name and then the vector by the first comma in the card, The result of this was only the black button turned the prim black with a llSetColour and the vector data. But that didnt really work when i was dealing with the testing around with the llSay message after the button is pressed. I can only guess i need to somehow increase that count as per your post i tried to tell the listen to get the position of the button and increment but i might of failed somehow. Below is the Listen event handling the messages from the button // Snipped Lines else { integer Pos = llListFindList(ColourName, [message]); // ColourName Is What I Called The Colour Name That I Needed To Be Seperated From The Vector gVector = llList2Vector(Vector, Pos +1); llSetColor(gVector, ALL_SIDES); // gVector is what i called the Vector so i could use the llList2Vector Function both of these are declared global in the script so i could use them for the needed data DialogLoadColour(); // Part of the reworked Wiki Dialog for putting names onto buttons but for this since the problem isnt with the dialog its not related :) } //Snipped Lines
I Also tried some other functions out with totally different results llParseString2List for example , llCSV2List and a few others but i have a feeling the answer lays with llSubString for this particular thing im trying to do. After stripping out the wiki dialog and adding some of my own tweaks to it, i now have a working dialog where the notecard information can be printed onto the buttons allowing for changes, and possibly an end user to add there own Colours and Vectors. And the dialog buttons will just change based on the notecard lines  Pretty much what im doing is taking Very Keynes advice and working on smaller modules at a time for a larger project this is basically the smaller steps for the larger picture. Next i wanted to say throw in for example
Black, <0,0,0>, I Am Black // Colour Name Then The Associated vector then a message to say when the button is clicked based on the notecard lines White, <1,1,1>, I Am White Yellow, <1,1,0>, I Am Yellow Green, <0,1,0>, I Am Green Cyan, <0,1,1>, I Am Cyan Blue, <0,0,1>, I Am Blue Magenta, <1,0,1>, I Am Magenta Red, <1,0,0>, I Am Red Purple, <0.5,0,0.5>, I Am Purple Orange, <1.0.5,0>, I Am Orange Pink, <1,0.5,0.5>, I Am Pink
So when black was clicked it would change the prims colour and then say the line from the notecard afterwards all of these seperated with comma's . It doesnt have to be only commas but after reviewing CSV2List for debugging it made more sense as per Pale's advice for debugging  How would i set my Dataserver up for this information storing and also how would i set the listen event up to handle the multiple information for example on the second notecard example. The aim really is what im trying to do here is take the lines from the notecard put the first bit as the button text, then the vector which would be tied to the button in order, then if possible have the last line be a message the prim will say. When the associated buttons were clicked. Any help or advice would be great im getting there with trying things on my own and playing with the functions but im not quite hitting the right function for this module
|
|
Haruki Watanabe
llSLCrash(void);
Join date: 28 Mar 2007
Posts: 434
|
09-16-2008 05:49
Ok, I guess your problem is here: gVector = llList2Vector(Vector, Pos +1); Because the vector is stored as a string in the list (and not as a vector, since it was read from the notecard and not put directly into the list), you have to typecast the string into a vector -> gVector = (vector)llList2String(Vector, Pos + 1) I made a small script that reads your notecard, makes a dialog out of it and passes the selection from the dialog to another script, using a linked message... Hope this will clarify some stuff for ya 
// This is the main-script, reading the notecard and handling the dialog
key ncRequest; // key for notecard-request integer ncLine; // Notecard line
string ncName = "colors"; // name of the notecard
list colors; // List with the colors/vectors/strings to say
integer dlgChannel = -12345; // Channel on which the dialog talks to the script integer listener; // The id for the listener key actToucher; // Key of the Agent who clicked on the prim
default { state_entry() { // When rezed, read the notecard llOwnerSay("Reading Notecard"); ncLine = 0; ncRequest = llGetNotecardLine(ncName, ncLine); }
touch_start(integer total_number) { actToucher = llDetectedKey(0); // when touched, present the menu to the toucher llListenRemove(listener); listener = llListen(dlgChannel, "", actToucher, ""); llDialog(actToucher, "Please choose a color", llList2ListStrided(colors, 0, -1, 3), dlgChannel); llSetTimerEvent(30); } listen(integer channel, string name, key id, string msg){ if(channel == dlgChannel && id == actToucher){ llListenRemove(listener); llSetTimerEvent(0); // User selected the color integer pos = llListFindList(colors, [msg]); // Get the position of the selected color in the colors-list // Watch out - converting a vector that has been stored in a list, does only work, if it has been stored // as a vector. But since you're reading the vector form a notecard, it's actually stored as a string. // So you have to use (vector)llList2String(listname, pos) to typecast it into a string!!! vector selectedColor = (vector)llList2String(colors, pos + 1); // The vector is at pos + 1 string selectedText = llList2String(colors, pos + 2); // Debug this info llOwnerSay(msg + " Vec: " + (string)selectedColor + " Text: " + selectedText); // Now you can Link-Message the color to another prim // You have to put the color-vector and the text into one string with // a separation-sign (I usually use the Pipe |) and then split it up // again in the receiving script. llMessageLinked(LINK_SET, 99, (string)selectedColor + "|" + selectedText, actToucher); } } dataserver(key queryId, string data){ if(queryId == ncRequest){ if(data != EOF){ if(llGetSubString(data, 0, 1) != "//" && llStringTrim(data, STRING_TRIM) != ""){ colors += llCSV2List(data); } ncLine++; ncRequest = llGetNotecardLine(ncName, ncLine); }else{ llOwnerSay("Finished reading notecard"); } } } timer(){ // Listener for dialog timed out - remove it llSetTimerEvent(0); llListenRemove(listener); } }
// Slave script
// This is the script that will receive linked messages and then change the color accordingly
// Script to receive link-messages, change the color and say the text
default { link_message(integer sender, integer num, string str, key id){
if(num == 99){ // split the passed string into vector and message list tmp = llParseString2List(str, ["|"], []); // Again, the vector is received as a string, so you have // to typecast it using (vector)llList2String... vector Color = (vector)llList2String(tmp, 0); // Vector is at position 0 string Text = llList2String(tmp, 1); // Now change the color and say the text llSetColor(Color, ALL_SIDES); llSay(0, Text); } } }
Hope this helps a little - I tried to comment everything as good as I could 
|
|
Jodie Suisei
Lost In LSL Code
Join date: 6 Oct 2006
Posts: 66
|
09-16-2008 06:20
Thank you that has cleared up my questions and a bigger idea of how to split data up that is read from the notecard into several different things  . Edit. I done a bit of tweaking with the example layout and managed to make use of llSubstring to seperate the name for the button and vector that is rooted out of the notecard. Had to change the Pos +1 to Pos +0 in order for it to align the buttons to the colours but its working the only unrelated bug i have found is orange when written and displayed comes out black, Mind you it was something i found on the forum will play around with some vectors now and find some more possible colours to add to my notecard  . Also another question can you use llGetSubstring to dig out more then one bit of data for example.
//lots of snipped lines
integer Spacer = llSubStringIndex(data, ","); if (Spacer > 0) { ColourName += [llStringTrim(llGetSubString(data, 0, Spacer -1), STRING_TRIM)]; Vector += [llStringTrim(llGetSubString(data, Spacer +1, -1), STRING_TRIM)]; }
Is it possible to keep using the comma but increase the llGetSubstring(data); to hook more information. guess what i mean is this
integer Spacer = llSubStringIndex(data, ","); if (Spacer > 0) { ColourName += [llStringTrim(llGetSubString(data, 0, Spacer -1), STRING_TRIM)]; Vector += [llStringTrim(llGetSubString(data, Spacer +1, -1), STRING_TRIM)];
NextDataChunk += [llStringTrim(llGetSubString(data, Spacer +2, -1), STRING_TRIM)];
// Where NextDataChunk is the added for grabbing that additional information stored in the notecard so i could pretty much as long as there is a comma it would store that data into a list also? }
Also since im telling the Spacer to start at 0 and the data i want to grab is at +1 possible to add more subString grabs into the data server event for example, if (spacer >2) { NewInfoName += [llStringTrim(llGetSubStrind(data, Spacer 2 -1), STRING_TRIM)]; }
Etc
Only testing what is possible as the vector system now works so i can go ahead and use your Link message example to push the data to link messages for the larger project with the vector colour change. The product im working is a huge step and im liking this one bit at a time but i dont want to push the limits of grabbing data with the data server and cause it to mess up lol Would rather ask then to try it for myself and messup the script badly its slowly taking shape but im still not massivly happy with the Wiki example on the dialog control but for now its working nicely just dont like the pagenumbers having to be on the buttons in order for it to scroll through the pages properly. Edit think i have found a work around will play with it a little and see what the results are  then again maybe not lol
|
|
Jodie Suisei
Lost In LSL Code
Join date: 6 Oct 2006
Posts: 66
|
09-20-2008 01:34
Im now facing a new problem i have made an example script to help highlight where im getting brick walled with being stuck on a way to get the data i want sifted out.
// The notecard data is as below since im using a notecard name "Test Card". //
// This Is A Test Card // Filled With Different Labels Crickets , Aliens , Cards , Buttons , Giraffe , Sausages Burgers , Life , Savage , Poker , Beans , Bacon
This is the script thats digging the data out i tried to comment it as best i could.
key kQuery; // Dataserver Key.
integer iLine; // Line Counter.
string aNoteCardName = "Test Card"; // Notecard Name Being Read From Prim Inventory.
list TestCardData; // The Data Pushed To A List.
integer CHANNEL = -49999999; // Channel For Using Our Dialog.
default { state_entry() { kQuery = llGetNotecardLine(aNoteCardName, iLine); // Get The First Notecard Line } touch_start ( integer total_number ) { llDialog(llGetOwner(), "Test Card Data", llList2ListStrided(TestCardData, 0, - 1, 6), CHANNEL); // The Basic Dialog Using The TestCardData And Making Use Of List2ListStrided Return Every 6th Item. } dataserver ( key query_id , string data ) { if ( query_id == kQuery ) { if ( data != EOF) { if (llGetSubString(data, 0 , 1) != "//" && llStringTrim(data, STRING_TRIM) != "") { TestCardData += llCSV2List(data); // Push The Data To The List Since Were Using Comma's So llCSV2List Is What Im Using. } } iLine++; // Increase The Line Count kQuery = llGetNotecardLine(aNoteCardName, iLine); // Grab The Next Notecard Line } else { // For Any Post Dataserver Processing But Since This Is A Problem Solve Is Here Incase Any Use Later On. } } listen ( integer channel, string name , key id , string message ) { // Listen Here For When The Multi - Page Dialog Solved Using llList2ListStrided. } }
// Now what i am trying to do is create a multi - page dialog that will scroll using llList2ListStrided but there doesnt seem to be any examples of this kind of thing. // // I could use llGetSubString And llSubStringIndex but seperating the data to individual parts after it // has picked it out to send through a linked message isnt working out to great. // // What Im trying to do is the following. // // Create a list seperated by comma's which i have done. // // Take that data and seperate out the first elements of the list for my buttons using llList2ListStrided. // // Now if the data collected is over 12 items it script errors because only 12 buttons per page //
Now what i was attempting is to use llList2ListStrided to grab only certain parts of the data for my buttons. The problem lays with more than 12 items in that list are grabbed and the dialog goes ooops script error for you because of that reason. I have tried several ways to make a multipage dialog based on llList2ListStrided. I have a semi working example that i made based on splitting the data up before hand using llGetSubString but using that im faced with issues of having to split the data up after the seperating element. If any one can help me piece this one together im just having trouble with multi - paging items in this way i cant find any examples so i thought it would be best to write a basic script and highlight the issues. My ultimate aim with this one is to have a notecard that would in the end be user scalable so they could add there own data to the card and only the data in the first row of the card would be the button names. As i said before i can get data seperated in seperate ways and i can use integer pos = to tell the buttons to where the data is and send that through a linked message without a problem its the mulipaging data in this way thats poking me. Any help or example of multi - paging data in this way would be appreciated i have tried forum searchs , in world example scripts , google , and even the wiki's but im hitting a blank every time.
|
|
Pale Spectre
Registered User
Join date: 2 Sep 2005
Posts: 586
|
09-20-2008 03:40
Hello Jodie.  I have to confess that I sometimes struggle a bit to really understand what your question is - so apologies if I'm about to solve a different problem! For example, there are no strided lists in this solution. I've simply attempted to produce a general solution for presenting a multi page dialog. I've intentionally left out any notecard reading-cum-dataserver stuff and have just hard-coded a long list because it's a lot easier to see what's what. However, you should be able to apply this solution (memory constraints aside) to any list however it is formed. Notice that the pageLen integer and pageControls list give you a lot of flexibility in terms of the combination of 'common' and 'variable' buttons you want to display. This example assumes we have 'Prev' and 'Next' on every dialog leaving 10 free positions for the variable buttons. list srcList = ["01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36"];
integer mnuChannel; integer mnuHandle;
integer page; integer pageLen = 10; list pageControls = ["Prev", "Next"];
list orderList(list tempList) { return llList2List(tempList, -3, -1) + llList2List(tempList, -6, -4) + llList2List(tempList, -9, -7) + llList2List(tempList, -12, -10); }
dialogShow() { list mnuOptions = orderList(llList2List(srcList, page * pageLen, (page * pageLen) + pageLen - 1) + pageControls); string mnuTitle = "\nPage " + (string)(page + 1) + " of " + (string)((integer)(llGetListLength(srcList) / pageLen) + 1); llListenRemove(mnuHandle); mnuChannel = ((integer)llFrand(900000) + 100000) * -1; mnuHandle = llListen(mnuChannel, "", llGetOwner(), ""); llDialog(llGetOwner(), mnuTitle, mnuOptions, mnuChannel); }
pageCheck() { if (page * pageLen > llGetListLength(srcList)) page = 0; else if (page < 0) page = (integer)(llGetListLength(srcList) / pageLen); }
default { touch_start(integer total_number) { if(llDetectedKey(0) == llGetOwner()) { page = 0; dialogShow(); } }
listen(integer channel, string name, key id, string message) { llListenRemove(mnuHandle);
if (message == "Next") { page += 1; pageCheck(); } else if (message == "Prev") { page -= 1; pageCheck(); } else { // handle your specific options here; }
dialogShow(); } }
Sorry, there isn't much by way of comments - they cost extra. 
|
|
Haruki Watanabe
llSLCrash(void);
Join date: 28 Mar 2007
Posts: 434
|
09-20-2008 03:40
Hi Jodie, Below is a script I made that generates a multi-page from a list that's being sent to it via linked-message. It's commented pretty well (I hope) and you should be able to see what's going on... Usage of the script is as follows: From the calling script you issue a command to the dialog-script:
// Code snippets
list myMenu = ["red", "blue", "green", "orange"]; // Note - these are just the labels for the buttons - if you have a strided list, you need // to extract the button-labels from that list integer gThisScript = 9999; // This number is used to track the script that's calling the dialog-script
key gToucher; // Used to keep track of the touching-agent
default{ touch_start(integer num){ gToucher = llDetectedKey(0); // Store the agent's key who touched the object // Call the dialog script, with the entries of the myMenu-List // Dialog-Title is "Please make a selection" // Dialog will show the total number of entries in the myMenu-List - this will look something like «showing entries 1-10/40 // Dialog will present a back-button at the first page of the dialog // See the description of the options in the dialog-script llMessageLinked(LINK_THIS, gThisScript, "SHOW_DIALOG|" + llList2CSV(myMenu) + "|Please make a selection|TRUE|TRUE", gToucher); } // Receive the message from the dialog-script link_message(integer sender, integer num, string str, key id){ if(num == gThisScript){ // The link_message is aimed at this script // separate the contents of str - Format: SND_DIALOG|user's-choice list tmp = llParseString2List(str, ["|"], []); string result; // variable to store the user's-choice // if the link-message comes from the dialog-script, we'll have «SND_DIALOG» in the 0th entry of the tmp-list // id reflects the key of the toucher. The dialog-script sends this back to the calling-script if(llList2String(tmp, 0) == "SND_DIALOG"){ result = llList2String(tmp, 1); llOwnerSay(llKey2Name(id) + " selected '" + result + "'"); } } } }
And here comes the dialog-script:
// Dialog-Maker // By Haruki Watanabe
// This script is public domain - use it, share it, to whatever you wanna do... :) // If you've got any improvements, please post them in the forum
// ******************************************************* // Constants // *******************************************************
integer REQUESTING_SCRIPT; // Number of the requesting script integer REQUESTING_LINK; // Link-Number where the request comes from
integer DLG_CHANNEL; // Channel on which the result of the dialog will be passed back integer LISTENER_DLG; // The Listener-ID integer LIST_OFFSET; // Offset of the List
integer TOTAL_ENTRIES; // Total Entries in the whole list to be presented
integer SHOW_ENTRIES; // BOOLEAN Whether or not to show the number of entries in the dialog-title (e.g. 'showing 1-9/25') integer BACKLINK; // BOOLEAN Whether or not give the user the option to go back (useful if you're in a Sub-Menu)
string DLG_TITLE; // Title of the dialog string CMD; // The Command that's passed to this function-script
key AGENT_REQUEST; // Key of the requesting Agent
list DLG_CONTENT; // The contents that the user can choose from list DLG_CONTENT_LONG; // Helper-List - if the button labels are too long, we have to strip them down to 23 characters list MENU; // The actual list that's being passed to llDialog
float MAX_LISTEN_TIME = 240.0; // Maximum seconds the Listener keeps listening for an answer
// ******************************************************* // Functions // *******************************************************
show_dlg(list PASS_MENU) // Presents the Dialog-Menu to the requesting user { llListenRemove(LISTENER_DLG); // Delete any old listener MENU = []; if(llGetListLength(PASS_MENU) == 0 || TOTAL_ENTRIES == 0) // If there are no entries in the list, send an error-Message to the User { llInstantMessage(AGENT_REQUEST, "There are no entries in the list..."); } else { string TITLE = DLG_TITLE; integer start; // number where the list starts integer end; // number where the list ends -> these two shouldn't be confused with the list offset! start = LIST_OFFSET + 1; end = start + 9; if(end > TOTAL_ENTRIES) end = TOTAL_ENTRIES; if(SHOW_ENTRIES == TRUE) { TITLE = TITLE + "\n showing entries " + (string)start + " - " + (string)end + " of " + (string)TOTAL_ENTRIES; } DLG_CONTENT_LONG = llList2List(PASS_MENU, LIST_OFFSET, LIST_OFFSET + 9); // Get the portion of the list that fits into a dialog // Prevent the Buttons from being too long integer ml = llGetListLength(DLG_CONTENT_LONG); integer i; for(i = 0;i<ml;i++){ MENU += [llGetSubString(llList2String(DLG_CONTENT_LONG, i), 0, 23)]; } // Give the user a 'back'-option if(BACKLINK == TRUE || LIST_OFFSET > 0) MENU += ["Back..."]; // if the list is too big to fit into one Menu, give the user a 'next'-option if(end < TOTAL_ENTRIES) MENU += ["Next..."]; // Show the dialog and initialize a listener LISTENER_DLG = llListen(DLG_CHANNEL, "", AGENT_REQUEST, ""); llDialog(AGENT_REQUEST, TITLE, MENU, DLG_CHANNEL); llSetTimerEvent(MAX_LISTEN_TIME); // Initialize a timer, in case the user clicks on 'ignore' } }
// Create an arbitrary dialog channel
integer randInt(integer n) { return (integer)llFrand(n + 1); }
integer randIntBetween(integer min, integer max) { return min + randInt(max - min); }
integer make_dlg_channel() { return randIntBetween(-65356, 0); }
// ******************************************************* // Main-Section // *******************************************************
default { link_message(integer sender, integer num, string str, key id) { AGENT_REQUEST = id; REQUESTING_LINK = sender; REQUESTING_SCRIPT = num; // split up the passed string into a list // Format of the string: // COMMAND|CONTENT|DIALOG-TITLE|SHOW_ENTRIES|BACKLINK list temp = llParseString2List(str, ["|"], []); CMD = llList2String(temp, 0); if(CMD == "SHOW_DIALOG") { DLG_CONTENT = llCSV2List(llList2String(temp, 1)); // Comma-separated list of all the entries for the dialog DLG_TITLE = llList2String(temp, 2); // The Title of the dialog (e.g. Color-Menu) SHOW_ENTRIES = llList2Integer(temp, 3); // if set to TRUE, the dialog will show the number of total entries in the dialog BACKLINK = llList2Integer(temp, 4); // if set to TRUE, the dialog will always present a «Back» button // When the user is on the first page of the dialog and hits the «Back»-Button, // The script will return «back» to the calling script // This is useful if you have sub-menus and want the user to be able // to go back to the last menu LIST_OFFSET = 0; // Set the List offset to the beginning of the list TOTAL_ENTRIES = llGetListLength(DLG_CONTENT); // Determine the total length of the list DLG_CHANNEL = make_dlg_channel(); // Create an arbitrary channel to listen for the dialog show_dlg(DLG_CONTENT); // Show the dialog to the user } } listen(integer channel, string name, key id, string message) { if(channel == DLG_CHANNEL && id == AGENT_REQUEST) // The User clicked on an option { if(message == "Back...") // The selected option was 'back' { if(LIST_OFFSET > 0) { // if we're not at the beginning of the options-list, // set the Offset back and call the dialog again LIST_OFFSET -= 10; show_dlg(DLG_CONTENT); } else { // We're at the beginning of the options list - send the back-msg back to the calling script llMessageLinked(REQUESTING_LINK, REQUESTING_SCRIPT, "SND_DIALOG|back", AGENT_REQUEST); } } else if(message == "Next...") { // The User wants to see the next portion of the options-list // increment the list-offset and show the dialog again LIST_OFFSET += 10; show_dlg(DLG_CONTENT); } else { // The user has made her/his choice - send the answer back to the calling script // Find the selected button id in the MENU-List integer i = llListFindList(MENU, [message]); string sendback = llList2String(DLG_CONTENT_LONG, i); llMessageLinked(REQUESTING_LINK, REQUESTING_SCRIPT, "SND_DIALOG|" + sendback, AGENT_REQUEST); } } } timer() { llListenRemove(LISTENER_DLG); } on_rez(integer bla) { llResetScript(); } }
The script takes care of the pagination and uses some helper-lists to prevent running into a script error when the button labels are too long (i.e. more than 23 characters). HTH... 
|
|
Jodie Suisei
Lost In LSL Code
Join date: 6 Oct 2006
Posts: 66
|
Thank You 
09-20-2008 04:57
Thank you for the posts Pale and Haruki Pale no problem about the comments  Haruki i understand your script example better it seems more in line with what im doing and from your previous posts on helping me most of it all falls into place  I will play around with adding my dataserver event into it and adding my data to the CSV2List. What i am still confused on now is , where would i put the llList2ListStrided(Name, 0, -1, 6) would it go into the touch event? into the state_entry? if you could clear that up if at all possible would be great  . Or would it be something like this list myMenu = llList2ListStrided(Dataname, 0, -1, 6);? Edit Pale Your example is pretty much spot on to what is attempting so was Haruki's so i will play with both and see what i can do with them 
|
|
Haruki Watanabe
llSLCrash(void);
Join date: 28 Mar 2007
Posts: 434
|
09-20-2008 07:45
Hi Jodie, As for what you have to pass in the link-message to my dialog-script: let's say you have a notecard containing this: Red, <1.0, 0.0, 0.0>, You chose red Blue, <0.0, 1.0, 0.0>, You chose blue Green, <0.0, 0.0, 1.0>, You chose green ... and so forth After you read this notecard, your color-list would look like: list colors = ["Red", <1.0, 0.0, 0.0>, "You chose red","Blue", <0.0, 1.0, 0.0>, "You chose blue","Green", <0.0, 0.0, 1.0>, "You chose green"]; Now you want every 3rd entry on the buttons of your dialog, means «Red, Blue, Green» (one button for each color). So you split up the colors-list using llList2ListStrided. I'd put this right in front of the call to my dialog-script in the touch-event. This way, you don't have to worry about the list-split up when you added more entries to the notecard. list dialogMenu = llList2ListStrided(colors, 0, -1, 3); Now, pass this to my dialog-script: llMessageLinked(LINK_THIS, gThisScript, "SHOW_DIALOG|" + llList2CSV(dialogMenu) + "|Dialog-Title|TRUE|TRUE", llDetectedKey(0)); The dialog-script then passes the chosen button back to your calling-script and you use this information to determine, which stride of the list you should use: (I assume that you store the chosen value in a variable called «result») integer pos = llListFindList(colors, [result]); now the vector of the chosen item is on pos + 1 and the text is on pos + 2 vector colorVec = llList2String(colors, pos + 1); string text = llList2String(colors, pos + 2); HTH  P.S. there's a nice example on how to use strided-lists here: http://www.lslwiki.net/lslwiki/wakka.php?wakka=llList2ListStrided
|
|
Jodie Suisei
Lost In LSL Code
Join date: 6 Oct 2006
Posts: 66
|
Thank You again 
09-20-2008 07:56
Thank you again i had a feeling it was the touch event or before the dialog call itself, im now up and working again and i should have this module for my larger project finished soon 
|