Jump to content
carley Greymoon

best way owner set texture?

Recommended Posts

hi, i'm making a texture change HUD. the code i used was:

default
{
    state_entry()
    {
        llListen (-xxxxx,"","","");
    }

    listen(integer channel, string name, key id, string msg)
    {
        llSetTexture(msg,ALL_SIDES);
}

that worked perfect. you wore or rezzed the object, click on the HUD, enter the UUID and all the parts changed very fast and reliable. trouble was anyone else using the same HUD could change the texture on your object as well.

so to make it owner specific i added

if (llGetOwnerKey(id) == llGetOwner()) making it:

 

default
{
    state_entry()
    {
        llListen (-xxxxxx"","","");
    }

    listen(integer channel, string name, key id, string msg)
    {
        if (llGetOwnerKey(id) == llGetOwner()){
        llSetTexture(msg,ALL_SIDES);
        }
    }
}

 

that technically works but it is very glitchy, sometimes the linkset goes randomly transparent, other times just some parts get the texture. reapplying the same texture does nothing, using a different texture makes everything change again but wit the same randomness and unreliable. only after 4 or 5 tries does it finally work right. it's maddening.

i'm guessing it is lag and that when the desired texture finally gets into the cache it works. can it be that adding the get owner key and comparing it causes too much lag and it makes the scripts fail randomly?

this script goes into an object with about 90 prims. in other words there is 90 iterations of the script firing at once.

is that the problem and is there a better way of doing it?

i'm new to scripting and have just cobbled together code i've found here and on other sites.

thank you for any help.

 

 

 

Edited by carley Greymoon

Share this post


Link to post
Share on other sites
3 hours ago, carley Greymoon said:

this script goes into an object with about 90 prims. in other words there is 90 iterations of the script firing at once.

Rather than having a script in every prim in your linkset try using a single script in the root with llSetLinkTexture(LINK_SET, msg, ALL_SIDES);

Share this post


Link to post
Share on other sites

1st - you need only one script - see Fluffy's post

2nd - the script doesn't check if it receives an uuid (ok, not that important here :) )

if (llGetOwnerKey(id) == llGetOwner()){
	key uuid = (key)msg;
	if (uuid) {
		llSetLinkTexture(LINK_SET,msg,ALL_SIDES);
	}
}

3rd - if you encounter update problems - means the textures are changed but you don't see the result - it helps to change another thing on the object. For example set an invisible hovertext (with llSetText)

Edited by Nova Convair

Share this post


Link to post
Share on other sites

i don't think i can use setlink. imagine an avatar, it is one mesh( 1 linkset) but has 3 sections, the head, torso and lower with 3 different textures. separating the sections into their own object, then i could apply the texture to the whole thing with SetLink but then each section would have to be worn separately, meaning a person would have to use 3 attachment points.

so that's why i put a script in each part, in essence i grouped them by using different listening channels for each section.

before i added the owner check it work really well, no issues at all.

 

Nova, i had no idea it should check if it did indeed receive a UUID but it sounds logical that it should, thank you for pointing that out and providing an example snippet. i will try to insert that bit.

i'm not sure what you mean by number 3. i myself can change other things to get it to update eventually but i can't ask that of users, although i'm sure i'm not understanding what you mean.

 

Edited by carley Greymoon

Share this post


Link to post
Share on other sites
1 hour ago, carley Greymoon said:

i don't think i can use setlink. imagine an avatar, it is one mesh( 1 linkset) but has 3 sections, the head, torso and lower with 3 different textures. separating the sections into their own object, then i could apply the texture to the whole thing with SetLink but then each section would have to be worn separately, meaning a person would have to use 3 attachment points.

6 hours ago, Fluffy Sharkfin said:

 llSetLinkTexture(LINK_SET, msg, ALL_SIDES);

Look at the command again... The example given is using wildcard parameters... LINK_SET means all prims in the link, ALL_SIDES means all faces on the prim.

You CAN use llSetLinkTexture, just specify WHICH prim in the linkset and which faces on the prim in each use of the command.

So, for say a mesh body that's 1 'prim' with 3 faces each with a different texture, your single script would have 3 uses of llSetLinkTexture, each applying a different image to a different 'face' of the 'prim'.
 

Share this post


Link to post
Share on other sites

if the main problem was people using the same channel in their HUDs ...

 chan = 0x80000000 | (integer)("0x"+(string)llGetOwner());    // unique channel based on owners UUID   

  llListen (chan,"","","");

( now each HUD has a unique channel )

Share this post


Link to post
Share on other sites
12 minutes ago, Klytyna said:

So, for say a mesh body that's 1 'prim' with 3 faces each with a different texture, your single script would have 3 uses of llSetLinkTexture, each applying a different image to a different 'face' of the 'prim'.

Unfortunately that's not going to work if they want to apply different textures to different parts of the linkset since we can't use lists of integers to specify link numbers in llSetLink commands (which is a real shame).

Personally I'd suggest using a for loop with llSetLinkPrimitiveParamsFast() and a list of link numbers for each part of the object (head, torso and lower), it may take marginally longer to set the texture for all the children of a linkset but it's still preferable to having 90+ running scripts with listens.  You can pass all three textures in a single message as a comma separated value and apply each texture to different parts of the linkset.

list head = []; // link numbers for head
list torso = []; // link numbers for torso
list lower = []; // link numbers for lower

setTexture(list link_numbers, key texture)
{
  integer i;
  for (i=0; i < llGetListLength(link_numbers); i++)
    llSetLinkPrimitiveParamsFast(llList2Integer(link_numbers,i), [PRIM_TEXTURE, ALL_SIDES, texture, <1,1,0>, <0,0,0>, 0.0]);
}

default
{
  state_entry()
  {
    llListen (-xxxxxx,"","","");
  }

  listen(integer channel, string name, key id, string msg)
  {
    if (llGetOwnerKey(id) == llGetOwner()){
      list textures = llCSV2List(msg);
      setTexture(head,llList2Key(textures,0));
      setTexture(torso,llList2Key(textures,1));
      setTexture(lower,llList2Key(textures,2));
    }
  }
}

 

Of course you'd need to fill in all the link numbers for each list at the start of the script, but a simple way to do that would be to rez the object, tint each of the sections a separate color then drop in a script which will check the color of each object in the linkset and compile the link numbers into 3 lists based on those colors and spit those lists out into chat.  Then you can copy and paste those into the start of the script above.

Share this post


Link to post
Share on other sites

wow thanks for all the help and suggestions. i'm going to try both ways just so i can know more than one way of doing it. i had no idea you could automatically find link numbers by color.

thanks to everyone for taking the time to help:)

