Difference between revisions of "Open Prim Animator/Frame Labels"

From Second Life Wiki
Jump to navigation Jump to search
(Committing changes made to OPA made over the past year at work)
 
 
(2 intermediate revisions by one other user not shown)
Line 1: Line 1:
<lsl>
<source lang="lsl2">
getRecordedSnapshots(){
//!  @brief Provides an API to allow animation frames to be "labelled" so they can be called by string instead of integer.
/**
*    @author SignpostMarv Martin
*/
 
getRecordedSnapshots(){ // short-hand for getting the number of animation frames
     llMessageLinked(LINK_THIS,-1,"XDrecordedSnapshots",NULL_KEY);
     llMessageLinked(LINK_THIS,-1,"XDrecordedSnapshots",NULL_KEY);
}
}


//!  name of the notecard to load the frame labels from. Each label should be on a new line corresponding to the animation frame (first line first frame, second line second frame and so on)
string notecard = "OPA-Frame-Labels";
string notecard = "OPA-Frame-Labels";
//!  notecard contents
string contents;
string contents;
//!  notecard lines
list  _contents;
list  _contents;
//!  dataserver keys for non-sequential loading of notecard lines.
list multithread_fetch = [];
list multithread_fetch = [];
//!  dataserver key for fetching the number of notecard lines
key nlq;
key nlq;


//!  Yet another vestigial copypasta.
export_string(string _export_string){
export_string(string _export_string){
     integer s=1000;
     integer s=1000;
Line 21: Line 36:
}
}


//!  number of animation frames
integer recordedSnapshots = 0;
integer recordedSnapshots = 0;
//!  command to change the current animation frame.
key op_change_frame = "1071f377-8623-4ed3-acc1-d30cabb4524a";
key op_change_frame = "1071f377-8623-4ed3-acc1-d30cabb4524a";


