User:Daemonika Nightfire/Scripts/Dynamic Menu

From Second Life Wiki
Jump to navigation Jump to search

Dynamisches Menue

Ein dynamisches Menue ist ein Menue, das sich anhand der verfuegbaren Daten aus einer Liste selbst generiert. In diesem Basis-Beispiel haben wir ein Menue mit einer vordefinierten Liste, in der lediglich schriftlich auf Englisch von 1 bis 10 gezaehlt wird. Wenn wir nun im Menue einen stellvertretenden Button druecken, wird das entsprechende Wort im Chat ausgegeben.

// Liste mit Eintraegen
integer qty = 0;
list entrys = ["One","Two","Three","Four","Five","Six","Seven","Eight","Nine","Ten"];

// Generiert ein menue aus der Liste
list menubutton = [];
list navigation = [];
string menudesc = "";
integer index_start = 0;
integer index_end = 5;
integer selection = 6;
BuildMenu()
{
    menubutton = [];
    navigation = [];
    menudesc = "";
    
    // Startpunkt befindet sich unter 0.
    if(index_start < 0)
    {
        // Der Startpunkt ist das Maximum abzueglich des unteilbaren Rests von Maximum/selection.
        index_start = qty - (qty%selection);
        if(index_start == qty)
        {
            index_start = qty - selection;
        }
    }
    
    // The Startpunkt liegt ueber dem Maximum
    if(index_start > qty-1)
    {
        // Damit fangen wir dann einfach wieder bei 0 an.
        index_start = 0;
    }
    
    // Das anzuzeigende Ende wird vom endgueltigen Startpunkt aus bestimmt.
    index_end = index_start + selection-1;
    if(index_end >= qty)
    {
        index_end = qty-1;
    }
    
    navigation = ["<<<", "Close", ">>>"];
    if(qty <= selection)
    {
        index_end = qty-1;
        navigation = [] + ["...", "Close", "..."];
    }
    
    menudesc = "\nChoose your options.\n\n";
    integer i = index_start;
    do
    {
        string number = (string)(i+1);
        menudesc += number + ") " + llGetSubString(llList2String(entrys, i), 0, 39) + "\n";
        menubutton += number;
    }
    while(++i <= index_end);
}

// Generiert einen zufaelligen Menue-Channel
integer menu_handler;
integer menu_channel;
OpenMenu(key user, string title, list buttons)
{
    llListenRemove(menu_handler);
    menu_channel = (integer)(llFrand(1) * -DEBUG_CHANNEL);
    menu_handler = llListen(menu_channel, "", "", "");
    llDialog(user, title, buttons, menu_channel);
    llSetTimerEvent(60.0);
}

default
{
    state_entry()
    {
        qty = llGetListLength(entrys);
        llSay(0, "\n" + (string)qty + " entrys loaded.\n" + (string)llGetUsedMemory() + " bytes memory in use.");
    }

    touch_start(integer total_number)
    {
        key agent = llDetectedKey(0);
        index_start = 0;
        index_end = selection-1;
        BuildMenu();
        OpenMenu(agent, menudesc, navigation + menubutton);
    }
    
    listen(integer chan, string name, key id, string msg)
    {
        list parsed = llParseString2List(msg, [" "], []);
        string cmd = llList2String(parsed, 0);
        //string data = llList2String(parsed, 1); // Falls wir zweiteilige Commandos nutzen
        
        if(chan == menu_channel)
        {            
            if(cmd == "Close" || cmd == "...")
            {
                llListenRemove(menu_handler);
                llSetTimerEvent(0.0);
            }
            else if(cmd == ">>>")
            {
                index_start += selection;
                
                BuildMenu();
                OpenMenu(id, menudesc, navigation + menubutton);
            }
            else if(cmd == "<<<")
            {
                index_start -= selection;
                
                BuildMenu();
                OpenMenu(id, menudesc, navigation + menubutton);
            }
            else if(~llListFindList(menubutton, [cmd]))
            {
                string choice = llList2String(entrys, (integer)cmd-1);
                llOwnerSay("entry: " + choice);
                
                BuildMenu();
                OpenMenu(id, menudesc, navigation + menubutton);
            }
        }
    }
    
    timer()
    {
        llListenRemove(menu_handler);
        llSetTimerEvent(0.0);
    }
    
    changed(integer ch)
    {
        if(ch & CHANGED_INVENTORY)
        {
            llResetScript();
        }
    }
    
    on_rez(integer Dae)
    {
        llResetScript();
    }
}

