Navigatore di diapositive MxN

Questo è un “semplice” script uno dei primi che avevo fatto che consente di navigare delle diapositive “Multiple”, leggendole dall’inventory del “proiettore di diapositive”.
Le immagini devono terminare con xxxxx-3×3 per indicare che sono una matrice di 3 righe per 3 colonne. Lo script è molto sofisticato e consente anche di lasciare a vista le ultime diapositive viste. Inoltre consente anche di fare una ricerca e di visualizzare dei commenti sulle diapositive.


Lo script computa i parametri

integer iM=4;
integer iN=4;

float fSCALX=1;
float fSCALY=1;
float fSPANX=.5;
float fSPANY=.5;

e poi fa evolvere con la funzione next() verso l’elemento successivo. Si può semplificare per adempiere al suo scopo su una singola texture

//
// Pakkio Jan 2008, V3.0
// PowerPoint projector
//
// Textures must be made MXN and have it in their name as in <name>-MxN
// example: my texture-4x4 (multiple images can be mixed)
// for each must find <name>-MxN.txt to have one line for each slide with "|" representing newlines
// if we find a <name>-MxN-i.give this will be given to people if required
//
// script will be able to select next texture, prev texture, and will keep last 5 slides, comments, inventory for retrieving them
//
integer iDELAY=10;
integer iLISTENHANDLER=0;
integer iMENUCHANNEL;
integer iCHANNEL=100;
integer iDEBUG=0;
integer iHOVERTEXT=1;
vector  vHOVERCOLOR=<1,1,1>;
integer iMENULISTENER=0;
vector  vSTARTPOS;
string sTELEPORT="";
vector vTELEPORT;

string sINVENTORY;

string sSEARCH="";

// will be set up during reset looking at the names of each link
integer eCONTROLLER;
integer eBOARD=1;
integer iPLAY=0;



// to loop over all the textures in the inventory
integer iTEXTURE;
string sTEXTURE;
integer bENDTEXTURE;

// to loop over the comments in notecards (
string sCOMMENT;
key kCOMMENT;
integer iCOMMENT;

integer iM=4;
integer iN=4;

float fSCALX=1;
float fSCALY=1;
float fSPANX=.5;
float fSPANY=.5;

string sME="MAIN";

list lHISTORYLINK=[];
list lHISTORY=[ "","","","","" ];
list lTEXT=[ "","","","","" ];

push(string texture, vector scale, vector offset)
{
    lHISTORY=llDeleteSubList(lHISTORY,0,0)+llDumpList2String([ texture, scale, offset ],"|");
    integer i;
    for(i=0;i<5;i++)
    {
        list data=peek(i);

        llSetLinkPrimitiveParams(llList2Integer(data,0),
            [ PRIM_TEXTURE, ALL_SIDES,
            llList2String(data,1), // texture
            (vector)llList2String(data,2), // scale
            (vector)llList2String(data,3), // offset
            0.0 ]);
    }
}
push_text(string text)
{
    lTEXT=llDeleteSubList(lTEXT,0,0)+text;
}
// return [linknum, texture, scale, offset]
list peek(integer offset)
{
    return [ llList2Integer(lHISTORYLINK,2*offset+1)] + llParseStringKeepNulls(llList2String(lHISTORY,offset),["|"],[]);
}


string str_replace(string src, string from, string to)
{//replaces all occurrences of 'from' with 'to' in 'src'.
    integer len = (~-(llStringLength(from)));
    if(~len)
    {
        string  buffer = src;
        integer b_pos = -1;
        integer to_len = (~-(llStringLength(to)));
        @loop;//instead of a while loop, saves 5 bytes (and run faster).
        integer to_pos = ~llSubStringIndex(buffer, from);
        if(to_pos)
        {

            buffer = llGetSubString(src = llInsertString(llDeleteSubString(src, b_pos -= to_pos, b_pos + len), b_pos, to), (-~(b_pos += to_len)), 0x8000);
            jump loop;
        }
    }
    return src;
}

// use channel 10 to debug (no cluttering of 0 channel, easy to listen with mystitool)
debug(string str)
{
    if(iDEBUG==1) llSay(10,str);
}