Share this post


Link to post
Share on other sites
46 minutes ago, carley Greymoon said:

wow thanks for all the help and suggestions. i'm going to try both ways just so i can know more than one way of doing it. i had no idea you could automatically find link numbers by color.

thanks to everyone for taking the time to help:)

Well, it's not automatic but you can do it with a simple script like so...

default
{
    state_entry()
    {
        integer i;
        vector color;
        list head = [];
        list torso = [];
        list lower = [];
        for (i=1; i<=llGetNumberOfPrims(); i++)
        {
            color = llList2Vector(llGetLinkPrimitiveParams(i,[PRIM_COLOR,0]),0);
            if (color == <1,0,0>)
                head = head + [i];
            else if (color == <0,1,0>)
                torso = torso + [i];
            else if (color == <0,0,1>)
                lower = lower + [i];
        }
        llOwnerSay("\nlist head = ["+llList2CSV(head)+"];\nlist torso = ["+llList2CSV(torso)+"];\nlist lower = ["+llList2CSV(lower)+"];");
    }
}

... just tint the different sections red, green and blue and then drop the above script in and it will output the lists of link numbers for each section complete with formatting so you can just copy and paste, replacing the first three lines of the other script.

Edited by Fluffy Sharkfin

Share this post


Link to post
Share on other sites
1 hour ago, Fluffy Sharkfin said:

Well, it's not automatic but you can do it with a simple script like so...


default
{
    state_entry()
    {
        integer i;
        vector color;
        list head = [];
        list torso = [];
        list lower = [];
        for (i=1; i<=llGetNumberOfPrims(); i++)
        {
            color = llList2Vector(llGetLinkPrimitiveParams(i,[PRIM_COLOR,0]),0);
            if (color == <1,0,0>)
                head = head + [i];
            else if (color == <0,1,0>)
                torso = torso + [i];
            else if (color == <0,0,1>)
                lower = lower + [i];
        }
        llOwnerSay("\nlist head = ["+llList2CSV(head)+"];\nlist torso = ["+llList2CSV(torso)+"];\nlist lower = ["+llList2CSV(lower)+"];");
    }
}

