Jump to content

Texture Applier


Elfie Erin
 Share

You are about to reply to a thread that has been inactive for 1985 days.

Please take a moment to consider if this thread is worth bumping.

Recommended Posts

Hello

I've been working on a texture applier for a while now and I've hit a wall, so I figured I would ask for some help here.

My plan is to have a script that holds texture UUIDS as so,

string tex_1 = "3d80799c-de95-11e8-9f32-f2801f1b9fd1";
string tex_2 = "3d807c12-de95-11e8-9f32-f2801f1b9fd1";

Then once triggered, it sends a message to a receiver containing the UUIDs

llWhisper(MyChannel, "tex_1 "+(string)tex_1 + " " + "tex_2 "+(string)tex_1);

The reciever then hears the string (cleaned it up visually here)

tex_1 3d80799c-de95-11e8-9f32-f2801f1b9fd1
tex_2 3d807c12-de95-11e8-9f32-f2801f1b9fd1

This is where I get a bit stumped about performing a function that takes this string and changes the corresponding receivers "string tex_1 = UUID" to the one being sent. What I can't figure out is how to clean up the message once received, if such a thing is possible in the first place, or if I'm just not thinking about this the right way.

If the receiver can load the UUID in like this, it will apply them to the desired links and faces of my mesh.

 

I have tried a few other methods that did not pan out, but I think if this one could actually function, it would be a more clean way of performing a one-click texture application to my avatar.

Link to comment
Share on other sites

 I assume you know how and where to actually set the textures, but don't know how to get those UUIDs out of the string you receive.

There are a couple easy ways to do this, namely:

http://wiki.secondlife.com/wiki/LlParseString2List

http://wiki.secondlife.com/wiki/LlCSV2List

These allow you to easily convert your string message to a list and from there you csn get the key by index. You could also shorten your message/list by only having the keys in there, you don't need the "tex_" names since you know they will be there in that order.

Alternatively, you could also use this to get the very specific part of the message you want, since you know the message will always be the same length:

http://wiki.secondlife.com/wiki/LlGetSubString

  • Thanks 1
Link to comment
Share on other sites

Assuming the message the receiving script hears will always be of the form "string [space] UUID", and the length of the string might vary, you could find the space character in the message and then grab everything after it:

uuid = llGetSubString (message, llSubStringIndex (message, " ") + 1, -1);

Doh! You want to have several textures in the message. Wulfie got it right first time.

Edited by KT Kingsley
  • Thanks 1
Link to comment
Share on other sites

Wulfie beat me to it ?

The only thing I'd add is that I try to use seprators for data sets like this  to make the field clear. a simple space may mess you up. I'll tend to use symbols that are not to normally be found ... ^, ~, | .. so this would mean:

 

//Call
lWhisper(MyChannel, "tex_1"+ DATA_SEP + (string)tex_1 + FUNC_SEP + "tex_2"+ DATA_SEP + (string)tex_1);

//Receiving Moduls
string EMPTY_STR = "";
string FUNC_SEP = "|";
string DATA_SEP = "^";

listen(integer channel, string name, key id, string message)
{
    list pairs = llParseString2List(message, [FUNC_SEP], [EMPTY_STR]);
    integer x;
    integer numPairs = llGetListLength(pairs);
    
    for (x = 0; x < numPairs: x++)
    {
        list params = llParseString2List(llList2String(pairs, x), [DATA_SEP], {EMPTY_STR]));
        string id = llList2String(params, 0);
        key texture = (key)llList2String(params, 1);
                             
        //do something
    }   
}

 

  • Thanks 1
Link to comment
Share on other sites

Thanks for all the replies. I've been trying to figure out how the mentioned solutions work for a day now and kind of get it, but my understanding of coding fails me again. What I have now, seems to me two lists, one with the 'tex_#' ID's, another with the corresponding UUID to that id, which is awesome! I just can't figure out how to manipulate the list and its contents now.

My problem is I cant visualize where the list "exist" so to speak, so when I try to plug the ID or key in, I can only get the first in the list.

integer MyChannel;
key MyOwner;

string EMPTY_STR = "";
string FUNC_SEP = "|";
string DATA_SEP = "^";