string dumpList(list lst)
{
    return llDumpList2String(lst,"|");
}
list parseString(string str)
{
    return llParseStringKeepNulls(str,["|"],[]);
}
//
// Will display the xxx|yyyy|zzz text loading <> color and @ for giving inventory
//
info(string str)
{
    sINVENTORY=""; string vcolor="<1,1,1>";
    list lst=llParseStringKeepNulls(str,["|"],[]);
    integer goon=1;
    while(goon==1)
    {
        string piece=llList2String(lst,0); string first=llGetSubString(piece,0,0);
        if(first=="@" || first=="<")
        {
            string rest=llGetSubString(piece,1,-1);
            if(first=="@")
            {
                sINVENTORY=rest; debug("Inventory: "+sINVENTORY);
                lst+="==>"+sINVENTORY;
            }
            if(first=="<")
            {
                vcolor=piece;
                debug("Color changed to. "+vcolor);
            }
            lst=llDeleteSubList(lst,0,0);
        }
        else goon=0;
    }
    str=llDumpList2String(lst,"n");

    llMessageLinked(LINK_SET,1,dumpList( [ sME, "TEXT", "SHOW", str, vcolor ]),"");
}

// utility variables

vector vPOS; // starting point is the last one so that next will go on the first 😉
integer iENABLED=1;     // autoslideshow enabled
integer iDIRECTION=1;   // direction on next
integer iCNT=0;         // counting from 1
integer iPOKE = FALSE;  // no dblclick




setBoard()
{
    list parms=[ PRIM_TEXTURE,0 , sTEXTURE, <fSCALX, fSCALY,0.0>, vPOS, 0.0 ];
    debug("SetPrimitiveParams: "+llList2CSV(parms));
    llSetPrimitiveParams(parms);
}
//
// go to next images in the grid
//
// order is from left to right and from top to bottom (like reading)
// Quite intuitive
//
next ()
{
    debug("doing next");
    iDIRECTION=1;
    vPOS.x=vPOS.x+fSCALX;
    if(vPOS.x>fSPANX){
        debug("vPOS.x over fSPANX");
        vPOS.x=-fSPANX;
        vPOS.y=vPOS.y-fSCALY;

        if(vPOS.y<-fSPANY)
        {
            debug("vPOS.y over fSPANY");
            vPOS.y=fSPANY;
        }
    }
    iCNT++;
    if(iCNT>(iM*iN))
    {
        debug("iCNT over "+(string)(iM*iN));
        iTEXTURE++;
        changeTexture(); // will go on next texture
        return;
    }




    if(sSEARCH=="")
    {
        setBoard();
        push( sTEXTURE, <fSCALX, fSCALY, 0>, vPOS);
    }
    //info((string)iCNT +"/"+(string)(iM*iN)+"/"+(string)(iTEXTURE+1));
    //llSetText((string)cnt    +"/"+(string)NUM+"nx="+(string)pos.x+"-y="+(string)pos.y,<1,0,0>,1);

    if(bENDTEXTURE==0)
    {
       iCOMMENT++; sTELEPORT="";

       if(llGetInventoryType(sCOMMENT)!=INVENTORY_NOTECARD)
       {
        // check if this is a teleport URL xxxxxx,sim (x,y,z)
        // find "("
        integer i=llSubStringIndex(sTEXTURE,"(");
        if(i>=0)
        {
            integer j=llSubStringIndex(sTEXTURE,")");
            if(j>=0)
            {
                // look for first ","
                integer k=llSubStringIndex(sTEXTURE,",");

                sTELEPORT=llStringTrim(llGetSubString(sTEXTURE,k+1,i-1),STRING_TRIM);
                string position=llStringTrim(llGetSubString(sTEXTURE,i+1,j-1),STRING_TRIM);;
                vTELEPORT=(vector)("<"+position+">");
                llMessageLinked(LINK_SET,1,dumpList( [ sME, "TEXT", "SHOW", "Teleport==>"+sTELEPORT+(string)vTELEPORT, "<1,1,1>" ]),"");
                return;
            }

        }

        llMessageLinked(LINK_SET,1,dumpList( [ sME, "TEXT", "SHOW", " ", "<1,1,1>" ]),"");

       } else {

          kCOMMENT=llGetNotecardLine(sCOMMENT,iCOMMENT);
       }
    }


}