... just tint the different sections red, green and blue and then drop the above script in and it will output the lists of link numbers for each section complete with formatting so you can just copy and paste, replacing the first three lines of the other script.

hi fluffy, i tried the script but the only output i got in chat was

list head = [];
list torso = [];
list lower = [];

no face numbers.

Share this post


Link to post
Share on other sites

Are you actually coloring those test prims Red (<1,0,0>), Green (<0,1,0>) and Blue (<0,0,1>), not just some random reddish, greenish, bluish colors?  As written, that little script will be looking for pure hues.

Edited by Rolig Loon

Share this post


Link to post
Share on other sites
26 minutes ago, Rolig Loon said:

Are you actually coloring those test prims Red (<1,0,0>), Green (<0,1,0>) and Blue (<0,0,1>), not just some random reddish, greenish, bluish colors?  As written, that little script will be looking for pure hues.

hi rolig, yes that was the problem. in the color picker i was using "rgb" with the values of 100, 0 ,0 and so on instead of "lsl". thanks for that:)

i'm going to try the mesh now:) i'll be back a bit later with hopefully some good news:)

Share this post


Link to post
Share on other sites

Yes, sorry I probably should have mentioned that you need to use the exact color values as the script ignores any members of the linkset which aren't tinted the correct colors. 

Share this post


Link to post
Share on other sites

hi Fluffy, no worries, i'm just grateful for the help.

i got it all set up and the scripts, the sender and receiver are communicating but the texture is not being set, instead it just turns gray. could it be the texture UUID is not getting passed onto the receiver script?

Share this post


Link to post
Share on other sites

I hate to ask another "Is it plugged in?" question, but since I can't see your finished script to be sure ..... Did you actually include the texture UUIDs in your script somewhere?

Share this post


Link to post
Share on other sites

hi Rolig, the texture UUID is input by the user via a text box. this is the code of the sender script

default
{
    state_entry()
    {
        llListen(-xxxxxx,"","","");
    }

    touch_start(integer total_number)
    {
        llTextBox(llDetectedKey(0)," \n Enter a texture UUID",-xxxxxx);
    }
   
    listen(integer channel, string name, key id, string msg)
    {
        llRegionSay(-12345,msg);
    }
}

and this is the code of the receiver script provided by fluffy(much thanks), i modified it to split it into one script for each section, so the user would have one button per section so they could apply textures independently.

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
list lower = [50, 51, 52, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93];

setTexture(list link_numbers, key texture)
{
  integer i;
  for (i=0; i < llGetListLength(link_numbers); i++)
    llSetLinkPrimitiveParamsFast(llList2Integer(link_numbers,i), [PRIM_TEXTURE, ALL_SIDES, texture, <1,1,0>, <0,0,0>, 0.0]);
}

default
{
  state_entry()
  {
    llListen(-xxxxxx,"","","");
  }

  listen(integer channel, string name, key id, string msg)
  {
    if (llGetOwnerKey(id) == llGetOwner()){
      list textures = llCSV2List(msg);

      setTexture(lower,llList2Key(textures,2));
    }
  }
}

 

 

Share this post


Link to post
Share on other sites

This doesn't work:

 listen(integer channel, string name, key id, string msg)
 {
    if (llGetOwnerKey(id) == llGetOwner()){
      list textures = llCSV2List(msg);

      setTexture(lower,llList2Key(textures,2));
    }
 }

msg is a string
the list you compose out of msg consists of strings
llList2Key only works if the list has stored a key it does not convert a string to a key
you need to use:

setTexture(lower,(key)llList2String(textures,2));

 

Share this post


Link to post
Share on other sites
1 hour ago, Nova Convair said:

This doesn't work:


 listen(integer channel, string name, key id, string msg)
 {
    if (llGetOwnerKey(id) == llGetOwner()){
      list textures = llCSV2List(msg);

      setTexture(lower,llList2Key(textures,2));
    }
 }

