Difference between revisions of "Open Prim Animator"
Jump to navigation
Jump to search
Kireji Haiku (talk | contribs) (not done editiing, yet....still working on it. Improved loop speeds so far and readability of code. Still have to rename variable names to make more sense so we don't need any comments!) |
m (<lsl> tag to <source>) |
||
(3 intermediate revisions by 3 users not shown) | |||
Line 1: | Line 1: | ||
< | <source lang="lsl2"> | ||
// Open Prim Animator - by Todd Borst | // Open Prim Animator - by Todd Borst | ||
// Extensive Modifications by SignpostMarv Martin | // Extensive Modifications by SignpostMarv Martin | ||
// Note from Todd to other editors: Please document changes you have made to get proper credit. | |||
// Note from Todd to users: People may have edited the script from since I've posted it originally. | |||
// You can always view the original script by clicking the history tab. | |||
// This is provided AS IS without support. Please don't bug me demanding | // This is provided AS IS without support. Please don't bug me demanding | ||
Line 18: | Line 22: | ||
// License: | // License: | ||
// You are welcome to use this anyway you like, even bring to other grids | // You are welcome to use this anyway you like, even bring to other grids | ||
// outside of Second Life. | // outside of Second Life. You are welcomed to sell it if you've made your | ||
// | // own improvements to it. This is effectively public domain. Have fun. | ||
integer COMMAND_CHANNEL = 32; | integer COMMAND_CHANNEL = 32; | ||
integer primCount; | integer primCount; | ||
integer commandListenerHandle = | integer commandListenerHandle = ERR_GENERIC; | ||
list posList; | list posList; | ||
Line 187: | Line 191: | ||
// touch_start(integer num_detected) | // touch_start(integer num_detected) | ||
// { | // { | ||
// if (commandListenerHandle == | // if (commandListenerHandle == ERR_GENERIC) | ||
// { | // { | ||
// if (playAnimationStyle == 0) | // if (playAnimationStyle == 0) | ||
Line 279: | Line 283: | ||
export = []; | export = []; | ||
i = 0 | i = 0; | ||
j = llGetListLength(rotList); | j = llGetListLength(rotList); | ||
Line 459: | Line 463: | ||
} | } | ||
if (commandListenerHandle != | if (commandListenerHandle != ERR_GENERIC) | ||
showMenuDialog(); | showMenuDialog(); | ||
} | } | ||
Line 477: | Line 481: | ||
llSetTimerEvent((float)FALSE); | llSetTimerEvent((float)FALSE); | ||
if (commandListenerHandle != | if (commandListenerHandle != ERR_GENERIC) | ||
showMenuDialog(); | showMenuDialog(); | ||
} | } | ||
Line 483: | Line 487: | ||
} | } | ||
} | } | ||
</ | </source> | ||
[[Category:Open Prim Animator|Open Prim Animator]] | [[Category:Open Prim Animator|Open Prim Animator]] |
Latest revision as of 07:15, 25 January 2015
// Open Prim Animator - by Todd Borst
// Extensive Modifications by SignpostMarv Martin
// Note from Todd to other editors: Please document changes you have made to get proper credit.
// Note from Todd to users: People may have edited the script from since I've posted it originally.
// You can always view the original script by clicking the history tab.
// This is provided AS IS without support. Please don't bug me demanding
// help or custom work for this free script.
// Summary: This is a simple prim animation script. Just add this script
// to your object and a dialog will automatically pop up for you to use.
// Features:
// -Single script "Prim Puppeteer" like animation tool
// -Playback controllable through external scripts
// -Animation is scalable and resizeable
// -On-touch trigger built-in
// -Completely free and open sourced
// License:
// You are welcome to use this anyway you like, even bring to other grids
// outside of Second Life. You are welcomed to sell it if you've made your
// own improvements to it. This is effectively public domain. Have fun.
integer COMMAND_CHANNEL = 32;
integer primCount;
integer commandListenerHandle = ERR_GENERIC;
list posList;
list rotList;
list scaleList;
integer currentSnapshot;
integer recordedSnapshots;
vector rootScale;
vector scaleChange = <1.0, 1.0, 1.0>;
integer maxMemory;
integer freeMemory;
// The values for playAnimationStyle means
// 0 := no animation playing
// 1 := play animation once
// 2 := play animation looping
integer playAnimationStyle;
key op_import = "6b78fcc8-e147-4105-99a6-ff19b4bf559d";
key op_export = "7c2ca168-2b64-4836-8727-8e62b78dbd44";
key op_alter_rootScale = "f9d3389e-a78c-43f8-9e35-c11adec112a5";
// _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
// _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
show_snapshot(integer snapNumber)
{
if (!snapNumber || recordedSnapshots < snapNumber)
return;
vector rootPos = llGetPos();
rotation rootRot = llGetRot();
vector pos;
rotation rot;
vector scale;
list params;
integer i = 2;
do
{
pos = llList2Vector(posList, ((snapNumber - 1)*(primCount - 1)) + (i - 2));
rot = llList2Rot(rotList, ((snapNumber - 1)*(primCount - 1)) + (i - 2));
scale = llList2Vector(scaleList, ((snapNumber - 1)*(primCount - 1)) + (i - 2));
if ( rootScale.x != 1.0 || rootScale.y != 1.0 || rootScale.z != 1.0 )
{
pos.x *= scaleChange.x;
pos.y *= scaleChange.y;
pos.z *= scaleChange.z;
scale.x *= scaleChange.x;
scale.y *= scaleChange.y;
scale.z *= scaleChange.z;
}
params += [PRIM_LINK_TARGET, i,
PRIM_POSITION, pos,
PRIM_ROTATION, rot/rootRot,
PRIM_SIZE, scale
];
if (64 < llGetListLength(params))
{
llSetLinkPrimitiveParamsFast(LINK_THIS, params);
params = [];
}
}
while (++i <= primCount);
if (llGetListLength(params))
{
llSetLinkPrimitiveParamsFast(LINK_THIS, params);
params = [];
}
}
playAnimation(float delay, integer loop)
{
if (delay < 0.1)
delay = 1.0;
if (loop == FALSE)
playAnimationStyle = 1;
else
playAnimationStyle = 2;
if (1 <= recordedSnapshots)
llSetTimerEvent(delay);
}
showMenuDialog()
{
// return;
string temp = (string)((float)freeMemory/(float)maxMemory * 100.0);
string menuText = "Free Memory: " + (string)freeMemory + " (" + llGetSubString(temp, 0, 4) +"%)"
+ "\nSnapshot " + (string)currentSnapshot +" of " + (string)recordedSnapshots
+ "\n\n[ Record ] - Record a snapshot of prim positions"
+ "\n[ Play ] - Play back all the recorded snapshots"
+ "\n[ Publish ] - Finish the recording process"
+ "\n[ Show Next ] - Show the next snapshot"
+ "\n[ Show Prev ] - Show the previous snapshot";
llDialog(llGetOwner(), menuText,
["Record","Play","Publish","Show Prev","Show Next","Loop","Stop","Export"], COMMAND_CHANNEL);
}
string truncate_float(float foo)
{
if (foo == 0.0)
return "0";
else if (foo == (float)((integer)foo))
return (string)((integer)foo);
string bar = (string)foo;
while (llGetSubString(bar, -1, -1) == "0")
bar = llGetSubString(bar, 0, -2);
if (llGetSubString(bar, -1, -1) == ".")
bar = llGetSubString(bar, 0, -2);
return bar;
}
calc_scaleChange()
{
if (rootScale != ZERO_VECTOR)
{
vector newScale = llGetScale();
if ( (newScale.x / rootScale.x) != scaleChange.x
|| (newScale.y / rootScale.y) != scaleChange.y
|| (newScale.z / rootScale.z) != scaleChange.z)
{
scaleChange.x = newScale.x / rootScale.x;
scaleChange.y = newScale.y / rootScale.y;
scaleChange.z = newScale.z / rootScale.z;
}
}
}
default
{
state_entry()
{
maxMemory = llGetFreeMemory();
freeMemory = llGetFreeMemory();
primCount = llGetNumberOfPrims();
commandListenerHandle = llListen(COMMAND_CHANNEL,"", llGetOwner(), "");
showMenuDialog();
rootScale = llGetScale();
if (llGetInventoryType("OPA Notecard Import - 2011-11-03") == INVENTORY_SCRIPT){
llResetOtherScript("OPA Notecard Import - 2011-11-03");
}
}
// Feel free to remove this on-touch trigger if you are using your own script to control playback
// touch_start(integer num_detected)
// {
// if (commandListenerHandle == ERR_GENERIC)
// {
// if (playAnimationStyle == 0)
// playAnimation(1.0,TRUE);
// else
// {
// playAnimationStyle = 0;
// llSetTimerEvent((float)FALSE);
// }
// }
// }
changed(integer change)
{
if (change & CHANGED_SCALE)
calc_scaleChange();
if (change & CHANGED_LINK)
{
if ( primCount != llGetNumberOfPrims() )
{
llOwnerSay("Link change detected, reseting script.");
llResetScript();
}
}
}
//The message link function is to allow other scripts to control the snapshot playback
//This command will display snapshot #2:
// llMessageLinked(LINK_ROOT, 2, "XDshow", NULL_KEY); llSleep(1.0);
//
//This command will play through all the recorded snapshots in ascending order. The number "1.0" is the delay speed and can be changed.
// llMessageLinked(LINK_ROOT, 0, "XDplay", "1.0");
//
//This command will loop through all the recorded snapshots in ascending order. The number "1.0" is the delay speed and can be changed.
// llMessageLinked(LINK_ROOT, 0, "XDplayLoop", "1.0");
//
//To stop any playing animation use
// llMessageLinked(LINK_ROOT, 0, "XDstop", NULL_KEY);
link_message(integer sender_num, integer num, string str, key id)
{
if ("XDshow" == str && 1 <= num && num <= recordedSnapshots)
show_snapshot(num);
else if ("XDplay" == str)
{
currentSnapshot = 1;
float delay = (float)((string)id);
playAnimation(delay, FALSE);
}
else if ("XDplayLoop" == str)
{
float delay = (float)((string)id);
playAnimation(delay, TRUE);
}
else if ("XDstop" == str)
{
playAnimationStyle = 0;
llSetTimerEvent((float)FALSE);
}
else if ("XDexport" == str && !num)
{
list export = [];
string foo;
vector bar;
rotation baa;
string baz;
integer i = 2;
integer j = primCount;
do
export += [llGetLinkName(i)];
while (++i <= j);
llMessageLinked(sender_num, 1, llDumpList2String(export,"|") , op_export);
export = [];
i = 0;
j = llGetListLength(posList);
do
{
bar = llList2Vector(posList,i);
export += ["<" + truncate_float(bar.x) + ","
+ truncate_float(bar.y) + "," + truncate_float(bar.z) + ">"];
}
while (++i < j);
llMessageLinked(sender_num, 2, llDumpList2String(export,"|") , op_export);
export = [];
i = 0;
j = llGetListLength(rotList);
do
{
baa = llList2Rot(rotList,i);
export += ["<" + truncate_float(baa.x) + "," + truncate_float(baa.y)
+ "," + truncate_float(baa.z) + "," + truncate_float(baa.s) + ">"];
}
while (++i < j);
llMessageLinked(sender_num, 3, llDumpList2String(export,"|") , op_export);
export = [];
i = 0;
j = llGetListLength(scaleList);
do
{
bar = llList2Vector(scaleList,i);
export += ["<" + truncate_float(bar.x) + ","
+ truncate_float(bar.y) + "," + truncate_float(bar.z) + ">"];
}
while (++i < j);
llMessageLinked(sender_num, 4, llDumpList2String(export,"|") , op_export);
}
else if ("XDmenu" == str)
{
showMenuDialog();
}
else if ("XDimportLength" == str && 0 < num)
{
list foo;
list bar;
integer i;
do
{
foo += [ZERO_VECTOR];
bar += [ZERO_ROTATION];
}
while (++i < num);
posList = foo;
scaleList = foo;
rotList = bar;
llMessageLinked(sender_num,-1,str,op_import);
recordedSnapshots = num / (llGetNumberOfPrims() - 1);
llMessageLinked(LINK_SET, recordedSnapshots, "XDrecordedSnapshots", NULL_KEY);
currentSnapshot = 1;
}
else if ("XDrecordedSnapshots" == str && num == -1)
{
llMessageLinked(sender_num,recordedSnapshots,str,NULL_KEY);
}
else if (id == op_import && 0 <= num)
{
list params = llParseString2List(str, ["|"], []);
vector impPos = (vector)llList2String(params, 0);
rotation impRot = (rotation)llList2String(params, 1);
vector impSize = (vector)llList2String(params, 2);
posList = llListReplaceList(posList, [impPos], num, num);
rotList = llListReplaceList(rotList, [impRot], num, num);
scaleList = llListReplaceList(scaleList, [impSize], num, num);
}
else if (id == op_alter_rootScale)
{
rootScale = (vector)str;
calc_scaleChange();
}
}
listen(integer channel, string name, key id, string message)
{
list parsedMessage = llParseString2List(message, [" "], []);
string firstWord = llToLower(llList2String(parsedMessage, 0));
string secondWord = llToLower(llList2String(parsedMessage, 1));
if ("show" == firstWord && recordedSnapshots > 0)
{
llSetTimerEvent((float)FALSE);
if (secondWord == "next")
{
++currentSnapshot;
if (recordedSnapshots < currentSnapshot)
currentSnapshot = 1;
show_snapshot(currentSnapshot);
}
else if (secondWord == "prev")
{
--currentSnapshot;
if (currentSnapshot < 1)
currentSnapshot = recordedSnapshots;
show_snapshot(currentSnapshot);
}
else
{
currentSnapshot = (integer)secondWord;
if (currentSnapshot && currentSnapshot <= recordedSnapshots)
{
show_snapshot(currentSnapshot);
llOwnerSay("Showing snapshot: " + (string)currentSnapshot);
}
else
{
llOwnerSay("Invalid snapshot number given: " + (string) currentSnapshot +
"\nA valid snapshot number is between 1 and " + (string) recordedSnapshots);
currentSnapshot = 1;
}
}
}
else if (firstWord == "record")
{
vector rootPos = llGetPos();
integer i = 2;
do
{
vector pos = llList2Vector(llGetLinkPrimitiveParams(i, [PRIM_POSITION]), 0);
pos.x -= rootPos.x;
pos.z -= rootPos.z;
pos.y -= rootPos.y;
pos = pos / llGetRot();
posList += pos;
rotation rot = llList2Rot(llGetLinkPrimitiveParams(i, [PRIM_ROTATION]), 0);
rot = rot / llGetRot();
rotList += rot;
scaleList += llList2Vector(llGetLinkPrimitiveParams(i, [PRIM_SIZE]), 0);
}
while (++i <= primCount);
++recordedSnapshots;
llOwnerSay("Total number of snapshots recorded: " + (string)recordedSnapshots);
freeMemory = llGetFreeMemory();
}
else if (firstWord == "play")
{
float delay = (float)secondWord;
currentSnapshot = 1;
playAnimation(delay, FALSE);
}
else if ("publish" == firstWord)
{
llSetTimerEvent((float)FALSE);
playAnimationStyle = 0;
currentSnapshot = 1;
llListenRemove(commandListenerHandle);
commandListenerHandle = -1;
llOwnerSay("Recording disabled. Publish complete.\nClick me to toggle animation on/off.");
}
else if ("loop" == firstWord)
{
llMessageLinked(LINK_THIS, 0, "XDplayLoop", NULL_KEY);
}
else if ("stop" == firstWord)
{
llMessageLinked(LINK_THIS, 0, "XDstop", NULL_KEY);
}
else if ("export" == firstWord)
{
llOwnerSay("Should be exporting");
llMessageLinked(LINK_THIS, 0, "XDexport", NULL_KEY);
}
if (commandListenerHandle != ERR_GENERIC)
showMenuDialog();
}
timer()
{
show_snapshot(currentSnapshot);
if (currentSnapshot < recordedSnapshots)
++currentSnapshot;
else
{
if (playAnimationStyle == 2)
currentSnapshot = 1;
else
{
llSetTimerEvent((float)FALSE);
if (commandListenerHandle != ERR_GENERIC)
showMenuDialog();
}
}
}
}