Puppeteer Recorder

puppeteer_recorder.lsl
//////////////////////////////////////////////////////////
//                 PUPPETEER RECORDER                   //
//////////////////////////////////////////////////////////
// Gremlin: Puppeteer Recorder, see Puppeteer Animator
///////////////////////////////////////////////////////////////////////////
//  Copyright (C) Wizardry and Steamworks 2011 - License: GNU GPLv3      //
//  Please see: http://www.gnu.org/licenses/gpl.html for legal details,  //
//  rights of fair usage, the disclaimer and warranty conditions.        //
///////////////////////////////////////////////////////////////////////////
 
list pos = [];
list rot = [];
 
default
{
    touch_start(integer total_number) {
        key toucher = llDetectedKey(0);
        if(toucher != llGetOwner()) return;
        integer comChannel = (integer)("0x8" + llGetSubString(llGetKey(), 0, 6));
        llListen(comChannel, "", toucher, "");
        llDialog(toucher, "\nWelcome to the Puppeteer:\n\n1.) ◆ Mark ◆ is for recording each step. Move/Rotate the prim and press ◆ Mark ◆ to record that position.\n2.) Use ◆ Wipe ◆ if you want to delete all existing recoded data.\n3.) Use ◆ Dump ◆ after you have recoded several steps.\n4.) ◆ Undo ◆ lets you delete the previous step. This works multiple times.\n5.) ◆ Preview ◆ will allow you to watch the animation before dumping the data.\n", [ "◆ Mark ◆", "◆ Wipe ◆", "◆ Dump ◆", "◆ Undo ◆", "◆ Preview ◆" ], comChannel);
    }
 
    listen(integer channel, string name, key id, string message) {
        if(message == "◆ Mark ◆") {
            pos += (list)llGetLocalPos();
            rot += (list)llGetLocalRot();
            llOwnerSay("--MARK--");
            return;
        }
        if(message == "◆ Dump ◆") {
            if(llGetListLength(pos) == 0) {
                llOwnerSay("Sorry, you need to first record steps before dumping the data.");
                return;
            }
            llOwnerSay("------------- BEGIN CUT -------------");
            integer i = 0;
            integer mLine;
            string pLine;
            do {
                if(llStringLength(pLine) + llStringLength(llList2String(pos, i)) < 254) {
                    pLine += llList2String(pos, i) + "#";
                    jump continue_p;
                }
                llOwnerSay("#" + pLine);
                pLine = "";
                mLine = 1;
@continue_p;
            } while(++i<llGetListLength(pos));
            if(!mLine) llOwnerSay("#" + pLine);
            llOwnerSay("[K]"); 
            i = 0;
            string rLine;
            do {
                if(llStringLength(rLine) + llStringLength(llList2String(rot, i)) < 254) {
                    rLine += llList2String(rot, i)+ "#";
                    jump continue_r;
                }
                llOwnerSay("#" + rLine);
                rLine = "";
                mLine = 1;
@continue_r;
            } while(++i<llGetListLength(rot));
            if(!mLine) llOwnerSay("#" + rLine);
            llOwnerSay("-------------- END CUT --------------");
            return;
        }
        if(message == "◆ Wipe ◆") {
            pos = [];
            rot = [];
            llOwnerSay("All recorded steps have been wiped.");
            return;
        }
        if(message == "◆ Undo ◆") {
            if(llGetListLength(pos) == 0) {
                llOwnerSay("No more steps left to undo.");
                return;
            }
            vector rPos = llList2Vector(pos, llGetListLength(pos)-1);
            pos = llDeleteSubList(pos, llGetListLength(pos)-1, llGetListLength(pos)-1);
            rotation rRot = llList2Rot(rot, llGetListLength(rot)-1);
            rot = llDeleteSubList(rot, llGetListLength(rot)-1, llGetListLength(rot)-1);
            llSetPos(rPos);
            llSetLocalRot(rRot);
            return;
        }
        if(message == "◆ Preview ◆") {
            llOwnerSay("Animation will run once and then stop.");
            state puppet;
        }
    }
}
 
state puppet {
    state_entry() {
        integer i = 0;
        do {
            llSetPos(llList2Vector(pos, i));
            llSetLocalRot(llList2Rot(rot, i));
        } while(++i<llGetListLength(pos));
        llOwnerSay("Animation done, resuming normal operation.");
        state default;
    }
}