Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Texture changer w/ prefix

Aeryn Tuqiri
Registered User
Join date: 29 May 2008
Posts: 13
08-26-2008 09:00
Hello, wondering if anyone could help me, I am looking for a script to change textures in a multi prims object, by using prefixes.

Was looking around and the most similar script I found was the color change script, where you have to type "/3 color" followed of the color you want. I wanted something similar but that uses textures, lets say you have a bracelet with different fabrics, and want to change all the leather textures leaving the rest untouched. So you could type something like "/4 leather blue" and it would change only the leather parts to a blue leather texture. Also, that doesn't uses a premade textures list, but it gets the textures names directly from the prim contents.

I have been trying to adapt the color changer script to a texture changer one... but not knowing that much about lsl is making it rather hard for me, so if anyone wants to give me a help, I would appreciate it.

Or maybe it cant be done Oo? I haven't seen texture changers using llGetSubString...

^^ anyway, thank you for any help you can provide
Kaluura Boa
Polygon Project
Join date: 27 Mar 2007
Posts: 194
08-26-2008 19:30
I can do it. But I have a question: Are you sure that each prim of your object(s) to which you want to apply this change of texture uses only one texture?

If we have to apply different textures on the faces of a prim, that must be planned ahead. If yes, check the number of possible different textures, this is a *vital* information for the script(er), as well as the number of prims we're talking about.

And, btw, be prepared to edit your object(s) to rename the prims... No script can do everything for you. ;-)
Aeryn Tuqiri
Registered User
Join date: 29 May 2008
Posts: 13
08-26-2008 19:49
^^ thanks for the reply, the texture list is quite big, I am good by renaming prims and all, also good by placing scripts in every prim, I have been doing it already by using different channels for each prim.....

but complex items are starting to have a huge channels list, so wanted to reduce it by adding prefixes to change the textures.

lets see, could be 41 textures, maybe more, and each prim could change into this 41 textures.
Kaluura Boa
Polygon Project
Join date: 27 Mar 2007
Posts: 194
08-27-2008 07:02
You didn't answer 2 *vital* questions: How many prims in your object(s)? Do these prims never/sometimes/always use one or several textures on their faces.

Let's assume one texture per prim and that the number of prims will always allow us to store all that we need in the script memory. (IOW, complex objects may lead your heap to collide with your stack... And that hurts!) ;-)

Your part of the job:

Rename each prim according to the kind of texture it must carry. With your example of "leather blue", that means to rename as "leather" each prim that may use the "blue" texture.

For the sake of simplicity: lowercase everywhere! The names of the prims and the textures too. (If for some reason, you can't rename the textures, no problem but, for the moment, I assume you can.)

Still for the sake of simplicity, I will assume that no change of texture will ever be applied to the root prim of the object(s). This will also allow you to give a more pleasant name to your object(s). (If possible, you can re-link your object(s) in order that a prim which never changes of texture becomes the root or you can add another hidden prim as root.)

Enough talking. Let's script a little...

Note: I added a little thing. If you name a prim "nochange", as its name suggests, it won't change.

Note also that, for the moment, if you re-link your object(s), you must reset the script.

------------------------------------------
list ArrayOfPrims;
list Prefixes;

default
{
on_rez(integer param) { llResetScript(); }

state_entry()
{
integer num = llGetNumberOfPrims();
for (; num > 1; --num)
{
string name = llGetLinkName(num);
if (name != "nochange";)
{
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);
}
}
}
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 index = llListFindList(Prefixes, llList2List(tempo, 0, 0));
if (index == -1)
{
llOwnerSay("Invalid prefix.";);
return;
}
string texture = llList2String(tempo, 1);
// To allow textures names in several words, use this line instead:
//string texture = llDumpList2String(llDeleteSubList(tempo, 0, 0), " ";);
if (llGetInventoryType(texture) != INVENTORY_TEXTURE)
{
llOwnerSay("Invalid texture.";);
return;
}
tempo = llCSV2List(llList2String(ArrayOfPrims, index));
index = llGetListLength(tempo);
for (; index >= 0; --index)
{
llSetLinkTexture(llList2Integer(tempo, index), texture, ALL_SIDES);
}
}
}
------------------------------------------
Quote me to retrieve the layout.

