aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs4
-rw-r--r--OpenSim/Region/Framework/Scenes/KeyframeMotion.cs315
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs12
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs3
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs138
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs1
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs13
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs7
9 files changed, 493 insertions, 2 deletions
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
index 93e22e0..2bebd30 100644
--- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
@@ -553,7 +553,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
553 { 553 {
554 Util.FireAndForget(delegate(object x) 554 Util.FireAndForget(delegate(object x)
555 { 555 {
556 Thread.Sleep(2000); 556 Thread.Sleep(4000);
557 557
558 // m_log.DebugFormat("[AVFACTORY]: Client_OnRequestWearables called for {0} ({1})", client.Name, client.AgentId); 558 // m_log.DebugFormat("[AVFACTORY]: Client_OnRequestWearables called for {0} ({1})", client.Name, client.AgentId);
559 ScenePresence sp = m_scene.GetScenePresence(client.AgentId); 559 ScenePresence sp = m_scene.GetScenePresence(client.AgentId);
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
index 6c4c63f..26650a5 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
@@ -355,6 +355,10 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
355 355
356 foreach (SceneObjectGroup objectGroup in objlist) 356 foreach (SceneObjectGroup objectGroup in objlist)
357 { 357 {
358 if (objectGroup.KeyframeMotion != null)
359 objectGroup.KeyframeMotion.Stop();
360 objectGroup.KeyframeMotion = null;
361
358 Vector3 inventoryStoredPosition = new Vector3 362 Vector3 inventoryStoredPosition = new Vector3
359 (((objectGroup.AbsolutePosition.X > (int)Constants.RegionSize) 363 (((objectGroup.AbsolutePosition.X > (int)Constants.RegionSize)
360 ? 250 364 ? 250
diff --git a/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs
new file mode 100644
index 0000000..239f7ca
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs
@@ -0,0 +1,315 @@
1// Proprietary code of Avination Virtual Limited
2// (c) 2012 Melanie Thielker
3//
4
5using System;
6using System.Timers;
7using System.Collections.Generic;
8using System.IO;
9using System.Diagnostics;
10using System.Reflection;
11using System.Threading;
12using OpenMetaverse;
13using OpenSim.Framework;
14using OpenSim.Region.Framework.Interfaces;
15using OpenSim.Region.Physics.Manager;
16using OpenSim.Region.Framework.Scenes.Serialization;
17using Timer = System.Timers.Timer;
18using log4net;
19
20namespace OpenSim.Region.Framework.Scenes
21{
22 public class KeyframeMotion
23 {
24 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
25
26 public enum PlayMode : int
27 {
28 Forward = 0,
29 Reverse = 1,
30 Loop = 2,
31 PingPong = 3
32 };
33
34 [Flags]
35 public enum DataFormat : int
36 {
37 Translation = 1,
38 Rotation = 2
39 }
40
41 public struct Keyframe
42 {
43 public Vector3? Position;
44 public Quaternion? Rotation;
45 public Quaternion StartRotation;
46 public int TimeMS;
47 public int TimeTotal;
48 public Vector3 AngularVelocity;
49 };
50
51 private Vector3 m_basePosition;
52 private Quaternion m_baseRotation;
53
54 private Keyframe m_currentFrame;
55 private List<Keyframe> m_frames = new List<Keyframe>();
56
57 private Keyframe[] m_keyframes;
58
59 private Timer m_timer = new Timer();
60
61 private readonly SceneObjectGroup m_group;
62
63 private PlayMode m_mode = PlayMode.Forward;
64 private DataFormat m_data = DataFormat.Translation | DataFormat.Rotation;
65
66 private int m_iterations = 0;
67
68 private const double timerInterval = 50.0;
69
70 public DataFormat Data
71 {
72 get { return m_data; }
73 }
74
75 public KeyframeMotion(SceneObjectGroup grp, PlayMode mode, DataFormat data)
76 {
77 m_mode = mode;
78 m_data = data;
79
80 m_group = grp;
81 m_basePosition = grp.AbsolutePosition;
82 m_baseRotation = grp.GroupRotation;
83
84 m_timer.Interval = (int)timerInterval;
85 m_timer.AutoReset = true;
86 m_timer.Elapsed += OnTimer;
87 }
88
89 public void SetKeyframes(Keyframe[] frames)
90 {
91 m_keyframes = frames;
92 }
93
94 public void Start()
95 {
96 if (m_keyframes.Length > 0)
97 m_timer.Start();
98 }
99
100 public void Stop()
101 {
102 m_timer.Stop();
103
104 m_basePosition = m_group.AbsolutePosition;
105 m_baseRotation = m_group.GroupRotation;
106
107 m_group.RootPart.Velocity = Vector3.Zero;
108 m_group.RootPart.UpdateAngularVelocity(Vector3.Zero);
109 m_group.SendGroupRootTerseUpdate();
110
111 m_frames.Clear();
112 }
113
114 public void Pause()
115 {
116 m_group.RootPart.Velocity = Vector3.Zero;
117 m_group.RootPart.UpdateAngularVelocity(Vector3.Zero);
118 m_group.SendGroupRootTerseUpdate();
119
120 m_timer.Stop();
121 }
122
123 private void GetNextList()
124 {
125 m_frames.Clear();
126 Vector3 pos = m_basePosition;
127 Quaternion rot = m_baseRotation;
128
129 if (m_mode == PlayMode.Loop || m_mode == PlayMode.PingPong || m_iterations == 0)
130 {
131 int direction = 1;
132 if (m_mode == PlayMode.Reverse || ((m_mode == PlayMode.PingPong) && ((m_iterations & 1) != 0)))
133 direction = -1;
134
135 int start = 0;
136 int end = m_keyframes.Length;
137// if (m_mode == PlayMode.PingPong && m_keyframes.Length > 1)
138// end = m_keyframes.Length - 1;
139
140 if (direction < 0)
141 {
142 start = m_keyframes.Length - 1;
143 end = -1;
144// if (m_mode == PlayMode.PingPong && m_keyframes.Length > 1)
145// end = 0;
146 }
147
148 for (int i = start; i != end ; i += direction)
149 {
150 Keyframe k = m_keyframes[i];
151
152 if (k.Position.HasValue)
153 k.Position = (k.Position * direction) + pos;
154 else
155 k.Position = pos;
156
157 k.StartRotation = rot;
158 if (k.Rotation.HasValue)
159 {
160 if (direction == -1)
161 k.Rotation = Quaternion.Conjugate((Quaternion)k.Rotation);
162 k.Rotation = rot * k.Rotation;
163 }
164 else
165 {
166 k.Rotation = rot;
167 }
168
169 float angle = 0;
170
171 float aa = k.StartRotation.X * k.StartRotation.X + k.StartRotation.Y * k.StartRotation.Y + k.StartRotation.Z * k.StartRotation.Z + k.StartRotation.W * k.StartRotation.W;
172 float bb = ((Quaternion)k.Rotation).X * ((Quaternion)k.Rotation).X + ((Quaternion)k.Rotation).Y * ((Quaternion)k.Rotation).Y + ((Quaternion)k.Rotation).Z * ((Quaternion)k.Rotation).Z + ((Quaternion)k.Rotation).W * ((Quaternion)k.Rotation).W;
173 float aa_bb = aa * bb;
174
175 if (aa_bb == 0)
176 {
177 angle = 0;
178 }
179 else
180 {
181 float ab = k.StartRotation.X * ((Quaternion)k.Rotation).X +
182 k.StartRotation.Y * ((Quaternion)k.Rotation).Y +
183 k.StartRotation.Z * ((Quaternion)k.Rotation).Z +
184 k.StartRotation.W * ((Quaternion)k.Rotation).W;
185 float q = (ab * ab) / aa_bb;
186
187 if (q > 1.0f)
188 {
189 angle = 0;
190 }
191 else
192 {
193 angle = (float)Math.Acos(2 * q - 1);
194 }
195 }
196
197 m_log.DebugFormat("[KEYFRAME]: Angle {0} aabb {1}", angle, aa_bb);
198 k.AngularVelocity = (new Vector3(0, 0, 1) * (Quaternion)k.Rotation) * (angle / (k.TimeMS / 1000));
199 k.TimeTotal = k.TimeMS;
200
201 m_frames.Add(k);
202
203 pos = (Vector3)k.Position;
204 rot = (Quaternion)k.Rotation;
205 }
206
207 m_basePosition = pos;
208 m_baseRotation = rot;
209
210 m_iterations++;
211 }
212 }
213
214 private void OnTimer(object sender, ElapsedEventArgs e)
215 {
216 if (m_frames.Count == 0)
217 {
218 GetNextList();
219
220 if (m_frames.Count == 0)
221 {
222 Stop();
223 return;
224 }
225
226 m_currentFrame = m_frames[0];
227 }
228
229 // Do the frame processing
230 double steps = (double)m_currentFrame.TimeMS / timerInterval;
231 float complete = ((float)m_currentFrame.TimeTotal - (float)m_currentFrame.TimeMS) / (float)m_currentFrame.TimeTotal;
232
233 if (steps <= 1.0)
234 {
235 m_currentFrame.TimeMS = 0;
236
237 m_group.AbsolutePosition = (Vector3)m_currentFrame.Position;
238 m_group.UpdateGroupRotationR((Quaternion)m_currentFrame.Rotation);
239 }
240 else
241 {
242 Vector3 v = (Vector3)m_currentFrame.Position - m_group.AbsolutePosition;
243 Vector3 motionThisFrame = v / (float)steps;
244 v = v * 1000 / m_currentFrame.TimeMS;
245
246 bool update = false;
247
248 if (Vector3.Mag(motionThisFrame) >= 0.05f)
249 {
250 m_group.AbsolutePosition += motionThisFrame;
251 m_group.RootPart.Velocity = v;
252 update = true;
253 }
254
255 if ((Quaternion)m_currentFrame.Rotation != m_group.GroupRotation)
256 {
257 Quaternion current = m_group.GroupRotation;
258
259 Quaternion step = Quaternion.Slerp(m_currentFrame.StartRotation, (Quaternion)m_currentFrame.Rotation, complete);
260
261 float angle = 0;
262
263 float aa = current.X * current.X + current.Y * current.Y + current.Z * current.Z + current.W * current.W;
264 float bb = step.X * step.X + step.Y * step.Y + step.Z * step.Z + step.W * step.W;
265 float aa_bb = aa * bb;
266
267 if (aa_bb == 0)
268 {
269 angle = 0;
270 }
271 else
272 {
273 float ab = current.X * step.X +
274 current.Y * step.Y +
275 current.Z * step.Z +
276 current.W * step.W;
277 float q = (ab * ab) / aa_bb;
278
279 if (q > 1.0f)
280 {
281 angle = 0;
282 }
283 else
284 {
285 angle = (float)Math.Acos(2 * q - 1);
286 }
287 }
288
289 if (angle > 0.01f)
290 {
291 m_group.UpdateGroupRotationR(step);
292 //m_group.RootPart.UpdateAngularVelocity(m_currentFrame.AngularVelocity / 2);
293 update = true;
294 }
295 }
296
297 if (update)
298 m_group.SendGroupRootTerseUpdate();
299 }
300
301 m_currentFrame.TimeMS -= (int)timerInterval;
302
303 if (m_currentFrame.TimeMS <= 0)
304 {
305 m_group.RootPart.Velocity = Vector3.Zero;
306 m_group.RootPart.UpdateAngularVelocity(Vector3.Zero);
307 m_group.SendGroupRootTerseUpdate();
308
309 m_frames.RemoveAt(0);
310 if (m_frames.Count > 0)
311 m_currentFrame = m_frames[0];
312 }
313 }
314 }
315}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index e9021f1..9898681 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -114,6 +114,12 @@ namespace OpenSim.Region.Framework.Scenes
114 private Random m_rand; 114 private Random m_rand;
115 private bool m_suspendUpdates; 115 private bool m_suspendUpdates;
116 private List<ScenePresence> m_linkedAvatars = new List<ScenePresence>(); 116 private List<ScenePresence> m_linkedAvatars = new List<ScenePresence>();
117 private KeyframeMotion m_keyframeMotion = null;
118
119 public KeyframeMotion KeyframeMotion
120 {
121 get; set;
122 }
117 123
118 public bool areUpdatesSuspended 124 public bool areUpdatesSuspended
119 { 125 {
@@ -1982,6 +1988,12 @@ namespace OpenSim.Region.Framework.Scenes
1982 1988
1983 public void ScriptSetPhysicsStatus(bool usePhysics) 1989 public void ScriptSetPhysicsStatus(bool usePhysics)
1984 { 1990 {
1991 if (usePhysics)
1992 {
1993 if (KeyframeMotion != null)
1994 KeyframeMotion.Stop();
1995 KeyframeMotion = null;
1996 }
1985 UpdatePrimFlags(RootPart.LocalId, usePhysics, IsTemporary, IsPhantom, IsVolumeDetect); 1997 UpdatePrimFlags(RootPart.LocalId, usePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
1986 } 1998 }
1987 1999
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index f35a27e..825f2a3 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -1921,6 +1921,9 @@ namespace OpenSim.Region.Framework.Scenes
1921 { 1921 {
1922 if (UsePhysics) 1922 if (UsePhysics)
1923 { 1923 {
1924 if (ParentGroup.KeyframeMotion != null)
1925 ParentGroup.KeyframeMotion.Stop();
1926 ParentGroup.KeyframeMotion = null;
1924 ParentGroup.Scene.AddPhysicalPrim(1); 1927 ParentGroup.Scene.AddPhysicalPrim(1);
1925 1928
1926 PhysActor.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate; 1929 PhysActor.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate;
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index d0430f4..9090311 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -11896,6 +11896,144 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11896 } 11896 }
11897 11897
11898 #endregion 11898 #endregion
11899
11900 public void llSetKeyframedMotion(LSL_List frames, LSL_List options)
11901 {
11902 SceneObjectGroup group = m_host.ParentGroup;
11903
11904 if (group.RootPart.PhysActor != null && group.RootPart.PhysActor.IsPhysical)
11905 return;
11906 if (group.IsAttachment)
11907 return;
11908
11909 if (frames.Data.Length > 0) // We are getting a new motion
11910 {
11911 if (group.KeyframeMotion != null)
11912 group.KeyframeMotion.Stop();
11913 group.KeyframeMotion = null;
11914
11915 int idx = 0;
11916
11917 KeyframeMotion.PlayMode mode = KeyframeMotion.PlayMode.Forward;
11918 KeyframeMotion.DataFormat data = KeyframeMotion.DataFormat.Translation | KeyframeMotion.DataFormat.Rotation;
11919
11920 while (idx < options.Data.Length)
11921 {
11922 int option = (int)options.GetLSLIntegerItem(idx++);
11923 int remain = options.Data.Length - idx;
11924
11925 switch (option)
11926 {
11927 case ScriptBaseClass.KFM_MODE:
11928 if (remain < 1)
11929 break;
11930 int modeval = (int)options.GetLSLIntegerItem(idx++);
11931 switch(modeval)
11932 {
11933 case ScriptBaseClass.KFM_FORWARD:
11934 mode = KeyframeMotion.PlayMode.Forward;
11935 break;
11936 case ScriptBaseClass.KFM_REVERSE:
11937 mode = KeyframeMotion.PlayMode.Reverse;
11938 break;
11939 case ScriptBaseClass.KFM_LOOP:
11940 mode = KeyframeMotion.PlayMode.Loop;
11941 break;
11942 case ScriptBaseClass.KFM_PING_PONG:
11943 mode = KeyframeMotion.PlayMode.PingPong;
11944 break;
11945 }
11946 break;
11947 case ScriptBaseClass.KFM_DATA:
11948 if (remain < 1)
11949 break;
11950 int dataval = (int)options.GetLSLIntegerItem(idx++);
11951 data = (KeyframeMotion.DataFormat)dataval;
11952 break;
11953 }
11954 }
11955
11956 group.KeyframeMotion = new KeyframeMotion(group, mode, data);
11957
11958 idx = 0;
11959
11960 int elemLength = 2;
11961 if (data == (KeyframeMotion.DataFormat.Translation | KeyframeMotion.DataFormat.Rotation))
11962 elemLength = 3;
11963
11964 List<KeyframeMotion.Keyframe> keyframes = new List<KeyframeMotion.Keyframe>();
11965 while (idx < frames.Data.Length)
11966 {
11967 int remain = frames.Data.Length - idx;
11968
11969 if (remain < elemLength)
11970 break;
11971
11972 KeyframeMotion.Keyframe frame = new KeyframeMotion.Keyframe();
11973 frame.Position = null;
11974 frame.Rotation = null;
11975
11976 if ((data & KeyframeMotion.DataFormat.Translation) != 0)
11977 {
11978 LSL_Types.Vector3 tempv = frames.GetVector3Item(idx++);
11979 frame.Position = new Vector3((float)tempv.x, (float)tempv.y, (float)tempv.z);
11980 }
11981 if ((data & KeyframeMotion.DataFormat.Rotation) != 0)
11982 {
11983 LSL_Types.Quaternion tempq = frames.GetQuaternionItem(idx++);
11984 frame.Rotation = new Quaternion((float)tempq.x, (float)tempq.y, (float)tempq.z, (float)tempq.s);
11985 }
11986
11987 float tempf = (float)frames.GetLSLFloatItem(idx++);
11988 frame.TimeMS = (int)(tempf * 1000.0f);
11989
11990 keyframes.Add(frame);
11991 }
11992
11993 group.KeyframeMotion.SetKeyframes(keyframes.ToArray());
11994 group.KeyframeMotion.Start();
11995 }
11996 else
11997 {
11998 if (group.KeyframeMotion == null)
11999 return;
12000
12001 if (options.Data.Length == 0)
12002 {
12003 group.KeyframeMotion.Stop();
12004 return;
12005 }
12006
12007 int code = (int)options.GetLSLIntegerItem(0);
12008
12009 int idx = 0;
12010
12011 while (idx < options.Data.Length)
12012 {
12013 int option = (int)options.GetLSLIntegerItem(idx++);
12014 int remain = options.Data.Length - idx;
12015
12016 switch (option)
12017 {
12018 case ScriptBaseClass.KFM_COMMAND:
12019 int cmd = (int)options.GetLSLIntegerItem(idx++);
12020 switch (cmd)
12021 {
12022 case ScriptBaseClass.KFM_CMD_PLAY:
12023 group.KeyframeMotion.Start();
12024 break;
12025 case ScriptBaseClass.KFM_CMD_STOP:
12026 group.KeyframeMotion.Stop();
12027 break;
12028 case ScriptBaseClass.KFM_CMD_PAUSE:
12029 group.KeyframeMotion.Pause();
12030 break;
12031 }
12032 break;
12033 }
12034 }
12035 }
12036 }
11899 } 12037 }
11900 12038
11901 public class NotecardCache 12039 public class NotecardCache
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs
index 9679798..99bfc97 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs
@@ -415,5 +415,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
415 415
416 void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules); 416 void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules);
417 LSL_List GetLinkPrimitiveParamsEx(LSL_Key prim, LSL_List rules); 417 LSL_List GetLinkPrimitiveParamsEx(LSL_Key prim, LSL_List rules);
418 void llSetKeyframedMotion(LSL_List frames, LSL_List options);
418 } 419 }
419} 420}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
index 3d0e5cb..a5e160d 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
@@ -641,5 +641,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
641 public static readonly LSLInteger RCERR_UNKNOWN = -1; 641 public static readonly LSLInteger RCERR_UNKNOWN = -1;
642 public static readonly LSLInteger RCERR_SIM_PERF_LOW = -2; 642 public static readonly LSLInteger RCERR_SIM_PERF_LOW = -2;
643 public static readonly LSLInteger RCERR_CAST_TIME_EXCEEDED = 3; 643 public static readonly LSLInteger RCERR_CAST_TIME_EXCEEDED = 3;
644
645 public const int KFM_MODE = 1;
646 public const int KFM_LOOP = 1;
647 public const int KFM_REVERSE = 3;
648 public const int KFM_FORWARD = 0;
649 public const int KFM_PING_PONG = 2;
650 public const int KFM_DATA = 2;
651 public const int KFM_TRANSLATION = 2;
652 public const int KFM_ROTATION = 1;
653 public const int KFM_COMMAND = 0;
654 public const int KFM_CMD_PLAY = 0;
655 public const int KFM_CMD_STOP = 1;
656 public const int KFM_CMD_PAUSE = 2;
644 } 657 }
645} 658}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs
index dcaa3b4..9c4437d 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs
@@ -1917,7 +1917,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
1917 1917
1918 public LSL_Integer llGetLinkNumberOfSides(LSL_Integer link) 1918 public LSL_Integer llGetLinkNumberOfSides(LSL_Integer link)
1919 { 1919 {
1920 return m_LSL_Functions.llGetLinkNumberOfSides(link); 1920 return m_LSL_Functions.llGetLinkNumberOfSides(link);
1921 }
1922
1923 public void llSetKeyframedMotion(LSL_List frames, LSL_List options)
1924 {
1925 m_LSL_Functions.llSetKeyframedMotion(frames, options);
1921 } 1926 }
1922 } 1927 }
1923} 1928}