User:Fred Gandt/Scripts/Continued 6

From Second Life Wiki
Jump to: navigation, search
I get in-world very rarely these days. The knock-on effect of this, is that I am not in the best position to keep these scripts updated. Please message me in-world (forwarded to email) if you discover any bugs (that can't be simply fixed), and I'll do my best to find a solution.

My Contributions

If unsure about how to use these scripts

I have implemented a version number system to make it more obvious if a script is updated. The V# is a comment at the top of each script.

If you have any comments about the content of this page please post them HERE

All my scripts are written for compilation as MONO

More Scripts

Legal Stuff

The legal stuff about contributing to this wiki. (worth reading)

PJIRA Issue Tracker

The issues I have filed on the PJIRA

Tuition

Tuition scripts, notes, videos and screenshots etc. (hardly any content yet)

Free Scripts

Menu Engine (Textures) ( V1 )

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.

  • 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.

  • 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.

  • 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);
                }
            }
        }
    }
}

Pretty Print Prim Params ( V5 )

Gathers and processes ALL primitive parameters from an object (multi or single prim), and spits out the results to owner's local chat in a human readable format, suitable for addition to another script with little editing required (chat chaff like the object name and timestamp will need to be cut).

Objects with lots of prims (links) may generate a massive wall of text. Trying to use the instruction to set the params in another object may not work due to Stack-Heap Collisions.

Any parameters that are not required can be omitted by commenting out the unrequired params in the lists "faceless_strings" and/or "faced_strings" and the matching (by index) integer in the lists "faceless_integers" and/or "faced_integers". Although this is a little clunky, it works, and I may update it some time later.

// V5 //
 
list faceless_strings = [ "PRIM_SCRIPTED_SIT_ONLY",
                          "PRIM_ALLOW_UNSIT",
                          "PRIM_SIT_TARGET",
                          "PRIM_OMEGA",
                          "PRIM_TEXT",
                          "PRIM_POINT_LIGHT",
                          "PRIM_FLEXIBLE",
                          "PRIM_TEMP_ON_REZ",
                          "PRIM_PHANTOM",
                          "PRIM_PHYSICS_SHAPE_TYPE",
                          "PRIM_PHYSICS",
                          "PRIM_MATERIAL",
                          "PRIM_ROT_LOCAL",
                          "PRIM_ROTATION",
                          "PRIM_POS_LOCAL",
                          "PRIM_POSITION",
                          "PRIM_SLICE",
                          "PRIM_SIZE",
                          "PRIM_TYPE",
                          "PRIM_DESC",
                          "PRIM_NAME" ];
 
list faceless_integers = [ 40, 39, 41, 32, 26, 23, 21, 4, 5, 30, 3, 2, 29, 8, 33, 6, 35, 7, 9, 28, 27 ];
 
list faced_strings = [ "PRIM_ALPHA_MODE",
                       "PRIM_NORMAL",
                       "PRIM_SPECULAR",
                       "PRIM_GLOW",
                       "PRIM_FULLBRIGHT",
                       "PRIM_BUMP_SHINY",
                       "PRIM_TEXGEN",
                       "PRIM_TEXTURE",
                       "PRIM_COLOR" ];
 
list faced_integers = [ 38, 37, 36, 25, 20, 19, 22, 17, 18 ];
 
list lookup_strings = [ NULL_KEY,
                        "89556747-24cb-43ed-920b-47caed15465f",
                        "5748decc-f629-461c-9a36-a35a221fe21f",
                        "8dcd4a48-2d37-4909-9f78-f7a9eb4ef903",
                        "8b5fec65-8d8d-9dc5-cda8-8fdf2716e361" ];
 
list lookdown_strings = [ "NULL_KEY",
                          "TEXTURE_PLYWOOD",
                          "TEXTURE_BLANK",
                          "TEXTURE_TRANSPARENT",
                          "TEXTURE_MEDIA" ];
 
list lookup_types = [ "PRIM_TYPE_BOX",
                      "PRIM_TYPE_CYLINDER",
                      "PRIM_TYPE_PRISM",
                      "PRIM_TYPE_SPHERE",
                      "PRIM_TYPE_TORUS",
                      "PRIM_TYPE_TUBE",
                      "PRIM_TYPE_RING",
                      "PRIM_TYPE_SCULPT" ];
 
list lookup_sculpt_type = [ 1, 2, 3, 4, 65, 66, 67, 68, 129, 130, 131, 132, 193, 194, 195, 196 ];
 
