FreeSlide

Back in March 2009, I released a script that implemented buffering to enable a smoother transitioning from slide to slide eliminating the lag that exists in non-buffered slide scripts.  I got alot of great feed back on that release.  Down below is a updated version which provides clickable hot-spots that allow for the left third of the screen to be used to go back one slide and the right third of the screen to be used for a slide advance.  Also added is a pop-up menu which allows the owner of the screen to set an auto-advance in number of seconds so that every X seconds, the slide presentation will advance to the next slide.  It will roll back to the first when it gets to the last.  All respects to those who have written this type of slide presentation before me.  The completed screen & script with sample slide presentation can be found at:

http://slurl.com/secondlife/SBU%20Medical%20Center/125/227/2045

(it is located on a floating platform 2045M in the sky so it is out of the way for future work down on the ground)

The updated script can be found below:

Earlier Description:

I've been to a few presentations in Second Life and most displays seem to be the same --- PowerPoint presentations that have been converted to images and then uploaded to SL, loaded into a prim, and then a script that loads image by image (slide by slide) onto one of the faces of the "screen" prim.  However, as each slide is loaded, it is obvious that the textures takes a moment to download to a client.  This results in a bit of a sync issue.  Since the presenter generally has all of the textures already on their client, the speaker moves ahead with their talk with everyone waiting for the image to download to their SL clients.  This shows as a blurry image at first that slowly rezzes until the image download is complete.

I've written a script that eliminates this "flicker/lag" issue by implementing a "double buffering" technique.  Double buffering is a method by showing one slide while the next slide is written to another location.  By the time the second slide is needed, it is already loaded and can be displayed immediately.  This can all be done with a single prim.  How?  Simple.  There are six faces on a cube.  Only one is needed for display.  In LSL scripting, each of these faces are numbered from one to six.  The script below is a typical slide presentation script with a small modification.  Instead of loading just the first slide, the first six slides are loaded, each slide to one face of the cubical prim.  Face 1 is oriented towards the audience and the prim is flattened to form a screen.  Now, whereas, the "screen" looks two dimensional, all six sides are still present.  Since the SL client doesn't know that people only care about side one, it loads all six sides and thus downloads the textures (slides) to all SL clients in the area.

When the presenter clicks on the screen, the script shifts all of the textures - 2 to 1, 3 to 2, 4 to 3, 5 to 4, 6 to 5, and then loads slide 7 into face 6.  Since the textures are already loaded by the time the presenter moves to slide 2.  The transition is immediate for all viewers.  Since there are actually 5 additional buffers, the presenter could move rapidly for up to six slides with out lagging between the slides.  Rapidly moving through seven slides would show lag on the seventh slide, but additional prims could be used  to extend this buffering.  But I think in most cases, the six sides would provide ample buffering.

Now, the fours faces that are on the sides will not show well, but the back will show one of the textures.  This may be confusing for some people.  Simply change the color of those faces to black and all textures will appear black and thus not show.

Most slides scripted slide viewer objects could be retro-fitted with this method so as to provide a more pleasant experience for audience participants.  I used the slide script below for a presentation I did March 24, 2009 at ISTE on my molecular visualization system and it worked out well.  Since there isn't a "pre-load" LSL command that I know of (similar to that of the audio preload command in LSL), using the various facets of a prim as a buffer gets around this.  The script is released under GPL.  If you want to be nice, leave my name in for credit. :-)

====== script below =======================

// FreeSlide - the Multi-buffered slide presentation script
// minimizes download time of each slide by pre-loading them to the various facets of the "screen prim"
// Script by Erich Bremer March 24, 2009
// clicking on prim advances the slide show.  Saying "B" on channel 7 makes the slide presentation go backwards by one slide. "/7b"

// Changes
// 6/23/2009 -  Added Auto-advance function
//              Added click on left edge of screen to goto previous slide and click on right side of slide to advance.  Middle third of slide brings up auto-advance menu

integer NumberOfTextures = 0;
integer CurrentTexture = 0;
integer listen_handle;
float SlideChangeWait = 0.0;
integer controlchannel = 7;


// Yes, you can hollow the prim and get another face to buffer on, but for simplicity, I left that out.

displayme() {
        llSetTexture(llGetInventoryName(INVENTORY_TEXTURE, CurrentTexture), 0);
        if (CurrentTexture+1<NumberOfTextures) {
            llSetTexture(llGetInventoryName(INVENTORY_TEXTURE, CurrentTexture+1), 1);
        } 
        if (CurrentTexture+2<NumberOfTextures) {
            llSetTexture(llGetInventoryName(INVENTORY_TEXTURE, CurrentTexture+2), 2);
        }
        if (CurrentTexture+3<NumberOfTextures) {
            llSetTexture(llGetInventoryName(INVENTORY_TEXTURE, CurrentTexture+3), 3);
        }
        if (CurrentTexture+4<NumberOfTextures) {
            llSetTexture(llGetInventoryName(INVENTORY_TEXTURE, CurrentTexture+4), 4);
        }
        if (CurrentTexture+5<NumberOfTextures) {
            llSetTexture(llGetInventoryName(INVENTORY_TEXTURE, CurrentTexture+5), 5);
        } 
    }

NextSlide() {
    if (CurrentTexture < NumberOfTextures - 1) {
            CurrentTexture++;
        } else {
            CurrentTexture = 0;
        }   
        displayme();
}

PreviousSlide() {
        if (CurrentTexture > 0) {
            CurrentTexture--;
        }
        displayme();
}
   
default
{
    state_entry()
    {
        NumberOfTextures = llGetInventoryNumber(INVENTORY_TEXTURE);
        listen_handle = llListen(controlchannel, "", llGetOwner(), "");
        displayme();

    }
   
    listen( integer channel, string name, key id, string message )
    {
        if (message == "b") {
            PreviousSlide();
        } else if (message == "n") {
            NextSlide();
        } else {
            SlideChangeWait = (float) message;
            llSetTimerEvent(SlideChangeWait);
            llResetTime();
        }    
    }


    touch_start(integer agent)
    {
        if (llDetectedKey(0) == llGetOwner()) {   
            vector touchedpos = llDetectedTouchST(0);
            if ((touchedpos.x > 0.3) && (touchedpos.x < 0.7)) {
                llDialog(llDetectedKey(0), "Please select number of seconds before an auto-advance (0 = disabled)",
                 ["0","1","2","5","10","15","20","30","45","60","120","240"], controlchannel);
            } else if (touchedpos.x <= 0.3) {
                PreviousSlide();
            } else if (touchedpos.x >= 0.7) {
                NextSlide();
            }           

        }      
    }
   
   
    timer()
    {
        NextSlide();
    }

  
    changed(integer change)
    {
        if (change & CHANGED_INVENTORY)
            llResetScript();
    }
}

============script above===================

Tags: