Difference between revisions of "User:Fred Gandt/Scripts/Continued 6"

From Second Life Wiki
Jump to navigation Jump to search
({{note|May run away screaming if asked to read tortured mutants.}})
(update pretty print prim params to include float trimming and line numbers)
 
(5 intermediate revisions by the same user not shown)
Line 2: Line 2:


== Free Scripts ==
== Free Scripts ==
=== {{Anchor|Menu Engine (Textures)}} Menu Engine (Textures) ( V1 ) ===
=== Menu Engine (Textures) ===
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 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.


Line 276: Line 276:
}</syntaxhighlight>
}</syntaxhighlight>


== {{Anchor|Pretty Print Prim Params}} Pretty Print Prim Params ( V5 ) ==
== Pretty Print Prim Params ==
Gathers and processes ALL primitive parameters from an object (multi or single prim), and spits out the results to [[llOwnerSay|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).
Gathers and processes ALL primitive parameters from an object (multi or single prim), and spits out the results to [[llOwnerSay|owner's local chat]] in a human readable format, suitable for addition to another script with little editing required, like the removal of included line numbers (since the llOwnerSays can get a little out of sync sometimes) and other chat chaff like the object name and timestamp.


Objects with lots of prims (links) may generate a massive wall of text. Trying to use the instruction to [[llSetLinkPrimitiveParamsFast|set the params]] in another object may not work due to [[LSL Errors#Script run-time error: Stack-Heap Collision|Stack-Heap Collisions]].
Objects with lots of prims (links) may generate a massive wall of text. Trying to use the instruction to [[llSetLinkPrimitiveParamsFast|set the params]] in another object may not work due to [[LSL Errors#Script run-time error: Stack-Heap Collision|Stack-Heap Collisions]].
Line 285: Line 285:
{{note|May run away screaming if asked to read tortured mutants.}}
{{note|May run away screaming if asked to read tortured mutants.}}


<syntaxhighlight lang="lsl2">// V5 //
<syntaxhighlight lang="lsl2">// V6 //
 
list faceless_strings = [ "PRIM_SCRIPTED_SIT_ONLY",
list faceless_strings = [ "PRIM_SCRIPTED_SIT_ONLY",
                           "PRIM_ALLOW_UNSIT",
                           "PRIM_ALLOW_UNSIT",
Line 411: Line 411:
   
   
list lookup_bool = [ "FALSE", "TRUE" ];
list lookup_bool = [ "FALSE", "TRUE" ];
integer line_number;
string trimTrailingZeros( string f ) {
    while ( llGetSubString( f, -1, -1 ) == "0" && llGetSubString( f, -2, -2 ) != "." ) {
        f = llDeleteSubString( f, -1, -1 );
    }
    return f;
}
string reduceVecsAndRots( string S ) {
    list coords = llCSV2List( llGetSubString( S, 1, -2 ) );
    integer length = llGetListLength( coords );
    integer count;
    while ( count < length ) {
        coords = llListReplaceList( coords, [ trimTrailingZeros( llList2String( coords, count ) ) ], count, count );
        ++count;
    }
    return "<" + llList2CSV( coords ) + ">";
}
   
   
list readable( list p, integer i ) {
list readable( list p, integer i ) {
     integer length = llGetListLength( p );
     integer length = llGetListLength( p );
     integer count = 0;
     integer count;
    rotation rot;
     integer type;
     integer type;
     integer lfl;
     integer lfl;
     integer int;
     integer int;
    vector vec;
     string str;
     string str;
     string rs;
     string rs;
Line 431: Line 453:
                 rs = "\"" + str + "\"";
                 rs = "\"" + str + "\"";
             }
             }
         } else if ( type == TYPE_VECTOR && llList2Vector( p, count ) == ZERO_VECTOR ) {
         } else if ( type == TYPE_VECTOR ) {
            rs = "ZERO_VECTOR";
            vec = llList2Vector( p, count );
         } else if ( type == TYPE_ROTATION && llList2Rot( p, count ) == ZERO_ROTATION ) {
            if ( vec == ZERO_VECTOR ) {
            rs = "ZERO_ROTATION";
                rs = "ZERO_VECTOR";
            } else {
                rs = reduceVecsAndRots( ( string )vec );
            }
         } else if ( type == TYPE_ROTATION ) {
            rot = llList2Rot( p, count );
            if ( rot == ZERO_ROTATION ) {
                rs = "ZERO_ROTATION";
            } else {
                rs = reduceVecsAndRots( ( string )rot );
            }
         } else if ( type == TYPE_INTEGER ) {
         } else if ( type == TYPE_INTEGER ) {
             int = llList2Integer( p, count );
             int = llList2Integer( p, count );
Line 464: Line 496:
                 rl = lookup_bool;
                 rl = lookup_bool;
             }
             }
        } else if ( type == TYPE_FLOAT ) {
            rs = trimTrailingZeros( llList2String( p, count ) );
         }
         }
         if ( rl ) {
         if ( rl ) {
Line 476: Line 510:
     }
     }
     return p;
     return p;
}
ownerSayWithLineNumber( string S ) {
    llOwnerSay( ( string )( ++line_number ) + " " + S );
}
}
   
   
Line 483: Line 521:
         terminator = "";
         terminator = "";
     }
     }
     llOwnerSay( "        " + llList2CSV( o ) + terminator );
     ownerSayWithLineNumber( "        " + llList2CSV( o ) + terminator );
}
}
   
   
Line 550: Line 588:
         integer nol = llGetObjectPrimCount( llGetKey() );
         integer nol = llGetObjectPrimCount( llGetKey() );
         if ( nol == 1 ) {
         if ( nol == 1 ) {
             llOwnerSay( "llSetLinkPrimitiveParamsFast( LINK_THIS, [" );
             ownerSayWithLineNumber( "llSetLinkPrimitiveParamsFast( LINK_THIS, [" );
             defineParams( 0 );
             defineParams( 0 );
         } else {
         } else {
             llOwnerSay( "llSetLinkPrimitiveParamsFast( " + ( string )nol + ", [" );
             ownerSayWithLineNumber( "llSetLinkPrimitiveParamsFast( " + ( string )nol + ", [" );
             while ( nol ) {
             while ( nol ) {
                 defineParams( nol-- );
                 defineParams( nol-- );
                 if ( nol ) {
                 if ( nol ) {
                     llOwnerSay( "    ] + [ PRIM_LINK_TARGET, " + ( string )nol + "," );
                     ownerSayWithLineNumber( "    ] + [ PRIM_LINK_TARGET, " + ( string )nol + "," );
                 }
                 }
             }
             }
         }
         }
         llOwnerSay( "    ] );" );
         ownerSayWithLineNumber( "    ] );" );
         // llRemoveInventory( llGetScriptName() ); // Automatically removes the script after it's run, if uncommented.
         // llRemoveInventory( llGetScriptName() ); // Automatically removes the script after it's run, if uncommented.
    }
}</syntaxhighlight>
== Chat Face Details ==
Useful for finding the color, texture and other settings of any face of any prim in an object. The information about the face touched is chatted to the owner.
Drop the script into the root.
<syntaxhighlight lang="lsl2">// V2 //
list bools = [ "FALSE", "TRUE" ];
string nullKey( string k ) {
    if ( k == "00000000-0000-0000-0000-000000000000" ) {
        return "NULL_KEY";
    }
    return k;
}
default {
    touch_start( integer nd ) {
        while ( nd ) {
            if ( llDetectedKey( --nd ) == llGetOwner() ) {
                integer link = llDetectedLinkNumber( nd );
                integer face = llDetectedTouchFace( nd );
                list params = llGetLinkPrimitiveParams( link, [ PRIM_COLOR, face, PRIM_TEXTURE, face, PRIM_TEXGEN, face,
                                                                PRIM_BUMP_SHINY, face, PRIM_FULLBRIGHT, face,
                                                                PRIM_GLOW, face, PRIM_SPECULAR, face,
                                                                PRIM_NORMAL, face, PRIM_ALPHA_MODE, face ] );
                float alpha = llList2Float( params, 1 );
                float tex_rot = llList2Float( params, 5 );
                float spec_rot = llList2Float( params, 14 );
                float norm_rot = llList2Float( params, 21 );
                integer nop = llGetNumberOfPrims();
                string plural = "";
                if ( nop > 1 ) {
                    plural = "s";
                }
                llOwnerSay( "Link: " + ( string )link + " of " + ( string )nop + " prim" + plural +
                            "\nLink UUID: " + ( string )llGetLinkKey( link ) +
                            "\n\nTouch:" +
                            "\n    Face: " + ( string )face + " of " + ( string )llGetLinkNumberOfSides( link ) +
                            "\n    ST: " + ( string )llDetectedTouchST( nd ) +
                            "\n    UV: " + ( string )llDetectedTouchUV( nd ) +
                            "\n    Normal: " + ( string )llDetectedTouchNormal( nd ) +
                            "\n    Binormal: " + ( string )llDetectedTouchBinormal( nd )
                );
                llOwnerSay( "\nColor: " + llList2String( params, 0 ) +
                            "\nTransparency: " + ( string )( ( 1.0 - alpha ) * 100 ) + "%" +
                            "\nAlpha: " + ( string )alpha +
                            "\n\nTexture:" +
                            "\n    UUID: " + llList2String( params, 2 ) +
                            "\n    Scale: " + llList2String( params, 3 ) +
                            "\n    Offset: " + llList2String( params, 4 ) +
                            "\n    Rotation in Radians: " + ( string )tex_rot +
                            "\n    Rotation in Degrees: " + ( string )( tex_rot * RAD_TO_DEG ) +
                            "\nTexgen: " + llList2String( [ "PRIM_TEXGEN_DEFAULT", "PRIM_TEXGEN_PLANAR" ], llList2Integer( params, 6 ) )
                );
                llOwnerSay( "\nShininess: " + llList2String( [ "PRIM_SHINY_NONE", "PRIM_SHINY_LOW", "PRIM_SHINY_MEDIUM",
                                                              "PRIM_SHINY_HIGH" ], llList2Integer( params, 7 ) ) +
                            "\nBumpiness: " + llList2String( [ "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" ], llList2Integer( params, 8 ) ) +
                            "\nFullbright: " + llList2String( bools, llList2Integer( params, 9 ) ) +
                            "\nGlow: " + llList2String( params, 10 ) +
                            "\nAlpha Mode: " + llList2String( bools, llList2Integer( params, 22 ) ) +
                            "\n    Mask Cutoff: " + llList2String( bools, llList2Integer( params, 23 ) )
                );
                llOwnerSay( "\nSpecular:" +
                            "\n    UUID: " + nullKey( llList2String( params, 11 ) ) +
                            "\n    Repeats: " + llList2String( params, 12 ) +
                            "\n    Offsets: " + llList2String( params, 13 ) +
                            "\n    Rotation in Radians: " + ( string )spec_rot +
                            "\n    Rotation in Degrees: " + ( string )( spec_rot * RAD_TO_DEG ) +
                            "\n    Color: " + llList2String( params, 15 ) +
                            "\n    Glossiness: " + llList2String( params, 16 ) +
                            "\n    Environment: " + llList2String( params, 17 )
                );
                llOwnerSay( "\nNormal:" +
                            "\n    UUID: " + nullKey( llList2String( params, 18 ) ) +
                            "\n    Repeats: " + llList2String( params, 19 ) +
                            "\n    Offsets: " + llList2String( params, 20 ) +
                            "\n    Rotation in Radians: " + ( string )norm_rot +
                            "\n    Rotation in Degrees: " + ( string )( norm_rot * RAD_TO_DEG ) + "\n"
                );
            }
        }
     }
     }
}</syntaxhighlight>}}
}</syntaxhighlight>}}