msg is a string
the list you compose out of msg consists of strings
llList2Key only works if the list has stored a key it does not convert a string to a key
you need to use:


setTexture(lower,(key)llList2String(textures,2));

 

hi Nova, i just tried that and i still get the same result, the lower section just turns gray. when open the edit panel it show a gray texture in the texture window same as before.

this is the script with your change:

list lower = [50, 51, 52, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93];

setTexture(list link_numbers, key texture)
{
  integer i;
  for (i=0; i < llGetListLength(link_numbers); i++)
    llSetLinkPrimitiveParamsFast(llList2Integer(link_numbers,i), [PRIM_TEXTURE, ALL_SIDES, texture, <1,1,0>, <0,0,0>, 0.0]);
}

default
{
  state_entry()
  {
    llListen(-xxxxxx,"","","");
  }

  listen(integer channel, string name, key id, string msg)
  {
    if (llGetOwnerKey(id) == llGetOwner()){
      list textures = llCSV2List(msg);

      setTexture(lower,(key)llList2String(textures,2));
    }
  }
}
-----------------------------------------------------------------------

this starting to get weird. i'm wracking my brain to think of something i might be overlooking and not including here but i can't think of anything.

i'm sorry to be such a pain. i get the feeling once it is figured out why it's not working i'm going to feel bad for having overlooked mentioning some thing.

Edited by carley Greymoon

Share this post


Link to post
Share on other sites

i just tried the script again as a whole and the only part that gets the texture set is the head section, wich is also the root prim.


list head = [1];
list torso = [42, 43, 44, 45, 46, 47, 48, 49, 53, 54, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134];
list lower = [50, 51, 52, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93];

setTexture(list link_numbers, key texture)
{
  integer i;
  for (i=0; i < llGetListLength(link_numbers); i++)
    llSetLinkPrimitiveParamsFast(llList2Integer(link_numbers,i), [PRIM_TEXTURE, ALL_SIDES, texture, <1,1,0>, <0,0,0>, 0.0]);
}

default
{
  state_entry()
  {
    llListen (-xxxxxx,"","","");
  }

  listen(integer channel, string name, key id, string msg)
  {
    if (llGetOwnerKey(id) == llGetOwner()){
      list textures = llCSV2List(msg);
      setTexture(head,llList2Key(textures,0));
      setTexture(torso,llList2Key(textures,1));
      setTexture(lower,llList2Key(textures,2));
    }
  }
}

i also tried it with llList2String, same result, only the head section gets the texture set.

 

Edited by carley Greymoon

Share this post


Link to post
Share on other sites
1 hour ago, Nova Convair said:

llList2Key only works if the list has stored a key it does not convert a string to a key

From the wiki 

Quote

If the type of the element at index in src is not a key it is typecast to a key. If it cannot be typecast null string is returned.

 

carley, the reason the script isn't working as you have it now is it was written to work with three texture UUIDs, if you're passing a single UUID to it then you simply need to change

setTexture(lower,(key)llList2String(textures,2));

to

setTexture(lower,(key)llList2String(textures,0));

 

But, that would defeat the purpose of separating the message into a list of UUIDs since there's only one.

The idea is to handle changing all the textures of the linkset using a single script rather than using multiple scripts for each texture. :)

Share this post


Link to post
Share on other sites

Okay since you're sending texture UUIDs one at a time rather than all three at once, try this...

Sender Script (based on the script you currently have)

default
{
    state_entry()
    {
        llListen(-54321,"","","");
    }

    touch_start(integer total_number)
    {
        llTextBox(llDetectedKey(0)," \n Enter a bodypart and texture UUID",-54321);
    }
   
    listen(integer channel, string name, key id, string msg)
    {
        llRegionSay(-12345,msg); 
    }
}

Receiver Script (based on the script I posted earlier)

list head = [1,2,3];
list torso = [4,5,6];
list lower = [7,8,9];

setTexture(list link_numbers, key texture)
{
    integer i;
    for (i=0; i < llGetListLength(link_numbers); i++)
        llSetLinkPrimitiveParamsFast(llList2Integer(link_numbers,i), [PRIM_TEXTURE, ALL_SIDES, texture, <1,1,0>, <0,0,0>, 0.0]);
}