list lookdown_sculpt_type = [ "PRIM_SCULPT_TYPE_SPHERE",
                              "PRIM_SCULPT_TYPE_TORUS",
                              "PRIM_SCULPT_TYPE_PLANE",
                              "PRIM_SCULPT_TYPE_CYLINDER",
                              "PRIM_SCULPT_TYPE_SPHERE | PRIM_SCULPT_FLAG_INVERT",
                              "PRIM_SCULPT_TYPE_TORUS | PRIM_SCULPT_FLAG_INVERT",
                              "PRIM_SCULPT_TYPE_PLANE | PRIM_SCULPT_FLAG_INVERT",
                              "PRIM_SCULPT_TYPE_CYLINDER | PRIM_SCULPT_FLAG_INVERT",
                              "PRIM_SCULPT_TYPE_SPHERE | PRIM_SCULPT_FLAG_MIRROR",
                              "PRIM_SCULPT_TYPE_TORUS | PRIM_SCULPT_FLAG_MIRROR",
                              "PRIM_SCULPT_TYPE_PLANE | PRIM_SCULPT_FLAG_MIRROR",
                              "PRIM_SCULPT_TYPE_CYLINDER | PRIM_SCULPT_FLAG_MIRROR",
                              "PRIM_SCULPT_TYPE_SPHERE | PRIM_SCULPT_FLAG_INVERT | PRIM_SCULPT_FLAG_MIRROR",
                              "PRIM_SCULPT_TYPE_TORUS | PRIM_SCULPT_FLAG_INVERT | PRIM_SCULPT_FLAG_MIRROR",
                              "PRIM_SCULPT_TYPE_PLANE | PRIM_SCULPT_FLAG_INVERT | PRIM_SCULPT_FLAG_MIRROR",
                              "PRIM_SCULPT_TYPE_CYLINDER | PRIM_SCULPT_FLAG_INVERT | PRIM_SCULPT_FLAG_MIRROR" ];
 
list lookup_hole = [ 0, 16, 32, 48 ];
 
list lookdown_hole = [ "PRIM_HOLE_DEFAULT",
                       "PRIM_HOLE_CIRCLE",
                       "PRIM_HOLE_SQUARE",
                       "PRIM_HOLE_TRIANGLE" ];
 
list lookup_material = [ "PRIM_MATERIAL_STONE",
                         "PRIM_MATERIAL_METAL",
                         "PRIM_MATERIAL_GLASS",
                         "PRIM_MATERIAL_WOOD",
                         "PRIM_MATERIAL_FLESH",
                         "PRIM_MATERIAL_PLASTIC",
                         "PRIM_MATERIAL_RUBBER",
                         "PRIM_MATERIAL_LIGHT" ];
 
list lookup_shiny = [ "PRIM_SHINY_NONE",
                      "PRIM_SHINY_LOW",
                      "PRIM_SHINY_MEDIUM",
                      "PRIM_SHINY_HIGH" ];
 
list lookup_bump = [ "PRIM_BUMP_NONE",
                     "PRIM_BUMP_BRIGHT",
                     "PRIM_BUMP_DARK",
                     "PRIM_BUMP_WOOD",
                     "PRIM_BUMP_BARK",
                     "PRIM_BUMP_BRICKS",
                     "PRIM_BUMP_CHECKER",
                     "PRIM_BUMP_CONCRETE",
                     "PRIM_BUMP_TILE",
                     "PRIM_BUMP_STONE",
                     "PRIM_BUMP_DISKS",
                     "PRIM_BUMP_GRAVEL",
                     "PRIM_BUMP_BLOBS",
                     "PRIM_BUMP_SIDING",
                     "PRIM_BUMP_LARGETILE",
                     "PRIM_BUMP_STUCCO",
                     "PRIM_BUMP_SUCTION",
                     "PRIM_BUMP_WEAVE" ];
 
list lookup_texgen = [ "PRIM_TEXGEN_DEFAULT",
                       "PRIM_TEXGEN_PLANAR" ];
 
list lookup_phys_shape = [ "PRIM_PHYSICS_SHAPE_PRIM",
                           "PRIM_PHYSICS_SHAPE_NONE",
                           "PRIM_PHYSICS_SHAPE_CONVEX" ];
 
list lookup_bool = [ "FALSE", "TRUE" ];
 
