Jump to content

HOW WOULD I TURN THIS TEXTURE CHANGER INTO A LINKED SET?


Pixels Sideways
 Share

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

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

Recommended Posts

HIYA:

I've been trying to mod this script to do linked sets.  

So far my mod had not worked. 

What exactly and where do I add the inked set code?

Thank you.

xo

pixels

 

 


default
{
    state_entry()
    {
        llSetText("Avatar Texture Bundle", <0,1,0>,1);
        llSetTimerEvent(5.0);
    }
    timer()
    {
        integer number = llGetInventoryNumber(INVENTORY_TEXTURE);
        float rand = llFrand(number);
        integer choice = (integer)rand;
        string name = llGetInventoryName(INVENTORY_TEXTURE, choice);
        llSetTexture(name, 4);
    }
}
// END //

 

Link to comment
Share on other sites

By "linked set", do you mean "a set of linked prims"? If so, there are two primary ways of doing things to prims in a linked set:

  1. Put multiple scripts into the individual prims. Check "Edit Linked" in your Edit tool, then click the right-arrow to iterate through the individual prims that make up an object. For each prim that you want to script, go to "Contents" and either drop-in a script, or click "New Script" then edit that script. These scripts can then use functions such as "llSetTexture" that are intended to alter the prim to which their script is attached only. You could drop a copy of the script you gave into each prim of your object, and those copies would set the textures of their prims.
  2. Just have one script, in the root prim (prim #1), and use functions which are explicitly for setting attributes of other (linked) prims. For example, use llSetLinkTexture() to alter a specified face of a specified prim: http://wiki.secondlife.com/wiki/LlSetLinkTexture

I tend to prefer approach #1. For example, I made a piece of abstract art with multiple rotating parts, and I dropped a copy of a "rotate" script into each individual prim; that script looks like so:

float angle = 0.0;
default
{
    state_entry()
    {
        llSetTimerEvent(0.04);
    }
    timer()
    {
        angle += PI/500;
        if (angle >= 2*PI) {angle = 0;}
        rotation rot = llEuler2Rot(<PI/2, angle, 3*PI/2>);
        llSetLinkPrimitiveParamsFast(LINK_THIS, [ PRIM_ROT_LOCAL , rot ]);
    }
}

I could have used just one script, and repeated the llSetLinkPrimitiveParamsFast call multiple times, but giving it a different link number each time instead of "LINK_THIS" which means "the prim to which this script is attached". But I prefer to have multiple copies of a simple script, instead of one massive script; makes maintenance easier.

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

On 10/1/2021 at 5:38 PM, Pixels Sideways said:

What exactly and where do I add the inked set code?

To demonstrate how to do that, I made a new version of my "Abstract Sculpture #2" that changes textures instead of rotating. This uses a modified version of your script to changes textures of prims 2 through 5 of a 5-prim object once each 7 seconds:


// Texture-Prims.lsl

integer number; // number of textures available.
integer choice; // texture choice #
string  name;   // texture name

// Initialize script:
init()
{
    // Get current number of textures in object's inventory:
    number = llGetInventoryNumber(INVENTORY_TEXTURE);

    // Trigger "timer" event once each 7 seconds:
    llSetTimerEvent(7);
}

default
{
    state_entry()
    {
        init();
    }

    // Reset script on owner change or inventory change:
    changed (integer what)
    {
        if ( (what & CHANGED_OWNER) || (what & CHANGED_INVENTORY) )
        {
            llResetScript(); // Invokes init() via state_entry.
        }
    }

    // Reset script on rez:
    on_rez(integer StartParameter)
    {
        llResetScript(); // Invokes init() via state_entry.
    }

    // Timer event; occurs once each 7 seconds:
    timer()
    {
        // Re-texture link 2:
        choice = (integer)llFrand(number);
        name = llGetInventoryName(INVENTORY_TEXTURE, choice);
        llSetLinkTexture(2, name, 0);

        // Re-texture link 3:
        choice = (integer)llFrand(number);
        name = llGetInventoryName(INVENTORY_TEXTURE, choice);
        llSetLinkTexture(3, name, 0);

        // Re-texture link 4:
        choice = (integer)llFrand(number);
        name = llGetInventoryName(INVENTORY_TEXTURE, choice);
        llSetLinkTexture(4, name, 0);

        // Re-texture link 5:
        choice = (integer)llFrand(number);
        name = llGetInventoryName(INVENTORY_TEXTURE, choice);
        llSetLinkTexture(5, name, 0);
    }
}

 

Link to comment
Share on other sites

That's a cool script for specifically changing each prim in a linked set and def can be fun to play with.

What I am seeking is simpler.

My script above is a simple texture change script that auto change the texture via a timer  

It is for a single prim.

Since I want all the prims and their all faces in a linked set to change their textures at the same time to the same texture, I would need to add the set linked set. 

I did add a linked set command but it gave me an error message so I took it out. 

I don't know exactly where to add the linked set command and what exactly I need to follow it with so it works correctly.

Thank you. 

 

 

Edited by Pixels Sideways
Link to comment
Share on other sites

34 minutes ago, Pixels Sideways said:

I did add a linked set command but it gave me an error message so I took it out. I don't know exactly where to add the linked set command and what exactly I need to follow it with so it works correctly.

 

I'm not sure what you mean by "linked set command". Linden Scripting Language doesn't have "commands". It has "functions". Is that what you mean? Nearly all of the functions in LSL can be used in conjunction with "linked sets" of prims. But there is no function called "llLinkedSet". So, exactly what function did you use, and exactly what error message did you get? I can't troubleshoot code you're not giving, so can you be more specific as to what you mean?

If you're asking how to link prims together, that's done using the "Link" button on your edit tool. First right-click the prim you want to be the highest-numbered prim and select "Edit". Then shift-click the next-highest, then the next-highest, then shift-click the prim you want to be #1 last. Then click "Link" and they'll all become a single object consisting of "a set of linked prims", or a "linked set" for short. Then you could use a script similar to the one I just gave to alter textures on faces of the individual prims of your object.

Link to comment
Share on other sites

On 10/1/2021 at 5:38 PM, Pixels Sideways said:

...linked sets...

Check your IM inbox; I just gave you a free object. 🙂 The object consists of a set of 5 linked prims. Prim #1 (or "root") contains a script which alters texture of the other 4 prims. I created the object via the method I described in my previous comment (ie, I edited prim 5, then shift-clicked prims 4,3,2,1, then clicked "Link"). You can use this to practice unlinking and linking prims and using a script in one prim to change texture on all the others.

Link to comment
Share on other sites

1 hour ago, Pixels Sideways said:

I want all the prims and their all faces in a linked set to change their textures at the same time to the same texture

Depending on what type of prims you have, that may not be what you actually want, as some of the faces may not even be visible. For example, in the snowman I gave you, there is only 1 face per prim, face 0, because they're all spheres (except for root which is box).

But yes, it's even simpler to change all visible faces to the same texture at the same time:


// Texture-Prims-Same.lsl

integer number; // number of textures available.
integer choice; // texture choice #
string  name;   // texture name

// Initialize script:
init()
{
    // Get current number of textures in object's inventory:
    number = llGetInventoryNumber(INVENTORY_TEXTURE);

    // Trigger "timer" event once each 7 seconds:
    llSetTimerEvent(7);
}

default
{
    state_entry()
    {
        init();
    }

    // Reset script on owner change or inventory change:
    changed (integer what)
    {
        if ( (what & CHANGED_OWNER) || (what & CHANGED_INVENTORY) )
        {
            llResetScript(); // Invokes init() via state_entry.
        }
    }

    // Reset script on rez:
    on_rez(integer StartParameter)
    {
        llResetScript(); // Invokes init() via state_entry.
    }

    // Timer event; occurs once each 7 seconds:
    timer()
    {
        // Select a texture:
        choice = (integer)llFrand(number);
        name = llGetInventoryName(INVENTORY_TEXTURE, choice);

        // Re-texture link 2:
        llSetLinkTexture(2, name, 0);

        // Re-texture link 3:
        llSetLinkTexture(3, name, 0);

        // Re-texture link 4:
        llSetLinkTexture(4, name, 0);

        // Re-texture link 5:
        llSetLinkTexture(5, name, 0);
    }
}

 

Link to comment
Share on other sites

I figured it out.  This works:

 

default
{
    state_entry()
    {
        llSetTimerEvent(10.0);
    }
    timer()
    {
        integer number = llGetInventoryNumber(INVENTORY_TEXTURE);
        float rand = llFrand(number);
        integer choice = (integer)rand;
        string name = llGetInventoryName(INVENTORY_TEXTURE, choice);
        llSetLinkTexture(LINK_SET, name, ALL_SIDES);
    }
}
// END //

 

Thank you for the variations.  And the script object samples.  Your script will be helpful for changing the textures of specific prime in a linked set.  I look forward to playing with it. 

Link to comment
Share on other sites

2 hours ago, Pixels Sideways said:

llSetLinkTexture(LINK_SET, name, ALL_SIDES);

Ah, you meant "LINK_SET", not "linked sets". You should have said so! Those are two completely different things! Casing and spacing and punctuation are not optional or interchangeable or unimportant in any computer programming language, LSL included.

Also, "LINK_SET" would not have come to my mind, because you kept asking about "commands" (I assume you mean "functions"), not constants (which is what "LINK_SET" is).

"LINK_SET", as any identifier consisting only of UPPER_CASE_LETTERS_AND_UNDERSCORES, in any computer programming language, is not a "command" or a function; it's a mnemonic for an integer. LSL calls such mnemonics "constants", but most other languages call them other things (such as "identifiers" or "macros").

Specifically, "LINK_SET" is just a mnemonic for the integer -1. In the context in which it's used, namely the function (or "command" if you prefer) llSetLinkTexture, the constant "LINK_SET" means "all prims", just as the constant "LINK_THIS" means "current prim only" and the constant "LINK_ROOT" means "root prim only". More info on this can be found here:

http://wiki.secondlife.com/wiki/LlSetLinkTexture

In the context of an object with 3 prims numbered 1,2,3, with each prim having 3 faces numbered 0,1,2 the following source code:

llSetLinkTexture(LINK_SET, name, ALL_SIDES);

is actually just a shorthand for the following source code, which would compile to the same bytecode and do exactly the same thing:

llSetLinkTexture(1, name, 0);
llSetLinkTexture(1, name, 1);
llSetLinkTexture(1, name, 2);
llSetLinkTexture(2, name, 0);
llSetLinkTexture(2, name, 1);
llSetLinkTexture(2, name, 2);
llSetLinkTexture(3, name, 0);
llSetLinkTexture(3, name, 1);
llSetLinkTexture(3, name, 2);

I agree, the former is much shorter and more understandable than the latter. And it has the advantage that if number-of-prims or number-of-sides-per-prim changes, "llSetLinkTexture(LINK_SET, name, ALL_SIDES);" doesn't have to change, whereas the other version would have to be completely rewritten.

In any case, I'm glad you figured out this specific problem, and I hope this comment helps you to also understand the more-general principles involved (eg, difference between functions and constants, usage of constants to tailor behavior of functions, etc).

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

18 hours ago, LoneWolfiNTj said:

In the context of an object with 3 prims numbered 1,2,3, with each prim having 3 faces numbered 0,1,2 the following source code:

llSetLinkTexture(LINK_SET, name, ALL_SIDES);

is actually just a shorthand for the following source code, which would compile to the same bytecode and do exactly the same thing:

llSetLinkTexture(1, name, 0);
llSetLinkTexture(1, name, 1);
llSetLinkTexture(1, name, 2);
llSetLinkTexture(2, name, 0);
llSetLinkTexture(2, name, 1);
llSetLinkTexture(2, name, 2);
llSetLinkTexture(3, name, 0);
llSetLinkTexture(3, name, 1);
llSetLinkTexture(3, name, 2);

In case it confuses anybody, those two bits of LSL would not "compile to the same bytecode" despite having the same effect in an object with 3 links each with 3 faces; that's because they don't do it the same way. (Adding a link or a face in the Build Tool would demonstrate that difference without recompiling the scripts.) Also, the single function call will be much more efficient, executing the entire texture change in a single simulation frame and with fewer object update messages to the viewer. To generalize, whenever there's a choice between doing work in LSL or inside a library function call, doing it in the library will have a big performance advantage. (Pre-Mono, that advantage was huge because LSL execution was so slow.)

On 10/1/2021 at 11:36 PM, LoneWolfiNTj said:

By "linked set", do you mean "a set of linked prims"? If so, there are two primary ways of doing things to prims in a linked set:

  1. Put multiple scripts into the individual prims. [...]
  2. Just have one script, in the root prim (prim #1), and use functions which are explicitly for setting attributes of other (linked) prims. For example, use llSetLinkTexture() to alter a specified face of a specified prim: http://wiki.secondlife.com/wiki/LlSetLinkTexture

I tend to prefer approach #1.[...] But I prefer to have multiple copies of a simple script, instead of one massive script; makes maintenance easier.

Sorry to pick on this, but this preference isn't universal: I much prefer to keep to as few scripts as possible. There are special cases when it's better to spread scripts among multiple links, but from an efficiency standpoint fewer scripts will (almost always) win, often by a lot. To be precise, it's script time that will be reduced whereas script memory may be comparable because within a sim, multiple copies of the same compiled script will share one copy of the code memory (not data memory, of course, and not if the script copies are compiled individually). The script time savings are in part an artefact of how the scheduler works, so all scripts—even completely idle scripts—burn a little processor time every simulation frame.

  • Like 3
Link to comment
Share on other sites

8 hours ago, Qie Niangao said:

...would not "compile to the same bytecode" despite having the same effect ... the single function call will be much more efficient, executing the entire texture change in a single simulation frame and with fewer object update messages to the viewer...

Looks like I jumped to an unwarranted conclusion in that regard. In fact, I'll amend my comment for accuracy. Oops, I can't; seems there's an edit time limit on this site. (24Hr, or thereabouts?)

8 hours ago, Qie Niangao said:

I much prefer to keep to as few scripts as possible

I use both methods ("centralized" & "decentralized", if you will), but my own personal preference is the decentralized approach, other things being equal. I guess I just like the idea of having each part of an object have a mind of its own.

That being said, I just got through converting an object of mine to the centralized approach, for time synchronization purposes, so I'm not averse to that approach if I see a reason to use it.

That's a fun thing about LSL: like Perl, usually There Is More Than One Way To Do It. (That's literally the motto of the Perl programming language.)

Edited by LoneWolfiNTj
Link to comment
Share on other sites

On 10/3/2021 at 4:29 AM, Pixels Sideways said:

llSetLinkTexture(LINK_SET, name, ALL_SIDES);

Ok, I changed my Abstract Sculpture from the way I was doing it (changing each prim with a separate function call) to that, and wow, what an improvement! The prims change texture much faster and all at the same time! (Whereas before, they were changing one at a time, and slowly.) So, in the process of me trying to answer your question, you taught me something new and useful.

Here, have a free full-perms copy of my Abstract Sculpture #4 (using a similar line of code: "llSetLinkTexture(LINK_ALL_CHILDREN, name, 0);") as a thank-you gift:

https://marketplace.secondlife.com/p/Abstract-Sculpture-4/22761298

Link to comment
Share on other sites

On 10/4/2021 at 2:07 AM, Qie Niangao said:

the single function call will be much more efficient

Aye, I just found that out a couple days ago. I was changing 4 prims in an object to the same texture using 4 function calls, and they changed one-at-a-time, slowly; but when I replaced those 4 calls with "llSetLinkTexture(LINK_ALL_CHILDREN, name, 0);", they changed all-at-once and quickly. So, ya, not the same bytecode, and really not even the same behavior as the single-call version is much faster.

  • Like 1
Link to comment
Share on other sites

You are about to reply to a thread that has been inactive for 942 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...