default{
default{
     state_entry(){
     state_entry(){
         integer type = llGetInventoryType(notecard);
         integer type = llGetInventoryType(notecard); // check the notecard is in inventory
         if(type == INVENTORY_NONE){
         if(type == INVENTORY_NONE){ // if type is INVENTORY_NONE it isn't there.
             llOwnerSay("Notecard not found");
             llOwnerSay("Notecard not found");
         }else if(type != INVENTORY_NOTECARD){
         }else if(type != INVENTORY_NOTECARD){ // if type is not INVENTORY_NOTECARD, something else is hogging the name.
             llOwnerSay("Inventory item found with name of notecard, but it is not a notecard");
             llOwnerSay("Inventory item found with name of notecard, but it is not a notecard");
         }else{
         }else{ // notecard found, proceeding with parsing process
             state num_lines;
             state num_lines;
         }
         }
     }
     }


     changed(integer c){
     changed(integer c){ // rather than resetting the script, we jump straight to the num_lines state if the notecard is now found.
         if(c & CHANGED_INVENTORY && llGetInventoryType(notecard) == INVENTORY_NOTECARD){
         if(c & CHANGED_INVENTORY && llGetInventoryType(notecard) == INVENTORY_NOTECARD){
             state num_lines;
             state num_lines;
Line 42: Line 60:
     }
     }


    state_exit(){
//    state_exit(){
//        llOwnerSay("Notecard found, parsing");
//        llOwnerSay("Notecard found, parsing");
    }
//    }
}
}


state num_lines{
state num_lines{ // we're using separate states to avoid race conditions with changed inventory etc.
     state_entry(){
     state_entry(){
         nlq = llGetNumberOfNotecardLines(notecard);
         nlq = llGetNumberOfNotecardLines(notecard); // fire off a request for the notecard lines
     }
     }


Line 75: Line 93:
}
}


state mtf{
state mtf{ // fetch all notecard lines without the delay caused by traditional sequential loading.
     state_entry(){
     state_entry(){
         integer i;
         integer i;
Line 109: Line 127:


     link_message(integer s, integer n, string m, key i){
     link_message(integer s, integer n, string m, key i){
         if(m == "XDrecordedSnapshots" && n >= 0){
         if(m == "XDrecordedSnapshots" && n >= 0){ // if we're updating the number of animation frames
             recordedSnapshots = n;
             recordedSnapshots = n;
             if(recordedSnapshots == 1){
             if(recordedSnapshots == 1){ // and there's only one frame
                 llMessageLinked(LINK_THIS,0,"XDplay",NULL_KEY);
                 llMessageLinked(LINK_THIS,0,"XDplay",NULL_KEY); // play it.
             }
             }
         }else if(i == op_change_frame){
         }else if(i == op_change_frame){ // if we receive a command to change to an animation frame by a named label,
             integer frame = llListFindList(_contents,[m]);
             integer frame = llListFindList(_contents,[m]); // check the label exists in the notecard contents
             if(frame >= 0){
             if(frame >= 0){ // then if the named label does exist,
                 llMessageLinked(LINK_THIS,frame + 1,"XDshow",NULL_KEY);
                 llMessageLinked(LINK_THIS,frame + 1,"XDshow",NULL_KEY); // show it.
             }
             }
         }
         }
Line 128: Line 146:
     }
     }
}
}
</lsl>
</source>
[[Category:Open Prim Animatior|Frame Labels]]
[[Category:Open Prim Animator|Frame Labels]]

Latest revision as of 14:58, 26 February 2015

//!  @brief Provides an API to allow animation frames to be "labelled" so they can be called by string instead of integer.
/**
*    @author SignpostMarv Martin
*/

getRecordedSnapshots(){ // short-hand for getting the number of animation frames
    llMessageLinked(LINK_THIS,-1,"XDrecordedSnapshots",NULL_KEY);
}

//!  name of the notecard to load the frame labels from. Each label should be on a new line corresponding to the animation frame (first line first frame, second line second frame and so on)
string notecard = "OPA-Frame-Labels";

//!  notecard contents
string contents;

//!  notecard lines
list   _contents;

//!  dataserver keys for non-sequential loading of notecard lines.
list multithread_fetch = [];

//!  dataserver key for fetching the number of notecard lines
key nlq;

//!  Yet another vestigial copypasta.
export_string(string _export_string){
    integer s=1000;
    while(llStringLength(_export_string) > s){
        llOwnerSay(llGetSubString(_export_string,0,(s-1)));
        _export_string = llGetSubString(_export_string,s,-1);
    }
    if(llStringLength(_export_string) > 0){
        llOwnerSay(_export_string);
    }
}

//!  number of animation frames
integer recordedSnapshots = 0;

//!  command to change the current animation frame.
key op_change_frame = "1071f377-8623-4ed3-acc1-d30cabb4524a";

default{
    state_entry(){
        integer type = llGetInventoryType(notecard); // check the notecard is in inventory
        if(type == INVENTORY_NONE){ // if type is INVENTORY_NONE it isn't there.
            llOwnerSay("Notecard not found");
        }else if(type != INVENTORY_NOTECARD){ // if type is not INVENTORY_NOTECARD, something else is hogging the name.
            llOwnerSay("Inventory item found with name of notecard, but it is not a notecard");
        }else{ // notecard found, proceeding with parsing process
            state num_lines;
        }
    }

    changed(integer c){ // rather than resetting the script, we jump straight to the num_lines state if the notecard is now found.
        if(c & CHANGED_INVENTORY && llGetInventoryType(notecard) == INVENTORY_NOTECARD){
            state num_lines;
        }
    }

//    state_exit(){
//        llOwnerSay("Notecard found, parsing");
//    }
}

state num_lines{ // we're using separate states to avoid race conditions with changed inventory etc.
    state_entry(){
        nlq = llGetNumberOfNotecardLines(notecard); // fire off a request for the notecard lines
    }

    dataserver(key q, string m){
        if(q == nlq){
            integer i;
            integer j = (integer)m;
            if(j < 1){
                contents = "";
                state done_reading;
            }
            list    k = []; // declaring list k = []; isn't exactly necessary, you could do list k;
            list    l = [];
            for(i=0;i<j;++i){ // since we don't have the concept of transactions in LSL scripts, we're going to build up these lists separately 
                k += [NULL_KEY];
                l += [NULL_KEY];
            }
            _contents = k; // this is where we do the atomic writes due to lack of transactions on variables
            multithread_fetch = l; // this is where we do the atomic writes due to lack of transactions on variables
            k = []; // cleaning up the local variable on purpose in case the LSL VM executing this script is inefficient
            l = []; // cleaning up the local variable on purpose in case the LSL VM executing this script is inefficient
            state mtf;
        }
    }
}

state mtf{ // fetch all notecard lines without the delay caused by traditional sequential loading.
    state_entry(){
        integer i;
        integer j=llGetListLength(multithread_fetch);
        for(i=0;i<j;++i){
            multithread_fetch = llListReplaceList(multithread_fetch,[llGetNotecardLine(notecard,i)],i,i); // sets the notecard fetching away
        }
    }

    dataserver(key q, string m){
        integer i = llListFindList(multithread_fetch,[q]);
        if(i >= 0){
            _contents = llListReplaceList(_contents,[m],i,i); // the traditional method of notecard fetching in LSL is single-threaded, getting one line at a time
        }
        if(llListFindList(_contents,[NULL_KEY]) == -1){ // since we started out with a NULLL_KEY-filled list, if there aren't any NUL_KEY in the list then we know it's done. caveat scriptor: since key and string types are interchangeable 
            contents = llDumpList2String(_contents,"\n");
            state done_reading;
        }
    }

    state_exit(){
        _contents = [];
        multithread_fetch = [];
    }
}

state done_reading{
    state_entry(){
        _contents = llParseString2List(contents, ["\n"],[]);
//        llOwnerSay((string)llGetListLength(_contents) + " frame labels found");
        getRecordedSnapshots();
    }

    link_message(integer s, integer n, string m, key i){
        if(m == "XDrecordedSnapshots" && n >= 0){ // if we're updating the number of animation frames
            recordedSnapshots = n;
            if(recordedSnapshots == 1){ // and there's only one frame
                llMessageLinked(LINK_THIS,0,"XDplay",NULL_KEY); // play it.
            }
        }else if(i == op_change_frame){ // if we receive a command to change to an animation frame by a named label,
            integer frame = llListFindList(_contents,[m]); // check the label exists in the notecard contents
            if(frame >= 0){ // then if the named label does exist,
                llMessageLinked(LINK_THIS,frame + 1,"XDshow",NULL_KEY); // show it.
            }
        }
    }

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