Test and keep me informed.
Aeryn Tuqiri
Registered User
Join date: 29 May 2008
Posts: 13
08-27-2008 08:48
heh sorry, there are some prims that won't change yes, and might happen that not all prims change to the same selection of textures, some can be metal ones, other can be leather. as for total prims, I think that around 30+

I will test it out in around 7 hours from now, can't get on SL right now.

^^ thanks again
Aeryn Tuqiri
Registered User
Join date: 29 May 2008
Posts: 13
08-27-2008 13:24
tested it out and seems to work perfect, so basicly it gets each prim name and then every texture name, and by typing the channel followed with the prim name and texture, it changes it.

also changes any prim that has the same name, so if got 2 prims named ball, both of them change.

Now, what if you wanted to make 2 different effects for 1 set of prims, I explain, lets say we got a linked object with 2 boxes, 1 cilinder and the main prim containing the script, so unchangeable, each named box1, box 2 and cilinder respectively, and with this script you made it is possible to type /# box1 blue and /# box2 yellow, making one box blue and the other box yellow.

And then by typing /# allboxes red, it would make both boxes red.

or by typing /# all black, it would make all prims black, the 2 boxes and cilinder.

Would this be possible? or requieres a completly different script?


I don't mind having to write a list of all prefixes and prims names in the script, honestly, right now, I would even write all the textures in the script as well.
Kaluura Boa
Polygon Project
Join date: 27 Mar 2007
Posts: 194
08-28-2008 01:26
With a little imagination, everything is possible...

I'll go in SL in a few hours so I'll just explain and I'll post the script later.

The script just need a few modifications and it will adapt. And you won't have to do more than renaming prims.

Basicly, what you want is to be able to create super-groups containing several groups. Easy. To create the groups, you give a name to your prims. Let's just add another name and the super-groups are here!

With your example: The prims will have to be named "box1, all boxes", "box2, all boxes", "cylinder". That's all! No need to worry about the super-group "all", it can be automated. (I'll use the comma so you can use spaces in the names... even if it will introduce some complexity.)

I foresee no problem. Come on, give me some challenge! ;-)
Aeryn Tuqiri
Registered User
Join date: 29 May 2008
Posts: 13
08-28-2008 08:18
hehe, you are just too good.

I will be waiting ^^ hopefully works as you say.
Aeryn Tuqiri
Registered User
Join date: 29 May 2008
Posts: 13
08-30-2008 12:10
everything ok? Kaluura
Kaluura Boa
Polygon Project
Join date: 27 Mar 2007
Posts: 194
09-01-2008 01:52
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. ;-)
Aeryn Tuqiri
Registered User
Join date: 29 May 2008
Posts: 13
09-01-2008 15:06
wow, you are awesome

works marvelous =D

Thank you so much, this was what I was looking for ^^, no more huge lists of channels.

*hugs* let me know if there is anything I can do for you, I am good with making textures, profile pictures etc, I just suck when it comes LSL =P

thank you again, fell free to msg me ingame for anything ^^
Aeryn Tuqiri
Registered User
Join date: 29 May 2008
Posts: 13
09-03-2008 00:05
=3 its me again!

Wondering if you could adjust this script to work with with colors RGB, no need to have a premade color list or anything, just that people type /2 ball <0,0,0> and it will tint it.

also, could you highlight the part that sets the "all" group by default? I want to remove it in some situations where I do not want a prim to change texture.

^^ Thank you again

AT
Aeryn Tuqiri
Registered User
Join date: 29 May 2008
Posts: 13
09-03-2008 00:26
also, found a strange problem, you know that when you use a non existing prefix, it gives you a error msg saying "Script Prim: Invalid prefix."

this still happens if I use a existing prefix in at least 1 part of the item.

I explain the prim configuration I used for the object;

I have the object itself, and then I made a small prim that is the main prim, and another small prim to hold the script and textures.

when I use any command to change the object, I get the invalid prefix msg, then the prims do change color and also, the main prim changes color, but the main prim, does not contain the prefix I used in the name.

Could this be the reason? the script forcing it to change color even if the prefix isn't listen in the name (hence the error ?).

I tried placing the script in the main prim, and is still making the error, I can't understand.

I named the prims like:

all,boot
all,section1,stripes1,frame1
all,section2,stripes2,frame1

and so on, I used the all cause I prefer if the script doesn't change all parts and just the ones I tell it to change.