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)
 
(documentation)
Line 1: Line 1:
<lsl>
<lsl>
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.
             }
             }
         }
         }

Revision as of 06:40, 14 December 2011

<lsl> //! @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();
       }
   }

} </lsl>