changeTexture()
{
    debug("changing texture to "+(string)iTEXTURE);
    sTEXTURE=llGetInventoryName(INVENTORY_TEXTURE,iTEXTURE);
    if(sTEXTURE=="")
    {
        if(sSEARCH!="")
        {
            sSEARCH="";
            return;
        }
        // if textures finished then go back to first
        iTEXTURE=0;
        changeTexture();
        return;
    }
    // use only textures beginning with _
    //if(llGetSubString(sTEXTURE,0,0)=="_")
    {
        list pieces=llParseStringKeepNulls(sTEXTURE,["-"],[]);
        string lastpiece=llList2String(pieces,-1);
        pieces=llParseStringKeepNulls(lastpiece,["x"],[]);

        iM=(integer)llList2String(pieces,0);
        iN=(integer)llList2String(pieces,1);
        if(iM==0)iM=1;
        if(iN==0)iN=1;
        debug("read iM="+(string)iM+" iN="+(string)iN);

        // look for a comment notecard
        sCOMMENT=sTEXTURE+".txt";
        iCOMMENT=-1;

        fSPANY=((float)iM-1)/(2*(float)iM);
        fSCALY=1/(float)iM;
        fSPANX=((float)iN-1)/(2*(float)iN);
        fSCALX=1/(float)iN;

        vSTARTPOS=<fSPANX,-fSPANY,0>;
        vPOS=vSTARTPOS;
        iCNT=0;

        bENDTEXTURE=0;

        // show first image/subimage while notecardline will setText their content
        next();
    }
    //else
    //{
    //    iTEXTURE++;
    //    changeTexture();
    //}

}



