Jump to content
Rolig Loon

Preloading Slide Viewer

Recommended Posts

This basic preloading slide viewer was introduced by Sendao Goodman in 2007 and was in the LSL wiki's Scripting Library until sometime in 2011.  I have encountered several versions of it across Second Life, and have modified it myself many times for specific purposes. 

The operating principle of the unit is simple. Each slide in the unit's Contents is shown in turn on one of five faces of the root prim, all of which are colored black so that the slides are not visible.  By the time a slide is finally moved onto the one white face of the prim, it has been "preloaded" for all nearby avatars, so it rezzes instantly. 

This version is designed for a three-prim display unit.  It defaults to auto-advance mode with a cycle of 10 seconds, but the owner can change the speed or turn it off with a simple dialog menu. Anyone can also move to the next slide (or the previous one) manually by clicking on the viewer's "forward" or "reverse" button.

 

// PRE-LOAD and VIEW SLIDES
// Script by Sendao Goodman, 2007
// Modified by Rolig Loon 2009, 2010, 2011, 2012

//--------------------------

// Installation note: This is to be used in a linked 3-prim object.  
//      By default, slides show on face 2 of the root prim (the screen). 
//      One child prim, which must be named "forward", is the forward button. 
//      The other one, which must be named "reverse", is the reverse button. 

//--------------------------
// Drop this script and any images into the root prim and it will cycle every 10 seconds

// Owner: Touch the root prim (viewer screen) to change slide speed or turn it off.
// All Users: Touch the "forward" or "reverse" prim to change slides manually

float gPace = 10.0; 
integer gReload;
list gPics;
integer gLen;
integer gSlide;
integer gChan;
integer gLsn;

loadPictures()
{
    gPics=[];
    integer i = llGetInventoryNumber(INVENTORY_TEXTURE);
    if( i > 0 ) 
    {
        while( i > 0 ) 
        {
            i--;
            gPics += [llGetInventoryName(INVENTORY_TEXTURE,i)];
        }
        gLen = (gPics !=[]);
        llOwnerSay((string)gLen+" pictures loaded");
        gPics = llListSort( gPics, 1, TRUE ); // put them in order
        llOwnerSay("Slides are now set to advance every "+ (string)gPace + " seconds.");
        llSetTimerEvent(gPace);
    }
    else if( gReload == 0 ) 
    {
        llSetTimerEvent(0.0);
    }
}

string getSlide(integer slide)
{
    return llList2String( gPics, (slide+gLen)%gLen );
}

default
{
    on_rez(integer sp)
    {
        loadPictures();
        gSlide=0;
        gReload=0;
    }
    
    state_entry()
    {
        gChan = (integer)("0xF" + llGetSubString(llGetKey(),0,6));
        loadPictures();
        gSlide=0;
        gReload=0;
        llSetLinkColor(LINK_THIS, <0,0,0>, ALL_SIDES );
        llSetLinkColor(LINK_THIS, <1,1,1>, 2 ); // Slides displayed on this face are visible.  All other faces are colored black
    }
    
    listen(integer channel, string name, key id, string msg)
    {
        llListenRemove(gLsn);
        if(msg == "OFF")
        {
            gPace = 0.0;
        }
        else
        {
            gPace += (float)msg;
            if (gPace <= 0.0)
            {
                gPace = 0.0;
            }
        }
        llSetTimerEvent(gPace);
        llOwnerSay("Slides are now set to advance every "+ (string)gPace + " seconds.");
    }
    
    changed( integer ch )
    {
        if( ch & CHANGED_INVENTORY ) 
        {
            gReload = 1;
            llSetTimerEvent(2.0);
        }
    }

    touch_start(integer num)
    {
        if (llDetectedLinkNumber(0) == 1) // The root prim (viewer screen)
        {
            if (llDetectedKey(0) == llGetOwner()) 
            {
                gLsn = llListen(gChan,"","","");
                llDialog(llGetOwner()," \n\nSlides now advance every "+(string)gPace+ " seconds. Select a new speed.",["+2","+5","OFF","-2","-5"],gChan);
            }
        }    
        else if (llGetLinkName(llDetectedLinkNumber(0)) == "forward") //The forward button
        {
            if( gLen > 0 ) 
            {
                integer i=6;
                while( i > 0 ) 
                {
                    i--;
                    llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_TEXTURE,i,getSlide(gSlide+(i-2)),<1.0,1.0,0.0>,ZERO_VECTOR,0.0]);
                }
                gSlide = (gSlide+1)%gLen;
            }
        }
        else if (llGetLinkName(llDetectedLinkNumber(0)) == "reverse")  // The reverse button
        {
            if( gLen > 0 ) 
            {
                integer i=6;
                while( i > 0 ) 
                {
                    i--;
                    llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_TEXTURE,i,getSlide(gSlide+(i-3)),<1.0,1.0,0.0>,ZERO_VECTOR,0.0]);
                }
                gSlide = (gSlide-1)%gLen;
            }
        }
    }
    
    timer()
    {
        if( gReload == 1 ) 
        {
            gReload = 0;
            loadPictures();
            llSetTimerEvent(gPace);
        }
        else
        {
            integer i=6;
            while( i > 0 ) 
            {
                i--;
                llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_TEXTURE,i,getSlide(gSlide+(i-2)),<1.0,1.0,0.0>,ZERO_VECTOR,0.0]);
            }
            gSlide = (gSlide+1)%gLen;
        }
    }
}

 

  • Like 1
  • Thanks 1