Latest revision as of 09:53, 25 March 2017

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)

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

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, like the removal of included line numbers (since the llOwnerSays can get a little out of sync sometimes) and other chat chaff like the object name and timestamp.

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.

NOTE: May run away screaming if asked to read tortured mutants.
// V6 //
 
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" ];

integer line_number;

string trimTrailingZeros( string f ) {
    while ( llGetSubString( f, -1, -1 ) == "0" && llGetSubString( f, -2, -2 ) != "." ) {
        f = llDeleteSubString( f, -1, -1 );
    }
    return f;
}

string reduceVecsAndRots( string S ) {
    list coords = llCSV2List( llGetSubString( S, 1, -2 ) );
    integer length = llGetListLength( coords );
    integer count;
    while ( count < length ) {
        coords = llListReplaceList( coords, [ trimTrailingZeros( llList2String( coords, count ) ) ], count, count );
        ++count;
    }
    return "<" + llList2CSV( coords ) + ">";
}
 
list readable( list p, integer i ) {
    integer length = llGetListLength( p );
    integer count;
    rotation rot;
    integer type;
    integer lfl;
    integer int;
    vector vec;
    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 ) {
            vec = llList2Vector( p, count );
            if ( vec == ZERO_VECTOR ) {
                rs = "ZERO_VECTOR";
            } else {
                rs = reduceVecsAndRots( ( string )vec );
            }
        } else if ( type == TYPE_ROTATION ) {
            rot = llList2Rot( p, count );
            if ( rot == ZERO_ROTATION ) {
                rs = "ZERO_ROTATION";
            } else {
                rs = reduceVecsAndRots( ( string )rot );
            }
        } 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;
            }
        } else if ( type == TYPE_FLOAT ) {
            rs = trimTrailingZeros( llList2String( p, count ) );
        }
        if ( rl ) {
            rs = llList2String( rl, int );
            rl = [];
        }
        if ( rs ) {
            p = llListReplaceList( p, [ rs ], count, count );
            rs = "";
        }
        ++count;
    }
    return p;
}

ownerSayWithLineNumber( string S ) {
    llOwnerSay( ( string )( ++line_number ) + " " + S );
}
 
sayList( list o, integer t, integer m ) {
    string terminator = ",";
    if ( t == 38 && !m ) {
        terminator = "";
    }
    ownerSayWithLineNumber( "        " + 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 ) {
            ownerSayWithLineNumber( "llSetLinkPrimitiveParamsFast( LINK_THIS, [" );
            defineParams( 0 );
        } else {
            ownerSayWithLineNumber( "llSetLinkPrimitiveParamsFast( " + ( string )nol + ", [" );
            while ( nol ) {
                defineParams( nol-- );
                if ( nol ) {
                    ownerSayWithLineNumber( "    ] + [ PRIM_LINK_TARGET, " + ( string )nol + "," );
                }
            }
        }
        ownerSayWithLineNumber( "    ] );" );
        // llRemoveInventory( llGetScriptName() ); // Automatically removes the script after it's run, if uncommented.
    }
}

Chat Face Details

Useful for finding the color, texture and other settings of any face of any prim in an object. The information about the face touched is chatted to the owner.

Drop the script into the root.

// V2 //
 
list bools = [ "FALSE", "TRUE" ];
 
string nullKey( string k ) {
    if ( k == "00000000-0000-0000-0000-000000000000" ) {
        return "NULL_KEY";
    }
    return k;
}
 