Automatisch generiertes Menue

Ich werde hier nicht für alle moeglichen Varianten das gesamte Menue wiederholen. Stattdessen beschreibe ich, wie die Liste gefuellt werden kann. beachte dabei, in welchen Events sich die entsprechenden Befehle befinden.

Inhalt

In diesem Beispiel siehst du, wie der Inhalt eines Objekts ausgelesen, durchgezaehlt und die Namen in der Liste gespeichert werden. Denke daran, wenn du Animationen auflisten und per Knopfdruck abspielen moechtest, das du zusaetzlich noch entsprechende Berechtigungen schaffen musst. (siehe LlRequestPermissions).

integer qty = 0;
list entrys = [];

default
{
    state_entry()
    {
        qty = llGetInventoryNumber(INVENTORY_OBJECT);
        if(qty > 0)
        {
            integer i = 0;
            do
            {
                string qty_name = llGetInventoryName(INVENTORY_OBJECT, i);
                entrys += qty_name;
                
                if(llGetFreeMemory() < 10000)
                {
                    llOwnerSay("/me Memory Control: Unable to add more entrys.");
                    i = qty;
                }
            }
            while(++i < qty);
            
            qty = llGetListLength(entrys);
        }
        llSay(0, "\n" + (string)qty + " entrys loaded.\n" + (string)llGetUsedMemory() + " bytes memory in use.");
    }
}

Notecard

Dieses Beispiel liest eine Notecard aus, dabei werden die einzelnen Zeilen gezaehlt und die Texte der Zeilen in der Liste gespeichert. Hierfuer ist eine Notecard erforderlich, aehnlich wie folgendes Beispiel.

New Note
text01
text02
text03
text04
text05
text06
text07
text08
text09
text10
integer qty = 0;
list entrys = [];

string nc_name = "";
key read_nc;

default
{
    state_entry()
    {
        nc_name = llGetInventoryName(INVENTORY_NOTECARD, 0);
        read_nc = llGetNumberOfNotecardLines(nc_name);
    }
    
    dataserver(key request, string data)
    {
        if(request == read_nc)
        {
            integer count = (integer)data;
            integer i;
            do
            {
                string line = llGetNotecardLineSync(nc_name, i);
                if(line == NAK)
                {
                    llSay(0, "---NAK---\nNotecard are missing or not readable.");
                }
                else if(line == EOF)
                {
                    qty = llGetListLength(entrys);
                    llSay(0,"---EOF---\n" + (string)qty + " entrys loaded.\n" + (string)llGetUsedMemory() + " bytes memory in use.");
                }
                else
                {
                    if(line != "")
                    {
                        if(llGetFreeMemory() >= 10000)
                        {
                            entrys += line;
                        }
                    }
                }
            }
            while(++i <= count);
        }
    }
}

Agentlist (Radar)

Aehnlich wie die New Age Radar, wird auch hier lediglich die Agentlist auf der Region abgefragt und in die Liste eingepflegt.

integer qty = 0;
list entrys = [];

default
{
    state_entry()
    {
        entrys = llGetAgentList(AGENT_LIST_REGION, []); // AGENT_LIST_PARCEL
        qty = llGetListLength(entrys);
        llSay(0, "\n" + (string)qty + " entrys loaded.\n" + (string)llGetUsedMemory() + " bytes memory in use.");
    }
}