Share this post


Link to post
Share on other sites

A script for animations would be different in some significant ways.  For one thing, you'd need to request permissions and, of course, identify the av to animate.  You wouldn't need to preload animations, so all of that business could be stripped out of this script.  By the time you're done, it would have been easier and a lot faster to just sit down and write a proper animation script. :smileywink:

  • Like 1

Share this post


Link to post
Share on other sites
On 11/5/2012 at 8:53 AM, Rolig Loon said:

This basic preloading slide viewer was introduced by Sendao Goodman in 2007 and was in the LSL wiki's Scripting Library until sometime in 2011.  I have encountered several versions of it across Second Life, and have modified it myself many times for specific purposes. 

The operating principle of the unit is simple. Each slide in the unit's Contents is shown in turn on one of five faces of the root prim, all of which are colored black so that the slides are not visible.  By the time a slide is finally moved onto the one white face of the prim, it has been "preloaded" for all nearby avatars, so it rezzes instantly. 

This version is designed for a three-prim display unit.  It defaults to auto-advance mode with a cycle of 10 seconds, but the owner can change the speed or turn it off with a simple dialog menu. Anyone can also move to the next slide (or the previous one) manually by clicking on the viewer's "forward" or "reverse" button.

 


// PRE-LOAD and VIEW SLIDES
// Script by Sendao Goodman, 2007
// Modified by Rolig Loon 2009, 2010, 2011, 2012

//--------------------------

// Installation note: This is to be used in a linked 3-prim object.  
//      By default, slides show on face 2 of the root prim (the screen). 
//      One child prim, which must be named "forward", is the forward button. 
//      The other one, which must be named "reverse", is the reverse button. 

//--------------------------
// Drop this script and any images into the root prim and it will cycle every 10 seconds

// Owner: Touch the root prim (viewer screen) to change slide speed or turn it off.
// All Users: Touch the "forward" or "reverse" prim to change slides manually

float gPace = 10.0; 
integer gReload;
list gPics;
integer gLen;
integer gSlide;
integer gChan;
integer gLsn;

loadPictures()
{
    gPics=[];
    integer i = llGetInventoryNumber(INVENTORY_TEXTURE);
    if( i > 0 ) 
    {
        while( i > 0 ) 
        {
            i--;
            gPics += [llGetInventoryName(INVENTORY_TEXTURE,i)];
        }
        gLen = (gPics !=[]);
        llOwnerSay((string)gLen+" pictures loaded");
        gPics = llListSort( gPics, 1, TRUE ); // put them in order
        llOwnerSay("Slides are now set to advance every "+ (string)gPace + " seconds.");
        llSetTimerEvent(gPace);
    }
    else if( gReload == 0 ) 
    {
        llSetTimerEvent(0.0);
    }
}

