These scripts are set up to make hierarchical multi paged dialog menus for object contents simple. The whole system works from notecards (NCs). We start with a main NC containing any number of NC names that are the titles of sub menus. They in turn may contain names of further sub menus ad infinitum. Any number of cards and any number of eventual sub sectioned prim contents may be added. The following setup walkthrough should explain better.
These scripts are setup for texture display by menu but could simply be edited to rez objects or give items or both. The important bit is how simple it is to organize the menus.
https://d1yjxggot69855.cloudfront.net/skins/monobook/bullet.gif); color: rgb(0, 0, 0); font-family: verdana, helvetica, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); ">
- STEP 1
Fill the prim with whatever contents you're using. For the sake of demonstration lets assume it is textures and there are hundreds of them. To make life easier drop the "Helper" script into the contents and wait for the names of the contents to be chatted to you. You can then copy paste all the names in one go to a NC for ease.
https://d1yjxggot69855.cloudfront.net/skins/monobook/bullet.gif); color: rgb(0, 0, 0); font-family: verdana, helvetica, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); ">
- STEP 2
Decide how you want to arrange the textures into groups. If you feel like wading through page after page of uncategorized texture names you can simply copy the whole list of names to one card, save it and drop it in the prim with the "Engine" script and you're done. But to make using the menus far more pointed we can set up sub menus and sub sub menus.
So what we do is add the names of the textures in groups to separate NCs. We then name those NCs according to the category we choose. Again for the sake of simplicity lets say we have predominantly red, green and blue textures but, we also have cubist and swirly of each color.
IN EVERY NOTECARD WE ADD THE NAMES OF EITHER SUB MENU NOTECARD NAMES OR TEXTURE NAMES (contents) ONE PER NOTECARD LINE.
What we would have is:
Notecard Name: Textures (or whatever you choose) containing -
Cubist
Swirly
Then also
Notecard Name: Cubist containing -
Cubist Red
Cubist Green
Cubist Blue
And
Notecard Name: Swirly containing -
Swirly Red
Swirly Green
Swirly Blue
Then NCs named: Cubist Red, Cubist Green, Cubist Blue, Swirly Red, Swirly Green & Swirly Blue each containing a list of texture names that suit the selections on the menu that would logically lead you to those.
https://d1yjxggot69855.cloudfront.net/skins/monobook/bullet.gif); color: rgb(0, 0, 0); font-family: verdana, helvetica, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); ">
- STEP 3
Save all the NCs and drop them into the prim with the engine script and the textures. Write the name of the primary NC into the script (at the top) and it's all done.
The user would see on the first page: "Cubist" & "Swirly"
Then on the next page if they chose "Cubist": "Cubist Red", "Cubist Green" & "Cubist Blue"
Or on the next page if they chose "Swirly": "Swirly Red", "Swirly Green" & "Swirly Blue"
When clicking on any of the choices that lead to a list of texture names (however many there are) the next choice they make will set the texture for display. As I said before the scripts could be simply modified to do some other thing. I may write some alternative solutions based on this engine later.
The limits of this system are effectively moot. You can have as many textures as you can save to as many NCs as you need and as many NCs as will fit in the object with the other contents. The number of sub categories can be as many as is practical.
Finally, there is a "RETURN" button on every page to go back a step. So if you don't like what you are seeing you can step back to the last page of categories and back again if you wish right to the start. Every page that needs them will have ">>" (forward) and "<<" (back) buttons for cycling through the selections of that category.
Helper
Drop this on your loaded prim/object to get a local chatted readout of every texture name in the prim/object. Makes the initial setting up slightly easier since you can just copy paste the chat to a notecard.
// V1 //
default
{
state_entry()
{
string name = llGetObjectName();
integer it = llGetInventoryNumber(INVENTORY_TEXTURE);
while(it)
{
llSetObjectName(llGetInventoryName(INVENTORY_TEXTURE, (--it)));
llOwnerSay("/me ");
llSleep(0.01);
}
llSetObjectName(name);
llRemoveInventory(llGetScriptName()); // Self deleting script.
}
}
The Engine
This is the main script for the menu system. Add it to the same prim that has the contents (textures and NCs). Add the name of the primary NC to the top of the script.
// V1 //
string main = "Categories"; // Name of primary notecard. Contains the first categories.
integer channel = -56782348; // This should be a very negative number.
integer face = -1; // The face number to display the texture on. -1 means ALL_SIDES
///////////////////////////////////////////////////////////////////////////////////////
////////////////DON'T EDIT BELOW HERE UNLESS YOU KNOW WHAT YOU'RE DOING////////////////
///////////////////////////////////////////////////////////////////////////////////////
list multi_page = ["<<", "RETURN", ">>"];
key short_data_req;
key long_data_req;
list dialog_list;
integer nc_line;
string nc_name;
list data_list;
integer busy;
key nonl_req;
list choices;
integer nonl;
integer lis;
key agent;
ClearLists()
{
dialog_list = [];
data_list = [];
}
Dialog(list l)
{
llListenRemove(lis);
lis = llListen(channel, "", agent, "");
llDialog(agent, ("\n\n" + nc_name), l, channel);
llSetTimerEvent(30.0);
}
BuildList(string s)
{
dialog_list += [llGetSubString(s, 0, 23)];
data_list += [s];
}
default
{
on_rez(integer param)
{
llResetScript();
}
timer()
{
llResetScript();
}
touch_start(integer nd)
{
while(nd)
{
key toucher = llDetectedKey(--nd);
if(!busy)
{
busy = TRUE;
agent = toucher;
nonl_req = llGetNumberOfNotecardLines((nc_name = main));
choices = [nc_name];
return;
}
//llInstantMessage(toucher, "This device is in use. Please wait"); // This will cause a slight delay if used.
}
}
dataserver(key q, string data)
{
if(q == nonl_req)
{
if((nonl = ((integer)data)) > 11)
{
long_data_req = llGetNotecardLine(nc_name, (nc_line = 0));
return;
}
else
{
short_data_req = llGetNotecardLine(nc_name, (nc_line = 0));
return;
}
}
else if(q == short_data_req)
{
if(data != EOF)
{
BuildList(llStringTrim(data, STRING_TRIM));
short_data_req = llGetNotecardLine(nc_name, (++nc_line));
return;
}
Dialog(([llList2String(multi_page, 1)] + dialog_list));
return;
}
else if(q == long_data_req)
{
if(data != EOF)
{
BuildList(llStringTrim(data, STRING_TRIM));
if(llGetListLength(data_list) ><9)
{
if((++nc_line) == nonl)
{
nc_line = 0;
}
long_data_req = llGetNotecardLine(nc_name, nc_line);
return;
}
}
Dialog((multi_page + dialog_list));
}
}
listen(integer chan, string name, key id, string msg)
{
if(id == agent)
{
llSetTimerEvent(0.0);
llListenRemove(lis);
if(llListFindList(multi_page, [msg]) == -1)
{
string data = llList2String(data_list, llListFindList(dialog_list, [msg]));
integer type = llGetInventoryType(data);
ClearLists();
if(type == INVENTORY_NOTECARD)
{
nonl_req = llGetNumberOfNotecardLines((nc_name = data));
choices += [nc_name];
return;
}
else if(type == INVENTORY_TEXTURE)
{
llSetTexture(data, face);
busy = FALSE;
return;
}
}
else if(llListFindList(multi_page, [msg]) != -1)
{
ClearLists();
if(msg == llList2String(multi_page, 1))
{
if(llGetListLength(choices) > 1)
{
nonl_req = llGetNumberOfNotecardLines((nc_name = llList2String((choices = llList2List(choices, 0, -2)), -1)));
return;
}
else
{
nonl_req = llGetNumberOfNotecardLines((nc_name = main));
choices = [nc_name];
return;
}
}
else if(msg == llList2String(multi_page, 2))
{
if((++nc_line) == nonl)
{
nc_line = 0;
}
long_data_req = llGetNotecardLine(nc_name, nc_line);
return;
}
else if(msg == llList2String(multi_page, 0))
{
if((nc_line -= 17) ><0)
{
nc_line = (nonl + nc_line);
}
long_data_req = llGetNotecardLine(nc_name, nc_line);
}
}
}
}
}