default
{
    state_entry()
    {
        MyOwner = llGetOwner();
        MyChannel = 0x80000000 | (integer)("0x"+(string)MyOwner);
        llListen(MyChannel,"",NULL_KEY,"");
    }
    
    listen(integer channel, string name, key id, string message)
    {
        list pairs = llParseString2List(message, [FUNC_SEP], [EMPTY_STR]);
        integer x;
        integer numPairs = llGetListLength(pairs);
        
        for (x = 0; x < numPairs; x++)
        {
            list params = llParseString2List(llList2String(pairs, x), [DATA_SEP], [EMPTY_STR]);
            string id = llList2String(params, 0);
            key texture = (key)llList2String(params, 1);
                                 
            //do something

            llSetLinkTexture(1, id#1, ALL_SIDES);
            llSetLinkTexture(2, id#2, ALL_SIDES);
            
        }
    }
}

I suspect I will have to do some flow control to get it to work after //do something, or is there a simpler way to pick the 'id' by number? Right now I can only figure out how to pick the id, being "tex_1" and "tex_2" by name becuase I know them, but I don''t know how to use the 'texture' UUID corresponding to it's 'id', if that makes any sense ?...

Link to comment
Share on other sites

Even I have a little trouble following the logic in that listen event. Why the loop? Why two lists? (I know functionally why, but why.)

Assuming this was your sending script:

key texture_A = "3d80799c-de95-11e8-9f32-f2801f1b9fd1";
key texture_B = "3d807c12-de95-11e8-9f32-f2801f1b9fd1";
integer channel = 0;

default
{
    touch_start(integer total_number)
    {
        // The keys will be separated by a single space.
        llWhisper(channel, (string)texture_A + " " + (string)texture_B);
    }
}

Your receiver script could be much simpler:

integer channel = 0;

default
{
    state_entry()
    {
        llListen(channel, "", "", "");
    }
    
    listen(integer channel, string name, key id, string message)
    {
        // Make sure the message is coming from something with the same owner.
        if(llGetOwnerKey(id) == llGetOwner())
        {
            // Parse the message by separating it by spaces.
            //  (The spaces will not be in the list.)
            list textures = llParseString2List(message, [" "], []);
            
            // This is how you access the textures.
            // You don't need to save them into a variable.
            key texture_A = llList2Key(textures, 0);
            key texture_B = llList2Key(textures, 1);
            
            // llSetLinkTexture
            // ...
        }
    }
}

Even if your original message still had the tex_1 and tex_2 parts:

// message: "tex_1 uuid tex_2 uuid"

list textures = llParseString2List(message, [" "], []);
// list: ["tex_1", "uuid", "tex_2", "uuid"]

// This is how you access the textures.
key texture_A = llList2Key(textures, 1);
key texture_B = llList2Key(textures, 3);
// ..because lists start from 0.
// 0 is "tex_1", 2 is "tex_2"

 

Edited by Wulfie Reanimator
  • Thanks 1
Link to comment
Share on other sites

1 hour ago, Wulfie Reanimator said:

But an odd/irrational way to do it. I would simply..

Indeed ? but thank you for this, I get whats going on now! Simple and elegant, you deserve a medal ?!

I'm posting an annotated result that does what I wanted here, so others who have the same issue can benefit from this as well ??! Sharing is caring~

This script lets you update textures on a link-set from an applier.

Sender

Place this script inside your sender. This is a simple example of an object you click on.

integer MyChannel;
key MyOwner;

// Your texture UUIDs go here, followed by a space to seperate them at the reciever.
// Add more textures here if needed, following the pattern.
string tex_1 = "a8aae143-39dd-49d6-909c-7640619e2b3b ";
string tex_2 = "6debb190-2d88-454b-bb8d-7ea6e046eb79 ";


default
{
    state_entry()
    {
	// Security so you dont effect other users objects, or they yours.
	MyOwner = llGetOwner();
	MyChannel = 0x80000000 | (integer)("0x"+(string)MyOwner);
    }

    touch_start(integer total_number)
    {
	// Sends your UUIDs, add more (string)tex_# if needed.
	lWhisper(MyChannel, (string)tex_1 + (string)tex_2;
    }
}

Receiver

Place this script inside the object you want to change textures on.

integer MyChannel;
key MyOwner;

default
{
    state_entry()
    {
        MyOwner = llGetOwner();
        MyChannel = 0x80000000 | (integer)("0x"+(string)MyOwner);
        llListen(MyChannel,"",NULL_KEY,"");
    }
    
    listen(integer channel, string name, key id, string message)
    {
        if(llGetOwnerKey(id) == llGetOwner())
        {
            // Parse the message by separating it by spaces.
            // The spaces will not be in the list.
            list textures = llParseString2List(message, [" "], []);
            
            // This is how you access the textures.
            // First UUID.
            key tex_1 = llList2Key(textures, 0);
            // Second UUID.
            key tex_2 = llList2Key(textures, 1);
            
            // Applies the texture to a specified link, tex_1 being the first UUID recieved and so on, to desired face.
            llSetLinkTexture(1, tex_1, ALL_SIDES);
            llSetLinkTexture(2, tex_2, ALL_SIDES);
        }
    }
}

Let me know any blatant errors and I will fix this post.

Edited by Elfie Erin
Link to comment
Share on other sites

@Wulfie Reanimator

My first point to the suggestion was to not use a space (" ") to separate the values. This is a personal preference as, depending on what we are passing it could cause problems. Next it was not clear if the ids that were being passed in the first example give were needed, I assumed they were and so looked for a way to preserve and access them, thus the two lists and the loop. the first list would hold the pairs of ids & texture UUIDs (ID^UUID) while the loop would allow you access each pair and do something with it. This way also we are not coding in a limit to there being only two pairs passed.

As it seems the ID is irrelevant, and all that will be passed would be the UUID, then only one list is needed obviously, though I would still separate the UUIDs by something other than a space, would not create the constants with a space on the end, and still would code my receiver to loop through the resulting list so that I am not hard-coded to only respond to two.

Link to comment
Share on other sites

5 hours ago, Wandering Soulstar said:

@Wulfie Reanimator

My first point to the suggestion was to not use a space (" ") to separate the values. This is a personal preference as, depending on what we are passing it could cause problems. Next it was not clear if the ids that were being passed in the first example give were needed, I assumed they were and so looked for a way to preserve and access them, thus the two lists and the loop. the first list would hold the pairs of ids & texture UUIDs (ID^UUID) while the loop would allow you access each pair and do something with it. This way also we are not coding in a limit to there being only two pairs passed.

As it seems the ID is irrelevant, and all that will be passed would be the UUID, then only one list is needed obviously, though I would still separate the UUIDs by something other than a space, would not create the constants with a space on the end, and still would code my receiver to loop through the resulting list so that I am not hard-coded to only respond to two.

I wouldn't generally go for space-separated values either, but that is why I mentioned llCSV2List. It parses very cleanly and doesn't break things like vectors, which have commas in them. My example was limited to spaces because OP's code used it and it let me use llParseString2List like you did. It was the most familiar way to give the example. My examples are not limited to only two values either, everything is stored into a list.

I believe the best way to give an example is to give the simplest solution, as in only what is needed. It can then be expanded from there. Putting global variables or a loop in your example (especially without any comments or explanation) is confusing and might make someone think that it's necessary.

Also, even in your example, the code would be functionally identical if you removed all references to EMPTY_STR because llParseString2List doesn't need it it work properly. There's also a typo in your code so it doesn't even compile. All given examples should be tested to make sure they can be tested by others.

list params = llParseString2List(llList2String(pairs, x), [DATA_SEP], {EMPTY_STR]));
Edited by Wulfie Reanimator
Link to comment
Share on other sites

@Wulfie Reanimator

Good points all Wulfie. Particularly in regards to the comments and testing. Comments have been my weak point when I code for the last 30 years ? .. and should have checked that it compiled.

In regards to the use of EMPTY_STR, again, correct in that I should have left that out. Just so used to using it now that I forget. Started back in the pre-mono days when it helped save memory, and kept it up as it ensures I don't pass a space by accident.

Thanks for the feedback!

  • Like 1
Link to comment
Share on other sites

A possibly easier way of sending and receiving data is using the LSL JSON functions http://wiki.secondlife.com/wiki/Json_usage_in_LSL

Then you could send data something like:

string tex_1 = "a8aae143-39dd-49d6-909c-7640619e2b3b";
string tex_2 = "6debb190-2d88-454b-bb8d-7ea6e046eb79";

string output = llList2Json(JSON_OBJECT, [
	"tex_1", tex_1,		// key value pair
	"tex_2", tex_2		// key value pair
]);

// Output now looks like this:
"{\"tex_1\":\"a8aae143-39dd-49d6-909c-7640619e2b3b\",\"tex_2\":\"6debb190-2d88-454b-bb8d-7ea6e046eb79\"}"

Then on the reading end:

key input_tex_1 = llJsonGetValue(message, ["tex_1"]);	// Get the tex_1 value from the JSON object string
key input_tex_2 = llJsonGetValue(message, ["tex_2"]);	// Get the tex_2 value from the JSON object string

// Make sure the keys are valid keys before setting
if( input_tex_1 )
	llSetLinkTexture(1, tex_1, ALL_SIDES);
if( input_tex_2 )
    llSetLinkTexture(2, tex_2, ALL_SIDES);

A benefit of learning how to use JSON is that it's used in a vast amount of languages.

Edited by Jasdac Stockholm
  • Like 1
Link to comment
Share on other sites

You are about to reply to a thread that has been inactive for 1985 days.

Please take a moment to consider if this thread is worth bumping.

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
 Share

×
×
  • Create New...