string getSlide(integer slide)
{
    return llList2String( gPics, (slide+gLen)%gLen );
}

default
{
    on_rez(integer sp)
    {
        loadPictures();
        gSlide=0;
        gReload=0;
    }
    
    state_entry()
    {
        gChan = (integer)("0xF" + llGetSubString(llGetKey(),0,6));
        loadPictures();
        gSlide=0;
        gReload=0;
        llSetLinkColor(LINK_THIS, <0,0,0>, ALL_SIDES );
        llSetLinkColor(LINK_THIS, <1,1,1>, 2 ); // Slides displayed on this face are visible.  All other faces are colored black
    }
    
    listen(integer channel, string name, key id, string msg)
    {
        llListenRemove(gLsn);
        if(msg == "OFF")
        {
            gPace = 0.0;
        }
        else
        {
            gPace += (float)msg;
            if (gPace <= 0.0)
            {
                gPace = 0.0;
            }
        }
        llSetTimerEvent(gPace);
        llOwnerSay("Slides are now set to advance every "+ (string)gPace + " seconds.");
    }
    
    changed( integer ch )
    {
        if( ch & CHANGED_INVENTORY ) 
        {
            gReload = 1;
            llSetTimerEvent(2.0);
        }
    }

    touch_start(integer num)
    {
        if (llDetectedLinkNumber(0) == 1) // The root prim (viewer screen)
        {
            if (llDetectedKey(0) == llGetOwner()) 
            {
                gLsn = llListen(gChan,"","","");
                llDialog(llGetOwner()," \n\nSlides now advance every "+(string)gPace+ " seconds. Select a new speed.",["+2","+5","OFF","-2","-5"],gChan);
            }
        }    
        else if (llGetLinkName(llDetectedLinkNumber(0)) == "forward") //The forward button
        {
            if( gLen > 0 ) 
            {
                integer i=6;
                while( i > 0 ) 
                {
                    i--;
                    llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_TEXTURE,i,getSlide(gSlide+(i-2)),<1.0,1.0,0.0>,ZERO_VECTOR,0.0]);
                }
                gSlide = (gSlide+1)%gLen;
            }
        }
        else if (llGetLinkName(llDetectedLinkNumber(0)) == "reverse")  // The reverse button
        {
            if( gLen > 0 ) 
            {
                integer i=6;
                while( i > 0 ) 
                {
                    i--;
                    llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_TEXTURE,i,getSlide(gSlide+(i-3)),<1.0,1.0,0.0>,ZERO_VECTOR,0.0]);
                }
                gSlide = (gSlide-1)%gLen;
            }
        }
    }
    
    timer()
    {
        if( gReload == 1 ) 
        {
            gReload = 0;
            loadPictures();
            llSetTimerEvent(gPace);
        }
        else
        {
            integer i=6;
            while( i > 0 ) 
            {
                i--;
                llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_TEXTURE,i,getSlide(gSlide+(i-2)),<1.0,1.0,0.0>,ZERO_VECTOR,0.0]);
            }
            gSlide = (gSlide+1)%gLen;
        }
    }
}

 

Thanks for this script! but what if i would like to remove two objects forward/reverse option and keep only one object slideshow/texture preload and speed menu? What should I remove and keep?

Share this post


Link to post
Share on other sites

I son't understand exactly what you are asking, but if you don't want forward and reverse buttons, just remove them.  You don't need to modify the script at all. The two else if blocks of code in the touch_start event will never be used then, since no one will ever touch a link named "forward" or "reverse".

  • Thanks 1

Share this post


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

I son't understand exactly what you are asking, but if you don't want forward and reverse buttons, just remove them.  You don't need to modify the script at all. The two else if blocks of code in the touch_start event will never be used then, since no one will ever touch a link named "forward" or "reverse".

Hello! thanks for the answer! I mean I want the script to work not for the linkset of the three objects, but only for one object. I tried it, but unfortunately it works a bit strange. Different textures are displayed on several sides at once, which is not happen in the case if you use a linkset. and there is no menu to change the speed...