list readable( list p, integer i ) {
    integer length = llGetListLength( p );
    integer count = 0;
    integer type;
    integer lfl;
    integer int;
    string str;
    string rs;
    list rl;
    while ( count < length ) {
        type = llGetListEntryType( p, count );
        if ( type == TYPE_STRING || type == TYPE_KEY ) {
            str = llList2String( p, count );
            lfl = llListFindList( lookup_strings, [ str ] );
            if ( ~lfl ) {
                rs = llList2String( lookdown_strings, lfl );
            } else {
                rs = "\"" + str + "\"";
            }
        } else if ( type == TYPE_VECTOR && llList2Vector( p, count ) == ZERO_VECTOR ) {
            rs = "ZERO_VECTOR";
        } else if ( type == TYPE_ROTATION && llList2Rot( p, count ) == ZERO_ROTATION ) {
            rs = "ZERO_ROTATION";
        } else if ( type == TYPE_INTEGER ) {
            int = llList2Integer( p, count );
            if ( i == 2 ) {
                rl = lookup_material;
            } else if ( i == 9 ) {
                if ( !count ) {
                    rl = lookup_types;
                } else if ( count == 1 ) {
                    rs = llList2String( lookdown_hole, llListFindList( lookup_hole, [ int ] ) );
                } else {
                    if ( int == 5 ) {
                        rs = ( string )int + " /* MESH */";
                    } else {
                        rs = llList2String( lookdown_sculpt_type, llListFindList( lookup_sculpt_type, [ int ] ) );
                    }
                }
            } else if ( i == 19 ) {
                if ( !count ) {
                    rl = lookup_shiny;
                } else {
                    rl = lookup_bump;
                }
            } else if ( i == 22 ) {
                rl = lookup_texgen;
            } else if ( i == 30 ) {
                rl = lookup_phys_shape;
            } else if ( int < 2 ) {
                rl = lookup_bool;
            }
        }
        if ( rl ) {
            rs = llList2String( rl, int );
            rl = [];
        }
        if ( rs ) {
            p = llListReplaceList( p, [ rs ], count, count );
            rs = "";
        }
        ++count;
    }
    return p;
}
 
sayList( list o, integer t, integer m ) {
    string terminator = ",";
    if ( t == 38 && !m ) {
        terminator = "";
    }
    llOwnerSay( "        " + llList2CSV( o ) + terminator );
}
 
list getUniqueListEntries( list src ) {
    integer index = 0;
    list output = [];
    list entry = [];
    while ( llGetListLength( src ) ) {
        output += ( entry = llList2List( src, 0, 0 ) );
        src = llDeleteSubList( src, 0, 0 );
        while ( ~( index = llListFindList( src, entry ) ) ) {
            src = llDeleteSubList( src, index, index );
        }
    }
    return output;
}
 
pullFaces( integer ln, string str, integer i ) {
    list faces = llGetLinkPrimitiveParams( ln, [ i, ALL_SIDES ] );
    integer length = llGetListLength( faces );
    integer nos = llGetLinkNumberOfSides( ln );
    if ( nos > 1 ) {
        integer offset = length / nos;
        integer count = 0;
        list readable_faces;
        list unique_faces;
        while ( count < length ) {
            readable_faces += [ llList2CSV( readable( llList2List( faces, count, count + ( offset - 1 ) ), i ) ) ];
            count += offset;
        }
        unique_faces = getUniqueListEntries( readable_faces );
        if ( llGetListLength( unique_faces ) > 1 ) {
            length = llGetListLength( readable_faces );
            count = 0;
            while ( count < length ) {
                sayList( [ str, count ] + [ llList2String( readable_faces, count ) ], i, length - count );
                ++count;
            }
        } else {
            sayList( [ str, "ALL_SIDES" ] + unique_faces, i, 0 );
        }
    } else {
        sayList( [ str, 0 ] + readable( faces, i ), i, 0 );
    }
}
 
defineParams( integer ln ) {
    integer length = llGetListLength( faceless_strings );
    integer i;
    while ( length ) {
        i = llList2Integer( faceless_integers, --length );
        // Omit PRIM_POSTION and PRIM_ROTATION params for child prims, and PRIM_POS_LOCAL and PRIM_ROT_LOCAL for the root.
        if ( !( ( i == 6 || i == 8 ) && ln > 1 ) && !( ( i == 29 || i == 33 ) && ln <= 1 ) ) {
            sayList( [ llList2String( faceless_strings, length ) ] + readable( llGetLinkPrimitiveParams( ln, [ i ] ), i ), 0, 1 );
        }
    }
    length = llGetListLength( faced_strings );
    while ( length ) {
        --length;
        pullFaces( ln, llList2String( faced_strings, length ), llList2Integer( faced_integers, length ) );
    }
}
 
default {
    state_entry() {
        integer nol = llGetObjectPrimCount( llGetKey() );
        if ( nol == 1 ) {
            llOwnerSay( "llSetLinkPrimitiveParamsFast( LINK_THIS, [" );
            defineParams( 0 );
        } else {
            llOwnerSay( "llSetLinkPrimitiveParamsFast( " + ( string )nol + ", [" );
            while ( nol ) {
                defineParams( nol-- );
                if ( nol ) {
                    llOwnerSay( "    ] + [ PRIM_LINK_TARGET, " + ( string )nol + "," );
                }
            }
        }
        llOwnerSay( "    ] );" );
        // llRemoveInventory( llGetScriptName() ); // Automatically removes the script after it's run, if uncommented.
    }
}

More Scripts...

If you have any comments about the content of this page please post them HERE