default
{


    state_entry()
    {


        debug("Starting...");
        // read notecard, at end will start viewer
        //iSETUP=0;
        //kSETUP=llGetNotecardLine(sSETUP,iSETUP);

        // find LINKNUM of History-0 until History-4
        integer i;
        for(i=2;i<llGetNumberOfPrims();i++)
        {
            string name=llGetLinkName(i);
            debug("Found name: "+name+" linknum: "+(string)i);
            list pieces=llParseStringKeepNulls(name,["-"],[]);
            if(llList2String(pieces,0)=="History")
            {
                // it is an history
                debug("marking history piece");
                lHISTORYLINK+=[ llList2String(pieces,1), i ];

            }

        }
        // have history links ordered by History-x parm
        lHISTORYLINK=llListSort(lHISTORYLINK,2,TRUE);

        debug("lHISTORYLINK: "+llList2CSV(lHISTORYLINK));

        // reset play button to play and not pause if needed
        llMessageLinked(LINK_SET,1,dumpList( [ sME, "PLAY", "OFFSET", "<.333,.333,0>"]),"");

        // look for first image in the inventory
        iTEXTURE=0;
        changeTexture();

        //llListen(0,"",NULL_KEY,""); // for searching




    }
    changed(integer change)
    {
        if(change==CHANGED_INVENTORY)
        {
            //llResetScript();
            return;
        }
    }



    // notecard reader
    dataserver(key id, string data)
    {

       if(id==kCOMMENT)
         if(data!=EOF)
         {
             debug("Reading comment line #"+(string)iCOMMENT);

             if(llGetSubString(data,0,0)!="#")
             {


                 if(sSEARCH!="")
                 {

                     // either find uppercase or with no casing (numbers)
                     if(llSubStringIndex(llToUpper(data),llToUpper(sSEARCH))<0)

                     {
                         llMessageLinked(LINK_SET,1,dumpList( [ sME, "TEXT", "SHOW", "searching for "+sSEARCH+"...", "<1,1,1>" ]),"");
                         // if not found go next
                         next();
                         return;
                     }
                     else
                     {
                         // found!!
                         sSEARCH="";
                         setBoard();
                         push( sTEXTURE, <fSCALX, fSCALY, 0>, vPOS);
                     }

                 }
                 //string replaced=str_replace(data,"|","n");
                 push_text(data);

                 // only first line | replaced by n
                 info(data);




                 return;
             }
             iCOMMENT++;
             kCOMMENT=llGetNotecardLine(sCOMMENT, iCOMMENT);



         }
         else
         {
            debug("End of comments");

            bENDTEXTURE=1;

         }


    }



    touch_start(integer total_number)
    {

        key avatar=llDetectedKey(0);

        if(iLISTENHANDLER!=0)llListenRemove(iLISTENHANDLER);

        integer touched=llDetectedLinkNumber(0);

        debug("touched: "+(string)touched);
        if(touched==1){
            if(sTELEPORT!="")
            {
                llMapDestination(sTELEPORT,vTELEPORT,ZERO_VECTOR);
                return;
            }
            if(sINVENTORY=="") next();
            else
            {
                llGiveInventory(avatar,sINVENTORY);
                return;
            }
        }

        string linkname=llGetLinkName(touched);
        if(linkname=="Search")
        {
            iLISTENHANDLER=llListen(0,"",avatar,"");
            llSetTimerEvent(60);
            llDialog(avatar,"Say on normal chat FIND xxx or SEARCH xxx. You have 60 seconds for doing it.",[],-1);
            return;

        }

        if(linkname=="Stop")
        {
            llResetScript();
            return;
        }
        if(linkname=="Next")
        {
            next();
            return;
        }
        if(linkname=="FastNext")
        {
            iTEXTURE++;
            changeTexture();
            return;
        }
        if(linkname=="FastPrev" && iTEXTURE>0)
        {
            iTEXTURE-=1;
            changeTexture();
            return;
        }
        if(linkname=="Play")
        {
            if(iLISTENHANDLER!=0)
            {
                llListenRemove(iLISTENHANDLER);
                iLISTENHANDLER=0;
            }
            if(iPLAY==0)
            {
                iPLAY=1;
                llSetTimerEvent(0.1);
                llMessageLinked(LINK_SET,1,dumpList( [ sME, "PLAY", "OFFSET", "<.333,-.333,0>"]),"");
                return;
            }
            else
            {
                iPLAY=0;
                llMessageLinked(LINK_SET,1,dumpList( [ sME, "PLAY", "OFFSET", "<.333,.333,0>"]),"");
                llSetTimerEvent(0);
                return;
            }
        }


        list pieces=llParseStringKeepNulls(linkname,["-"],[]);
        if(llList2String(pieces,0)=="History")
        {
            // touched history, will display its content
            integer index=(integer)llList2String(pieces,1);
            debug("Trying to reinstate image");
            list data=peek(index);

            llSetLinkPrimitiveParams(eBOARD,
                [ PRIM_TEXTURE, ALL_SIDES,
                llList2String(data,1), // texture
                (vector)llList2String(data,2), // scale
                (vector)llList2String(data,3), // offset
                0.0 ]);

            info(llList2String(lTEXT,index));

            return;

        }



    }

    timer()
        {
            if(iLISTENHANDLER!=0)
            {
                llListenRemove(iLISTENHANDLER);
                iLISTENHANDLER=0;
                llSetTimerEvent(0);
                return;
            }
            next();
            llSetTimerEvent(iDELAY);
        }

    listen(integer channel,string name,key id,string message)
    {
        // SEARCH?

        if(llToUpper(llGetSubString(message,0,5))=="SEARCH")
        {

            sSEARCH=llGetSubString(message,7,-1);
            llSay(0,"Starting search for "+sSEARCH);
            // go on until found it
            next();
            return;
        }
        if(llToUpper(llGetSubString(message,0,3))=="FIND")
        {
            debug("FIND command");
            string sfind=llGetSubString(message,5,-1);
            llSay(0,"Starting find for "+sfind);
            for(iTEXTURE=iTEXTURE;iTEXTURE<llGetInventoryNumber(INVENTORY_TEXTURE);iTEXTURE++)
            {

                sTEXTURE=llGetInventoryName(INVENTORY_TEXTURE,iTEXTURE);
                debug("Scanning texture "+sTEXTURE);
                if(llGetSubString(sTEXTURE,0,0)=="_")
                {
                    string src=llToUpper(sTEXTURE);
                    string find=llToUpper(sfind);
                    debug("Checking if '"+src+"' contains '"+find+"' "+(string)llSubStringIndex(src,find));
                    if(llSubStringIndex(src,find)>=0)
                    {
                        debug("Found");
                        changeTexture();
                        return;
                    }
                }
            }
            return;

        }
    }

}
Advertisements
This entry was posted in Scripting avanzato. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s