Share this post


Link to post
Share on other sites
23 minutes ago, Sunbleached said:

Different textures are displayed on several sides at once

That's the way it is supposed to work.  That's why all faces of the root prim are colored black except for the one face that is used as the display screen. 

24 minutes ago, Sunbleached said:

and there is no menu to change the speed...

It sounds like you have removed every prim in the linkset except for the root prim.  That's kind of unusual, but it should still work if you do that.  Just remember that the root is link #0 if there are no child prims.  You should either edit the line in touch_start to reflect that change

4 hours ago, Sunbleached said:

if (llDetectedLinkNumber(0) == 1) // The root prim (viewer screen)

or simply remove that if test altogether, since it makes no difference if you only have one prim.

  • Thanks 1

Share this post


Link to post
Share on other sites
Posted (edited)
1 hour ago, Rolig Loon said:

That's the way it is supposed to work.  That's why all faces of the root prim are colored black except for the one face that is used as the display screen. 

It sounds like you have removed every prim in the linkset except for the root prim.  That's kind of unusual, but it should still work if you do that.  Just remember that the root is link #0 if there are no child prims.  You should either edit the line in touch_start to reflect that change

or simply remove that if test altogether, since it makes no difference if you only have one prim.

Thank you again! Here's what I got. but such a question. Are black painted surfaces necessary? And can I use this script for a screen with one face (or two)?

// PRE-LOAD and VIEW SLIDES
// Script by Sendao Goodman, 2007
// Modified by Rolig Loon 2009, 2010, 2011, 2012

//--------------------------

// Installation note: This is to be used in a linked 3-prim object.  
//      By default, slides show on face 2 of the root prim (the screen). 
//      One child prim, which must be named "forward", is the forward button. 
//      The other one, which must be named "reverse", is the reverse button. 

//--------------------------
// Drop this script and any images into the root prim and it will cycle every 10 seconds

// Owner: Touch the root prim (viewer screen) to change slide speed or turn it off.
// All Users: Touch the "forward" or "reverse" prim to change slides manually

float gPace = 10.0; 
integer gReload;
list gPics;
integer gLen;
integer gSlide;
integer gChan;
integer gLsn;

loadPictures()
{
    gPics=[];
    integer i = llGetInventoryNumber(INVENTORY_TEXTURE);
    if( i > 0 ) 
    {
        while( i > 0 ) 
        {
            i--;
            gPics += [llGetInventoryName(INVENTORY_TEXTURE,i)];
        }
        gLen = (gPics !=[]);
        llOwnerSay((string)gLen+" pictures loaded");
        gPics = llListSort( gPics, 1, TRUE ); // put them in order
        llOwnerSay("Slides are now set to advance every "+ (string)gPace + " seconds.");
        llSetTimerEvent(gPace);
    }
    else if( gReload == 0 ) 
    {
        llSetTimerEvent(0.0);
    }
}

string getSlide(integer slide)
{
    return llList2String( gPics, (slide+gLen)%gLen );
}

default
{
    on_rez(integer sp)
    {
        loadPictures();
        gSlide=0;
        gReload=0;
    }
    
    state_entry()
    {
        gChan = (integer)("0xF" + llGetSubString(llGetKey(),0,6));
        loadPictures();
        gSlide=0;
        gReload=0;
        llSetLinkColor(LINK_THIS, <0,0,0>, ALL_SIDES );
        llSetLinkColor(LINK_THIS, <1,1,1>, 1 ); // Slides displayed on this face are visible.  All other faces are colored black
    }
    
    listen(integer channel, string name, key id, string msg)
    {
        llListenRemove(gLsn);
        if(msg == "OFF")
        {
            gPace = 0.0;
        }
        else
        {
            gPace += (float)msg;
            if (gPace <= 0.0)
            {
                gPace = 0.0;
            }
        }
        llSetTimerEvent(gPace);
        llOwnerSay("Slides are now set to advance every "+ (string)gPace + " seconds.");
    }
    
    changed( integer ch )
    {
        if( ch & CHANGED_INVENTORY ) 
        {
            gReload = 1;
            llSetTimerEvent(2.0);
        }
    }

    touch_start(integer num)
    {
        if (llDetectedLinkNumber(0) == 0) // The root prim (viewer screen)
        {
            if (llDetectedKey(0) == llGetOwner()) 
            {
                gLsn = llListen(gChan,"","","");
                llDialog(llGetOwner()," \n\nSlides now advance every "+(string)gPace+ " seconds. Select a new speed.",["+2","+5","OFF","-2","-5"],gChan);
            }
        }    
    }
    
    timer()
    {
        if( gReload == 1 ) 
        {
            gReload = 0;
            loadPictures();
            llSetTimerEvent(gPace);
        }
        else
        {
            integer i=6;
            while( i > 0 ) 
            {
                i--;
                llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_TEXTURE,i,getSlide(gSlide+(i-2)),<1.0,1.0,0.0>,ZERO_VECTOR,0.0]);
            }
            gSlide = (gSlide+1)%gLen;
        }
    }
}

 