default {
    touch_start( integer nd ) {
        while ( nd ) {
            if ( llDetectedKey( --nd ) == llGetOwner() ) {
                integer link = llDetectedLinkNumber( nd );
                integer face = llDetectedTouchFace( nd );
                list params = llGetLinkPrimitiveParams( link, [ PRIM_COLOR, face, PRIM_TEXTURE, face, PRIM_TEXGEN, face,
                                                                PRIM_BUMP_SHINY, face, PRIM_FULLBRIGHT, face,
                                                                PRIM_GLOW, face, PRIM_SPECULAR, face,
                                                                PRIM_NORMAL, face, PRIM_ALPHA_MODE, face ] );
                float alpha = llList2Float( params, 1 );
                float tex_rot = llList2Float( params, 5 );
                float spec_rot = llList2Float( params, 14 );
                float norm_rot = llList2Float( params, 21 );
                integer nop = llGetNumberOfPrims();
                string plural = "";
                if ( nop > 1 ) {
                    plural = "s";
                }
                llOwnerSay( "Link: " + ( string )link + " of " + ( string )nop + " prim" + plural +
                            "\nLink UUID: " + ( string )llGetLinkKey( link ) +
                            "\n\nTouch:" +
                            "\n    Face: " + ( string )face + " of " + ( string )llGetLinkNumberOfSides( link ) +
                            "\n    ST: " + ( string )llDetectedTouchST( nd ) +
                            "\n    UV: " + ( string )llDetectedTouchUV( nd ) +
                            "\n    Normal: " + ( string )llDetectedTouchNormal( nd ) +
                            "\n    Binormal: " + ( string )llDetectedTouchBinormal( nd )
                );
                llOwnerSay( "\nColor: " + llList2String( params, 0 ) +
                            "\nTransparency: " + ( string )( ( 1.0 - alpha ) * 100 ) + "%" +
                            "\nAlpha: " + ( string )alpha +
                            "\n\nTexture:" +
                            "\n    UUID: " + llList2String( params, 2 ) +
                            "\n    Scale: " + llList2String( params, 3 ) +
                            "\n    Offset: " + llList2String( params, 4 ) +
                            "\n    Rotation in Radians: " + ( string )tex_rot +
                            "\n    Rotation in Degrees: " + ( string )( tex_rot * RAD_TO_DEG ) +
                            "\nTexgen: " + llList2String( [ "PRIM_TEXGEN_DEFAULT", "PRIM_TEXGEN_PLANAR" ], llList2Integer( params, 6 ) )
                );
                llOwnerSay( "\nShininess: " + llList2String( [ "PRIM_SHINY_NONE", "PRIM_SHINY_LOW", "PRIM_SHINY_MEDIUM",
                                                               "PRIM_SHINY_HIGH" ], llList2Integer( params, 7 ) ) +
                            "\nBumpiness: " + llList2String( [ "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" ], llList2Integer( params, 8 ) ) +
                            "\nFullbright: " + llList2String( bools, llList2Integer( params, 9 ) ) +
                            "\nGlow: " + llList2String( params, 10 ) +
                            "\nAlpha Mode: " + llList2String( bools, llList2Integer( params, 22 ) ) +
                            "\n    Mask Cutoff: " + llList2String( bools, llList2Integer( params, 23 ) )
                );
                llOwnerSay( "\nSpecular:" +
                            "\n    UUID: " + nullKey( llList2String( params, 11 ) ) +
                            "\n    Repeats: " + llList2String( params, 12 ) +
                            "\n    Offsets: " + llList2String( params, 13 ) +
                            "\n    Rotation in Radians: " + ( string )spec_rot +
                            "\n    Rotation in Degrees: " + ( string )( spec_rot * RAD_TO_DEG ) +
                            "\n    Color: " + llList2String( params, 15 ) +
                            "\n    Glossiness: " + llList2String( params, 16 ) +
                            "\n    Environment: " + llList2String( params, 17 )
                ); 
                llOwnerSay( "\nNormal:" +
                            "\n    UUID: " + nullKey( llList2String( params, 18 ) ) +
                            "\n    Repeats: " + llList2String( params, 19 ) +
                            "\n    Offsets: " + llList2String( params, 20 ) +
                            "\n    Rotation in Radians: " + ( string )norm_rot +
                            "\n    Rotation in Degrees: " + ( string )( norm_rot * RAD_TO_DEG ) + "\n"
                );
            }
        }
    }
}

More Scripts...

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