default
{
    state_entry()
    {
        llListen (-12345,"","","");
    }

    listen(integer channel, string name, key id, string msg)
    {
        if (llGetOwnerKey(id) == llGetOwner()){
            list data = llCSV2List(msg);
            string bodypart = llList2String(data,0);
            key texture = llList2Key(data,1);
            if (bodypart == "head")
                setTexture(head,texture);
            else if (bodypart == "torso")
                setTexture(torso,texture);
            else if (bodypart == "lower")
                setTexture(lower,texture);
        }
    }
}

 

In order for it to work you need to specify both which bodypart you wish to apply the texture to and the texture UUID as a CSV.

For example:

Quote

head,89556747-24cb-43ed-920b-47caed15465f

will texture the head with the default plywood texture.

 

It's not the most elegant solution to selecting which bodypart to texture, personally I'd go with a HUD or at least an llDialog menu rather than having to type the bodypart name into the text box, but at least you can test it and see it working. :)

 

Edited by Fluffy Sharkfin
typo

Share this post


Link to post
Share on other sites

oh wow, Thank you so much Fluffy:) it's working now as separate scripts. one for each section. 3 sections each with their own buttons. which is just fine with me, it serves my purpose.

but i don't understand how all 3 could work with one script. the user can input 3 UUIDs into one text box? i know you must be right, i just don't get how the script could know which UUID belongs to what section. lets say the torso texture UUID is 111-1111-1111-111 and the lower is 222-2222-222. how could the script know texture 111-1111-111 belongs to list torso = [42, 43, 44, 45, 46, 47, 48, 49, 53, 54, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134];?

in any case i thank you profusely:) and everyone else as well.

Share this post


Link to post
Share on other sites
7 minutes ago, carley Greymoon said:

oh wow, Thank you so much Fluffy:) it's working now as separate scripts. one for each section. 3 sections each with their own buttons. which is just fine with me, it serves my purpose.

but i don't understand how all 3 could work with one script. the user can input 3 UUIDs into one text box? i know you must be right, i just don't get how the script could know which UUID belongs to what section. lets say the torso texture UUID is 111-1111-1111-111 and the lower is 222-2222-222. how could the script know texture 111-1111-111 belongs to list torso = [42, 43, 44, 45, 46, 47, 48, 49, 53, 54, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134];?

in any case i thank you profusely:) and everyone else as well.

in the original script that I posted earlier the textures are meant to be sent in a certain order (head, torso, lower), the script simply assumes that's the order in which the three UUIDs have been sent and applies them to the corresponding bodyparts.

As for the new script, since you're sending them one at a time you have to specify which bodypart it applies the texture to and include that information in the message (i.e. "torso,111-1111-1111-111" or "lower,222-2222-222").  As I suggested earlier you could include an llDialog command to open a menu with three buttons (head, torso, lower) then when the user presses one the script automatically opens the text input window to allow them to input the texture UUID.  That way they don't have to type in the name of the bodypart they can just select it from the menu, but having separate buttons for each section works just as well (although you can also do that using a single script rather than three separate ones if you put the script in the root object and use llDetectedLinkNumber() in the touch event). ;)

 

Anyway, I'm glad it's working for you now! :)

Share this post


Link to post
Share on other sites

 

ahhh ok  i get it. :)  and the llDialog method sounds very coolB|

I learned a lot from this thread. Thanks again, without people like you, Rolig and Nova life would be much harder.

 

13 minutes ago, Fluffy Sharkfin said:

in the original script that I posted earlier the textures are meant to be sent in a certain order (head, torso, lower), the script simply assumes that's the order in which the three UUIDs have been sent and applies them to the corresponding bodyparts.

As for the new script, since you're sending them one at a time you have to specify which bodypart it applies the texture to and include that information in the message (i.e. "torso,111-1111-1111-111" or "lower,222-2222-222").  As I suggested earlier you could include an llDialog command to open a menu with three buttons (head, torso, lower) then when the user presses one the script automatically opens the text input window to allow them to input the texture UUID.  That way they don't have to type in the name of the bodypart they can just select it from the menu, but having separate buttons for each section works just as well (although you can also do that using a single script rather than three separate ones if you put the script in the root object and use llDetectedLinkNumber() in the touch event). ;)

 

Anyway, I'm glad it's working for you now! :)

 

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...