Edited by Sunbleached

Share this post


Link to post
Share on other sites
Posted (edited)

@Rolig Loon

As I can say now for one face objects it works. But for example, I want to use a mesh screen with two faces. the slideshow is displayed perfectly, but on the second face the texture is replaced. Is it possible to set a specific face where this next one (as i understand) texture will be displayed? and how much is it needed?

Since the script works perfectly with one face mesh prim, what is the need to display other textures on other faces? And is it possible to disable it and how?

Edited by Sunbleached

Share this post


Link to post
Share on other sites

The whole point of preloading textures is to give them time to rez, so that by the time they are presented on the one visible face, they are clear and sharp.  If you don't care about preloading, you don't need a script like this at all.  You should just write yourself a simple texture change script and be done with it.

  • Like 1

Share this post


Link to post
Share on other sites
Posted (edited)
1 hour ago, Rolig Loon said:

The whole point of preloading textures is to give them time to rez, so that by the time they are presented on the one visible face, they are clear and sharp.  If you don't care about preloading, you don't need a script like this at all.  You should just write yourself a simple texture change script and be done with it.

I just need exactly the preloading option. So if I use the screen with one face, then the effect will not be? I will need at least two faces to see effect ? And if I use a screen with eight faces, then the preload will be faster? I'm just trying to understand the logic.

Is it possible to specify the face on which preloading will be?

Edited by Sunbleached

Share this post


Link to post
Share on other sites
Posted (edited)

Textures do not load instantly.  Depending on your graphics card and internet connection (and on what's going on in the region), it can take 20 seconds or more before a texture is rendered fully.  Preloading, then, is a strategy for displaying a texture somewhere within the viewer's draw distance long before it needs to be in shape to see with your eyes. A texture may be preloaded on any surface. It may be at any scale and may be tinted any color or set to any alpha value.  This particular script preloads several textures on hidden faces (hidden physically and also tinted black, so it's not obvious that there's anything there) and then rotates them sequentially onto the one face that is designated as the viewing screen.  By the time that a texture finally reaches the viewing screen, therefore, it has been rezzed for as much as a minute or more and should be fully rendered.  You can certainly use fewer faces than this script expects, but of course that reduces both the number of preloaded textures and the amount of time that they spend preloading.  Obviously, if you only have one face, there is no preloading at all.

As you can see in the script,

3 hours ago, Sunbleached said:

llSetLinkColor(LINK_THIS, <1,1,1>, 1 ); // Slides displayed on this face are visible. All other faces are colored black

the display screen is defined as face #1.All other faces are used for preloading, as defined in the timer event.  If you decide to use some other face as the display screen, or if you use a different number of preloading faces, you will need to rewrite the loop in the timer event to get the visible slide on the right face.

Edited by Rolig Loon
  • Thanks 1

Share this post


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

All other faces are used for preloading, as defined in the timer event. 

Thanks. Just one more question. Is it also possible to specify on which side(s) preloading will be? 

Share this post


Link to post
Share on other sites

I just answered that ...

14 minutes ago, Rolig Loon said:

All other faces are used for preloading, as defined in the timer event. 

 

  • Thanks 1

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...