I'm back!

Sorry, I was unexpectedly busy... but I haven't forgotten you.
You can now give any name to your groups of prims or groups of groups. I mean:
- White spaces are authorized. Plural! Names can contain several words like, for example, "top of object".
- You don't have to worry about lower/upper case except that you must not rely on it to differentiate 2 groups.
- Partially matching names of group are correctly recognized. For example, "left corner" vs. "right corner" or "top left" vs "top right".
- I didn't forget the "all" group that is automatically created. Note that this doesn't prevent you from creating a group named "all the belt" for example.
Textures also can have names containing several words... AND you don't have to rename them to lower case any more.
The only precaution to take: Avoid the comma like the plague!

It is authorized only to separate the names of group in the prims names.
You can assign a prim to more than 2 groups. For example: "leather, belt, bright parts" is a valid name. So you can change all the leather prims, all the belt (without the buckle) or only the bright parts.
Enough talking! The script...
(Quote me to retrieve the layout.)
---------------------------------------------
list ArrayOfPrims;
list Prefixes;
default
{
on_rez(integer param) { llResetScript(); }
state_entry()
{
integer num = llGetNumberOfPrims();
for (; num > 1; --num)
{
string name = llToLower(llGetLinkName(num));
if (name != "nochange"

{
list tempo = llCSV2List(name);
integer grp = llGetListLength(tempo) - 1;
for (; grp >= -1; --grp)
{
if (grp == -1)
{
name = "all";
}
else
{
name = llList2String(tempo, grp);
}
integer index = llListFindList(Prefixes, [name]);
if (index == -1)
{
Prefixes = (Prefixes = []) + Prefixes + name;
ArrayOfPrims = (ArrayOfPrims = []) + ArrayOfPrims + ((string)num);
}
else
{
ArrayOfPrims = llListReplaceList(ArrayOfPrims,
[llList2String(ArrayOfPrims, index) + "," + (string)num],
index, index);
}
}
}
}
// DEBUG
//num = llGetListLength(ArrayOfPrims) - 1;
//for (; num >= 0; --num)
//{
// llOwnerSay(llList2String(Prefixes, num) + " " + llList2String(ArrayOfPrims, num));
//}
llListen(3, "", llGetOwner(), ""

;
}
listen(integer channel, string name, key id, string msg)
{
msg = llToLower(msg);
list tempo = llParseString2List(msg, [" "], []);
integer num = llGetListLength(tempo) - 2;
if (num < 0)
{
llOwnerSay("Invalid command line."

;
return;
}
string name;
integer index;
string texture;
integer FOUND = FALSE;
while ( (! FOUND) && (num >= 0) )
{
name = llDumpList2String(llList2List(tempo, 0, num), " "

;
// llOwnerSay("Checking prefix: " + name); // DEBUG
index = llListFindList(Prefixes, [name]);
if (index != -1)
{
texture = llDumpList2String(llList2List(tempo, num + 1, -1), " "

;
// llOwnerSay("With texture: " + texture); // DEBUG
FOUND = TRUE;
}
--num;
}
if ( (index == -1) || (! FOUND) )
{
llOwnerSay("Invalid prefix."

;
return;
}
FOUND = FALSE;
num = llGetInventoryNumber(INVENTORY_TEXTURE) - 1;
while ( (! FOUND) && (num >= 0) )
{
name = llGetInventoryName(INVENTORY_TEXTURE, num);
if (llToLower(name) == texture)
{
FOUND = TRUE;
}
--num;
}
if (! FOUND)
{
llOwnerSay("Invalid texture."

;
return;
}
tempo = llCSV2List(llList2String(ArrayOfPrims, index));
num = llGetListLength(tempo);
for (; num >= 0; --num)
{
llSetLinkTexture(llList2Integer(tempo, num), name, ALL_SIDES);
}
}
}
---------------------------------------------
Tested and debugged in world, Havok 4 and Mono compatible, etc, etc.
