Join us in Outworldz at www.outworldz.com:9000 or follow us:

Search dozens of selected web sites for OpenSim and LSL script

New! Script Meta-Search will search thousands of scripts here and at other sites for LSL or Opensim scripts.
Loading

Want to add a script or a project? Upload it and a half million people will see it and your name here this year.

Home   Show All
Category: Contributor: Creator
Prim Open_Prim_Animator  

Open_Prim_Animator

This is provided AS IS without support. Please don't bug me demanding
help or custom work for this free script.

Authors License:
You are welcome to use this anyway you like, even bring to other grids
outside of Second Life. If you try to sell what I'm giving away for
free, you will be cursed with unimaginably bad juju.

This work uses content from the Second Life® Wiki article at http://wiki.secondlife.com/wiki/Open_Prim_Animatorand is Copyright © 2007-2009 Linden Research, Inc.

Category: Prim
By : Todd Borst
Created: 2011-03-02 Edited: 2011-03-02
Worlds: OpenSim

the Zip file

Download all files for Open_Prim_Animator
Contents are in zip format, with .LSL (text) source code and LSLEdit (text + Solution) formats.
Get file # 1. Open_Prim_Animator_1.lsl
1
2 integer COMMAND_CHANNEL = 32;
3
4 integer primCount = 0;
5 integer commandListenerHandle = -1;
6
7 list posList = [];
8 list rotList = [];
9 list scaleList = [];
10 integer currentSnapshot = 0;
11 integer recordedSnapshots = 0;
12
13 vector rootScale = ZERO_VECTOR;
14 vector scaleChange = <1,1,1>;
15
16 // For tracking memory usage. The amount of snapshots you can record is based
17 // on the number of prims and available memory. Less prims = more snapshots
18 integer maxMemory = 0;
19 integer freeMemory = 0;
20
21 integer playAnimationStyle = 0;
22 // The values for playAnimationStyle means
23 // 0 = no animation playing
24 // 1 = play animation once
25 // 2 = play animation looping
26
27 // This function is used to display a recorded snapshot
28 showSnapshot(integer snapNumber)
29 {
30 if(snapNumber > 0 && snapNumber <= recordedSnapshots )
31 {
32 integer i = 0;
33 vector pos;
34 rotation rot;
35 vector scale;
36
37 vector rootPos = llGetPos();
38
39 // Might want to move llGetRot() into the loop for fast rotating objects.
40 // Rotation during the animation playback may cause errors.
41 rotation rootRot = llGetRot();
42
43 //2 is the first linked prim number.
44 for( i = 2; i <= primCount; i++)
45 {
46 pos = llList2Vector(posList,((snapNumber-1)*(primCount-1))+(i-2));
47 rot = llList2Rot(rotList,((snapNumber-1)*(primCount-1))+(i-2));
48 scale = llList2Vector(scaleList,((snapNumber-1)*(primCount-1))+(i-2));
49
50 //Adjust for scale changes
51 if( rootScale.x != 1.0 || rootScale.y != 1.0 || rootScale.z != 1.0 )
52 {
53 pos.x *= scaleChange.x;
54 pos.y *= scaleChange.y;
55 pos.z *= scaleChange.z;
56 scale.x *= scaleChange.x;
57 scale.y *= scaleChange.y;
58 scale.z *= scaleChange.z;
59 }
60
61 llSetLinkPrimitiveParamsFast( i, [ PRIM_POSITION, pos, PRIM_ROTATION, rot/rootRot, PRIM_SIZE, scale ] );
62 }
63 }
64 }
65
66 // This function is used to start a sequential animation playback.
67 // If the delay speed is set too low, the script might not be able to keep up.
68 playAnimation(float delay, integer loop)
69 {
70 if(delay < 0.1) delay = 1.0;
71
72 if( loop == FALSE)
73 playAnimationStyle = 1;
74 else
75 playAnimationStyle = 2;
76
77 if(recordedSnapshots >= 1)
78 llSetTimerEvent(delay);
79 }
80
81 // This shows the edit menu
82 showMenuDialog()
83 {
84 string temp = (string)((float)freeMemory/(float)maxMemory * 100.0);
85 string menuText = "Available Memory: " + (string)freeMemory + " (" + llGetSubString(temp, 0, 4) +"%)" +
86 "\nCurrent Snapshot: " + (string)currentSnapshot +"\tSnapshots Recorded: " + (string)recordedSnapshots +
87 "\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";
88
89 llDialog(llGetOwner(), menuText, ["Record","Play","Publish","Show Prev","Show Next"], COMMAND_CHANNEL);
90 }
91
92 default
93 {
95 {
96 maxMemory = llGetFreeMemory();
97 freeMemory = llGetFreeMemory();
98
99 primCount = llGetNumberOfPrims();
100 commandListenerHandle = llListen(COMMAND_CHANNEL,"", llGetOwner(), "");
101 showMenuDialog();
102
103 //setting initial root scale. this allows the animation to scale if the root size is changed afterwards.
104 rootScale = llGetScale();
105 }
106
107 //Feel free to remove this on-touch trigger if you are using your own script to control playback
108 touch_start(integer num_detected)
109 {
110 //only activate after publish.
111 if(commandListenerHandle == -1)
112 {
113 //if animation not playing start it, else stop it.
114 if( playAnimationStyle == 0)
115 playAnimation(1.0,TRUE);
116 else
117 {
118 playAnimationStyle = 0;
120 }
121 }
122 }
123
124 changed(integer change)
125 {
126 //this is needed to detect scale changes and record the differences in order to adjust the animation accordingly.
127 if(change & CHANGED_SCALE)
128 {
129 if(rootScale != ZERO_VECTOR)
130 {
131 vector newScale = llGetScale();
132 //since change_scale is triggered even with linked prim changes,
133 //this is to filter out non-root changes.
134 if( ( newScale.x / rootScale.x) != scaleChange.x ||
135 ( newScale.y / rootScale.y) != scaleChange.y ||
136 ( newScale.z / rootScale.z) != scaleChange.z )
137 {
138 scaleChange.x = newScale.x / rootScale.x;
139 scaleChange.y = newScale.y / rootScale.y;
140 scaleChange.z = newScale.z / rootScale.z;
141 }
142 }
143 }
144 // if new prims are added or removed from this object then the script resets
145 // because the animations are now broken.
146 else if(change & CHANGED_LINK)
147 {
148 if( primCount != llGetNumberOfPrims() )
149 {
150 llOwnerSay("Link change detected, reseting script.");
152 }
153 }
154 }
155
156 //The message link function is to allow other scripts to control the snapshot playback
157 //This command will display snapshot #2:
158 // llMessageLinked(LINK_ROOT, 2, "XDshow", NULL_KEY); llSleep(1.0);
159 //
160 //This command will play through all the recorded snapshots in ascending order. The number "1.0" is the delay speed and can be changed.
161 // llMessageLinked(LINK_ROOT, 0, "XDplay", "1.0");
162 //
163 //This command will loop through all the recorded snapshots in ascending order. The number "1.0" is the delay speed and can be changed.
164 // llMessageLinked(LINK_ROOT, 0, "XDplayLoop", "1.0");
165 //
166 //To stop any playing animation use
167 // llMessageLinked(LINK_ROOT, 0, "XDstop", NULL_KEY);
168 link_message(integer sender_num, integer num, string str, key id)
169 {
170 if("XDshow" == str && num >= 1 && num <= recordedSnapshots)
171 showSnapshot(num);
172 else if("XDplay" == str)
173 {
174 currentSnapshot = 1;
175 float delay = (float)((string)id);
176 playAnimation(delay,FALSE);
177 }
178 else if("XDplayLoop" == str)
179 {
180 float delay = (float)((string)id);
181 playAnimation(delay,TRUE);
182 }
183 else if("XDstop" == str)
184 {
185 playAnimationStyle = 0;
187 }
188 }
189
190 //This event handler takes care of all the editing commands.
191 //Available commands are: record, play, publish, show next, show prev, show #
192 listen(integer channel, string name, key id, string message)
193 {
194 list parsedMessage = llParseString2List(message, [" "], []);
195 string firstWord = llToLower(llList2String(parsedMessage,0));
196 string secondWord = llToLower(llList2String(parsedMessage,1));
197
198 //display a snapshot
199 if("show" == firstWord && recordedSnapshots > 0)
200 {
201 //stop any currently playing animation.
203
204 if(secondWord == "next")
205 {
206 currentSnapshot++;
207 if(currentSnapshot > recordedSnapshots)
208 currentSnapshot = 1;
209
210 showSnapshot(currentSnapshot);
211 }
212 else if(secondWord == "prev")
213 {
214 currentSnapshot--;
215 if(currentSnapshot < 1)
216 currentSnapshot = recordedSnapshots;
217
218 showSnapshot(currentSnapshot);
219 }
220 else
221 {
222 // when the conversion fails, snapshotNumber = 0
223 currentSnapshot = (integer)secondWord;
224 if(currentSnapshot > 0 && currentSnapshot <= recordedSnapshots )
225 {
226 showSnapshot(currentSnapshot);
227 llOwnerSay("Showing snapshot: "+(string)currentSnapshot);
228 }
229 else
230 {
231 llOwnerSay("Invalid snapshot number given: " + (string) currentSnapshot +
232 "\nA valid snapshot number is between 1 and " + (string) recordedSnapshots);
233 currentSnapshot = 1;
234 }
235 }
236 }
237 //record a snapshot
238 else if(firstWord == "record")
239 {
240 integer i = 0;
241 //2 is the first linked prim number.
242 vector rootPos = llGetPos();
243 for( i = 2; i <= primCount; i++)
244 {
245 vector pos = llList2Vector(llGetLinkPrimitiveParams(i, [PRIM_POSITION]),0);
246 //need to convert into local position
247 pos.x -= rootPos.x;
248 pos.z -= rootPos.z;
249 pos.y -= rootPos.y;
250 pos = pos / llGetRot();
251 posList += pos;
252
253 rotation rot = llList2Rot(llGetLinkPrimitiveParams(i, [PRIM_ROTATION]),0);
254 //Converting into local rot
255 rot = rot / llGetRot();
256 rotList += rot;
257
258 scaleList += llList2Vector(llGetLinkPrimitiveParams(i, [PRIM_SIZE]),0);
259 }
260 recordedSnapshots++;
261
262 llOwnerSay("Total number of snapshots recorded: " + (string)recordedSnapshots);
263 freeMemory = llGetFreeMemory();
264 }
265 //play the animation from beginning to end once without looping.
266 else if(firstWord == "play")
267 {
268 float delay = (float)secondWord;
269 currentSnapshot = 1;
270 //play the animation once without loop
271 playAnimation(delay, FALSE);
272 }
273 //publish disables the recording features and enables the on-touch trigger
274 else if("publish" == firstWord)
275 {
276 //stop any currently playing animation.
278 playAnimationStyle = 0;
279 currentSnapshot = 1;
280
281 //remove listeners to disable recording
282 llListenRemove(commandListenerHandle);
283 commandListenerHandle = -1; //indicating that it's been published
284
285 llOwnerSay("Recording disabled. Publish complete.\nClick me to toggle animation on/off.");
286 }
287
288 //if not published, show menu
289 if(commandListenerHandle != -1)
290 showMenuDialog();
291 }
292
293 //Timer event is used to handle the animation playback.
294 timer()
295 {
296 showSnapshot(currentSnapshot);
297
298 //if not at the end of the animation, increment the counter
299 if(currentSnapshot < recordedSnapshots)
300 currentSnapshot++;
301 else
302 {
303 // if animation is looping, set the counter back to 1
304 if( playAnimationStyle == 2)
305 currentSnapshot = 1;
306 // if animation isn't looping, stop the animation
307 else
308 {
310 //if not published, show dialog menu
311 if(commandListenerHandle != -1)
312 showMenuDialog();
313 }
314 }
315 }
316 }

Back to the Best Free Tools in Second Life and OpenSim.