aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Framework')
-rw-r--r--OpenSim/Region/Framework/Scenes/KeyframeMotion.cs546
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs60
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs6
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs24
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs8
-rw-r--r--OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs2
6 files changed, 495 insertions, 151 deletions
diff --git a/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs
index b7b0d27..e4e6f2c 100644
--- a/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs
+++ b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs
@@ -38,8 +38,8 @@ namespace OpenSim.Region.Framework.Scenes
38 [Flags] 38 [Flags]
39 public enum DataFormat : int 39 public enum DataFormat : int
40 { 40 {
41 Translation = 1, 41 Translation = 2,
42 Rotation = 2 42 Rotation = 1
43 } 43 }
44 44
45 [Serializable] 45 [Serializable]
@@ -53,17 +53,42 @@ namespace OpenSim.Region.Framework.Scenes
53 public Vector3 AngularVelocity; 53 public Vector3 AngularVelocity;
54 }; 54 };
55 55
56 private Vector3 m_serializedPosition;
56 private Vector3 m_basePosition; 57 private Vector3 m_basePosition;
57 private Quaternion m_baseRotation; 58 private Quaternion m_baseRotation;
58 private Vector3 m_serializedPosition;
59 59
60 private Keyframe m_currentFrame; 60 private Keyframe m_currentFrame;
61
61 private List<Keyframe> m_frames = new List<Keyframe>(); 62 private List<Keyframe> m_frames = new List<Keyframe>();
62 63
63 private Keyframe[] m_keyframes; 64 private Keyframe[] m_keyframes;
64 65
65 [NonSerialized()] 66 [NonSerialized()]
66 protected Timer m_timer = new Timer(); 67 protected Timer m_timer = null;
68
69 // timer lock
70 [NonSerialized()]
71 private object m_onTimerLock;
72
73 // timer overrun detect
74 // prevents overlap or timer events threads frozen on the lock
75 [NonSerialized()]
76 private bool m_inOnTimer;
77
78 // skip timer events.
79 //timer.stop doesn't assure there aren't event threads still being fired
80 [NonSerialized()]
81 private bool m_timerStopped;
82
83 [NonSerialized()]
84 private bool m_isCrossing;
85
86 [NonSerialized()]
87 private bool m_waitingCrossing;
88
89 // retry position for cross fail
90 [NonSerialized()]
91 private Vector3 m_nextPosition;
67 92
68 [NonSerialized()] 93 [NonSerialized()]
69 private SceneObjectGroup m_group; 94 private SceneObjectGroup m_group;
@@ -88,54 +113,120 @@ namespace OpenSim.Region.Framework.Scenes
88 { 113 {
89 set 114 set
90 { 115 {
91 if (value) 116 if (m_group != null)
92 { 117 {
93 // Once we're let go, recompute positions 118 if (!value)
94 if (m_selected) 119 {
95 UpdateSceneObject(m_group); 120 // Once we're let go, recompute positions
96 } 121 if (m_selected)
97 else 122 UpdateSceneObject(m_group);
98 { 123 }
99 // Save selection position in case we get moved 124 else
100 if (!m_selected) 125 {
101 m_serializedPosition = m_group.AbsolutePosition; 126 // Save selection position in case we get moved
127 if (!m_selected)
128 {
129 StopTimer();
130 m_serializedPosition = m_group.AbsolutePosition;
131 }
132 }
102 } 133 }
103 m_selected = value; } 134 m_isCrossing = false;
135 m_waitingCrossing = false;
136 m_selected = value;
137 }
104 } 138 }
105 139
140 private void StartTimer()
141 {
142 if (m_timer == null)
143 return;
144 m_timerStopped = false;
145 m_timer.Start();
146 }
147
148 private void StopTimer()
149 {
150 if (m_timer == null || m_timerStopped)
151 return;
152 m_timerStopped = true;
153 m_timer.Stop();
154 }
155
156 private void RemoveTimer()
157 {
158 if (m_timer == null)
159 return;
160 m_timerStopped = true;
161 m_timer.Stop();
162 m_timer.Elapsed -= OnTimer;
163 m_timer = null;
164 }
165
166
106 public static KeyframeMotion FromData(SceneObjectGroup grp, Byte[] data) 167 public static KeyframeMotion FromData(SceneObjectGroup grp, Byte[] data)
107 { 168 {
108 MemoryStream ms = new MemoryStream(data); 169 KeyframeMotion newMotion = null;
109 170
110 BinaryFormatter fmt = new BinaryFormatter(); 171 try
172 {
173 MemoryStream ms = new MemoryStream(data);
174 BinaryFormatter fmt = new BinaryFormatter();
175
176 newMotion = (KeyframeMotion)fmt.Deserialize(ms);
177
178 newMotion.m_group = grp;
111 179
112 KeyframeMotion newMotion = (KeyframeMotion)fmt.Deserialize(ms); 180 if (grp != null && grp.IsSelected)
181 newMotion.m_selected = true;
113 182
114 // This will be started when position is updated 183 newMotion.m_onTimerLock = new object();
115 newMotion.m_timer = new Timer(); 184 newMotion.m_timerStopped = false;
116 newMotion.m_timer.Interval = (int)timerInterval; 185 newMotion.m_inOnTimer = false;
117 newMotion.m_timer.AutoReset = true; 186 newMotion.m_isCrossing = false;
118 newMotion.m_timer.Elapsed += newMotion.OnTimer; 187 newMotion.m_waitingCrossing = false;
188 }
189 catch
190 {
191 newMotion = null;
192 }
119 193
120 return newMotion; 194 return newMotion;
121 } 195 }
122 196
123 public void UpdateSceneObject(SceneObjectGroup grp) 197 public void UpdateSceneObject(SceneObjectGroup grp)
124 { 198 {
125 m_group = grp; 199// lock (m_onTimerLock)
126 Vector3 offset = grp.AbsolutePosition - m_serializedPosition;
127
128 m_basePosition += offset;
129 m_currentFrame.Position += offset;
130 for (int i = 0 ; i < m_frames.Count ; i++)
131 { 200 {
132 Keyframe k = m_frames[i]; 201 m_isCrossing = false;
133 k.Position += offset; 202 m_waitingCrossing = false;
134 m_frames[i] = k; 203 StopTimer();
135 } 204
205 if (grp == null)
206 return;
207
208 m_group = grp;
209 Vector3 grppos = grp.AbsolutePosition;
210 Vector3 offset = grppos - m_serializedPosition;
211 // avoid doing it more than once
212 // current this will happen draging a prim to other region
213 m_serializedPosition = grppos;
214
215 m_basePosition += offset;
216 m_currentFrame.Position += offset;
136 217
137 if (m_running) 218 m_nextPosition += offset;
138 Start(); 219
220 for (int i = 0; i < m_frames.Count; i++)
221 {
222 Keyframe k = m_frames[i];
223 k.Position += offset;
224 m_frames[i]=k;
225 }
226
227 if (m_running)
228 Start();
229 }
139 } 230 }
140 231
141 public KeyframeMotion(SceneObjectGroup grp, PlayMode mode, DataFormat data) 232 public KeyframeMotion(SceneObjectGroup grp, PlayMode mode, DataFormat data)
@@ -144,12 +235,17 @@ namespace OpenSim.Region.Framework.Scenes
144 m_data = data; 235 m_data = data;
145 236
146 m_group = grp; 237 m_group = grp;
147 m_basePosition = grp.AbsolutePosition; 238 if (grp != null)
148 m_baseRotation = grp.GroupRotation; 239 {
240 m_basePosition = grp.AbsolutePosition;
241 m_baseRotation = grp.GroupRotation;
242 }
149 243
150 m_timer.Interval = (int)timerInterval; 244 m_onTimerLock = new object();
151 m_timer.AutoReset = true; 245 m_timerStopped = true;
152 m_timer.Elapsed += OnTimer; 246 m_inOnTimer = false;
247 m_isCrossing = false;
248 m_waitingCrossing = false;
153 } 249 }
154 250
155 public void SetKeyframes(Keyframe[] frames) 251 public void SetKeyframes(Keyframe[] frames)
@@ -157,19 +253,93 @@ namespace OpenSim.Region.Framework.Scenes
157 m_keyframes = frames; 253 m_keyframes = frames;
158 } 254 }
159 255
256 public KeyframeMotion Copy(SceneObjectGroup newgrp)
257 {
258 StopTimer();
259
260 KeyframeMotion newmotion = new KeyframeMotion(null, m_mode, m_data);
261
262 newmotion.m_group = newgrp;
263
264 if (m_keyframes != null)
265 {
266 newmotion.m_keyframes = new Keyframe[m_keyframes.Length];
267 m_keyframes.CopyTo(newmotion.m_keyframes, 0);
268 }
269
270 newmotion.m_frames = new List<Keyframe>(m_frames);
271
272 newmotion.m_basePosition = m_basePosition;
273 newmotion.m_baseRotation = m_baseRotation;
274
275 newmotion.m_currentFrame = m_currentFrame;
276
277 if (m_selected)
278 newmotion.m_serializedPosition = m_serializedPosition;
279 else
280 {
281 if (m_group != null)
282 newmotion.m_serializedPosition = m_group.AbsolutePosition;
283 else
284 newmotion.m_serializedPosition = m_serializedPosition;
285 }
286
287 newmotion.m_iterations = m_iterations;
288 newmotion.m_running = m_running;
289
290 if (m_running && !m_waitingCrossing)
291 StartTimer();
292
293 return newmotion;
294 }
295
296 public void Delete()
297 {
298 m_running = false;
299 RemoveTimer();
300 m_isCrossing = false;
301 m_waitingCrossing = false;
302 m_frames.Clear();
303 m_keyframes = null;
304 }
305
160 public void Start() 306 public void Start()
161 { 307 {
162 if (m_keyframes.Length > 0) 308 m_isCrossing = false;
163 m_timer.Start(); 309 m_waitingCrossing = false;
164 m_running = true; 310 if (m_keyframes != null && m_group != null && m_keyframes.Length > 0)
311 {
312 if (m_timer == null)
313 {
314 m_timer = new Timer();
315 m_timer.Interval = timerInterval;
316 m_timer.AutoReset = true;
317 m_timer.Elapsed += OnTimer;
318 }
319 else
320 {
321 StopTimer();
322 m_timer.Interval = timerInterval;
323 }
324
325 m_inOnTimer = false;
326 StartTimer();
327 m_running = true;
328 }
329 else
330 {
331 m_running = false;
332 RemoveTimer();
333 }
165 } 334 }
166 335
167 public void Stop() 336 public void Stop()
168 { 337 {
169 // Failed object creation 338 m_running = false;
170 if (m_timer == null) 339 m_isCrossing = false;
171 return; 340 m_waitingCrossing = false;
172 m_timer.Stop(); 341
342 RemoveTimer();
173 343
174 m_basePosition = m_group.AbsolutePosition; 344 m_basePosition = m_group.AbsolutePosition;
175 m_baseRotation = m_group.GroupRotation; 345 m_baseRotation = m_group.GroupRotation;
@@ -179,17 +349,16 @@ namespace OpenSim.Region.Framework.Scenes
179 m_group.SendGroupRootTerseUpdate(); 349 m_group.SendGroupRootTerseUpdate();
180 350
181 m_frames.Clear(); 351 m_frames.Clear();
182 m_running = false;
183 } 352 }
184 353
185 public void Pause() 354 public void Pause()
186 { 355 {
356 m_running = false;
357 RemoveTimer();
358
187 m_group.RootPart.Velocity = Vector3.Zero; 359 m_group.RootPart.Velocity = Vector3.Zero;
188 m_group.RootPart.UpdateAngularVelocity(Vector3.Zero); 360 m_group.RootPart.UpdateAngularVelocity(Vector3.Zero);
189 m_group.SendGroupRootTerseUpdate(); 361 m_group.SendGroupRootTerseUpdate();
190
191 m_timer.Stop();
192 m_running = false;
193 } 362 }
194 363
195 private void GetNextList() 364 private void GetNextList()
@@ -222,9 +391,16 @@ namespace OpenSim.Region.Framework.Scenes
222 Keyframe k = m_keyframes[i]; 391 Keyframe k = m_keyframes[i];
223 392
224 if (k.Position.HasValue) 393 if (k.Position.HasValue)
225 k.Position = (k.Position * direction) + pos; 394 {
395 k.Position = (k.Position * direction);
396// k.Velocity = (Vector3)k.Position / (k.TimeMS / 1000.0f);
397 k.Position += pos;
398 }
226 else 399 else
400 {
227 k.Position = pos; 401 k.Position = pos;
402// k.Velocity = Vector3.Zero;
403 }
228 404
229 k.StartRotation = rot; 405 k.StartRotation = rot;
230 if (k.Rotation.HasValue) 406 if (k.Rotation.HasValue)
@@ -238,6 +414,8 @@ namespace OpenSim.Region.Framework.Scenes
238 k.Rotation = rot; 414 k.Rotation = rot;
239 } 415 }
240 416
417/* ang vel not in use for now
418
241 float angle = 0; 419 float angle = 0;
242 420
243 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; 421 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;
@@ -267,6 +445,7 @@ namespace OpenSim.Region.Framework.Scenes
267 } 445 }
268 446
269 k.AngularVelocity = (new Vector3(0, 0, 1) * (Quaternion)k.Rotation) * (angle / (k.TimeMS / 1000)); 447 k.AngularVelocity = (new Vector3(0, 0, 1) * (Quaternion)k.Rotation) * (angle / (k.TimeMS / 1000));
448 */
270 k.TimeTotal = k.TimeMS; 449 k.TimeTotal = k.TimeMS;
271 450
272 m_frames.Add(k); 451 m_frames.Add(k);
@@ -284,139 +463,232 @@ namespace OpenSim.Region.Framework.Scenes
284 463
285 protected void OnTimer(object sender, ElapsedEventArgs e) 464 protected void OnTimer(object sender, ElapsedEventArgs e)
286 { 465 {
287 if (m_frames.Count == 0) 466 if (m_timerStopped) // trap events still in air even after a timer.stop
288 { 467 return;
289 GetNextList();
290
291 if (m_frames.Count == 0)
292 {
293 Stop();
294 return;
295 }
296
297 m_currentFrame = m_frames[0];
298 }
299 468
300 if (m_selected) 469 if (m_inOnTimer) // don't let overruns to happen
301 { 470 {
302 if (m_group.RootPart.Velocity != Vector3.Zero) 471 m_log.Warn("[KeyFrame]: timer overrun");
303 {
304 m_group.RootPart.Velocity = Vector3.Zero;
305 m_group.SendGroupRootTerseUpdate();
306 }
307 return; 472 return;
308 } 473 }
309 474
310 // Do the frame processing 475 if (m_group == null)
311 double steps = (double)m_currentFrame.TimeMS / timerInterval; 476 return;
312 float complete = ((float)m_currentFrame.TimeTotal - (float)m_currentFrame.TimeMS) / (float)m_currentFrame.TimeTotal;
313 477
314 if (steps <= 1.0) 478 lock (m_onTimerLock)
315 { 479 {
316 m_currentFrame.TimeMS = 0;
317 480
318 m_group.AbsolutePosition = (Vector3)m_currentFrame.Position; 481 m_inOnTimer = true;
319 m_group.UpdateGroupRotationR((Quaternion)m_currentFrame.Rotation);
320 }
321 else
322 {
323 Vector3 v = (Vector3)m_currentFrame.Position - m_group.AbsolutePosition;
324 Vector3 motionThisFrame = v / (float)steps;
325 v = v * 1000 / m_currentFrame.TimeMS;
326 482
327 bool update = false; 483 bool update = false;
328 484
329 if (Vector3.Mag(motionThisFrame) >= 0.05f) 485 try
330 { 486 {
331 m_group.AbsolutePosition += motionThisFrame; 487 if (m_selected)
332 m_group.RootPart.Velocity = v; 488 {
333 update = true; 489 if (m_group.RootPart.Velocity != Vector3.Zero)
334 } 490 {
491 m_group.RootPart.Velocity = Vector3.Zero;
492 m_group.SendGroupRootTerseUpdate();
493 }
494 m_inOnTimer = false;
495 return;
496 }
335 497
336 if ((Quaternion)m_currentFrame.Rotation != m_group.GroupRotation) 498 if (m_isCrossing)
337 { 499 {
338 Quaternion current = m_group.GroupRotation; 500 // if crossing and timer running then cross failed
501 // wait some time then
502 // retry to set the position that evtually caused the outbound
503 // if still outside region this will call startCrossing below
504 m_isCrossing = false;
505 m_group.AbsolutePosition = m_nextPosition;
506 if (!m_isCrossing)
507 {
508 StopTimer();
509 m_timer.Interval = timerInterval;
510 StartTimer();
511 }
512 m_inOnTimer = false;
513 return;
514 }
339 515
340 Quaternion step = Quaternion.Slerp(m_currentFrame.StartRotation, (Quaternion)m_currentFrame.Rotation, complete); 516 if (m_frames.Count == 0)
517 {
518 GetNextList();
341 519
342 float angle = 0; 520 if (m_frames.Count == 0)
521 {
522 Stop();
523 m_inOnTimer = false;
524 return;
525 }
343 526
344 float aa = current.X * current.X + current.Y * current.Y + current.Z * current.Z + current.W * current.W; 527 m_currentFrame = m_frames[0];
345 float bb = step.X * step.X + step.Y * step.Y + step.Z * step.Z + step.W * step.W; 528 m_currentFrame.TimeMS += (int)timerInterval;
346 float aa_bb = aa * bb;
347 529
348 if (aa_bb == 0) 530 //force a update on a keyframe transition
531 update = true;
532 }
533
534 m_currentFrame.TimeMS -= (int)timerInterval;
535
536 // Do the frame processing
537 double steps = (double)m_currentFrame.TimeMS / timerInterval;
538
539 if (steps <= 0.0)
349 { 540 {
350 angle = 0; 541 m_group.RootPart.Velocity = Vector3.Zero;
542 m_group.RootPart.UpdateAngularVelocity(Vector3.Zero);
543
544 m_nextPosition = (Vector3)m_currentFrame.Position;
545 m_group.AbsolutePosition = m_nextPosition;
546
547 m_group.UpdateGroupRotationR((Quaternion)m_currentFrame.Rotation);
548
549 m_frames.RemoveAt(0);
550 if (m_frames.Count > 0)
551 m_currentFrame = m_frames[0];
552
553 update = true;
351 } 554 }
352 else 555 else
353 { 556 {
354 float ab = current.X * step.X + 557 float complete = ((float)m_currentFrame.TimeTotal - (float)m_currentFrame.TimeMS) / (float)m_currentFrame.TimeTotal;
355 current.Y * step.Y +
356 current.Z * step.Z +
357 current.W * step.W;
358 float q = (ab * ab) / aa_bb;
359 558
360 if (q > 1.0f) 559 Vector3 v = (Vector3)m_currentFrame.Position - m_group.AbsolutePosition;
560 Vector3 motionThisFrame = v / (float)steps;
561 v = v * 1000 / m_currentFrame.TimeMS;
562
563 if (Vector3.Mag(motionThisFrame) >= 0.05f)
361 { 564 {
362 angle = 0; 565 // m_group.AbsolutePosition += motionThisFrame;
566 m_nextPosition = m_group.AbsolutePosition + motionThisFrame;
567 m_group.AbsolutePosition = m_nextPosition;
568
569 m_group.RootPart.Velocity = v;
570 update = true;
363 } 571 }
364 else 572
573 if ((Quaternion)m_currentFrame.Rotation != m_group.GroupRotation)
365 { 574 {
366 angle = (float)Math.Acos(2 * q - 1); 575 Quaternion current = m_group.GroupRotation;
576
577 Quaternion step = Quaternion.Slerp(m_currentFrame.StartRotation, (Quaternion)m_currentFrame.Rotation, complete);
578/* use simpler change detection
579 * float angle = 0;
580
581 float aa = current.X * current.X + current.Y * current.Y + current.Z * current.Z + current.W * current.W;
582 float bb = step.X * step.X + step.Y * step.Y + step.Z * step.Z + step.W * step.W;
583 float aa_bb = aa * bb;
584
585 if (aa_bb == 0)
586 {
587 angle = 0;
588 }
589 else
590 {
591 float ab = current.X * step.X +
592 current.Y * step.Y +
593 current.Z * step.Z +
594 current.W * step.W;
595 float q = (ab * ab) / aa_bb;
596
597 if (q > 1.0f)
598 {
599 angle = 0;
600 }
601 else
602 {
603 angle = (float)Math.Acos(2 * q - 1);
604 }
605 }
606
607 if (angle > 0.01f)
608 */
609 if(Math.Abs(step.X - current.X) > 0.001f
610 || Math.Abs(step.Y - current.Y) > 0.001f
611 || Math.Abs(step.Z - current.Z) > 0.001f)
612 // assuming w is a dependente var
613
614 {
615 m_group.UpdateGroupRotationR(step);
616 //m_group.RootPart.UpdateAngularVelocity(m_currentFrame.AngularVelocity / 2);
617 update = true;
618 }
367 } 619 }
368 } 620 }
369 621
370 if (angle > 0.01f) 622 if (update)
371 { 623 m_group.SendGroupRootTerseUpdate();
372 m_group.UpdateGroupRotationR(step);
373 //m_group.RootPart.UpdateAngularVelocity(m_currentFrame.AngularVelocity / 2);
374 update = true;
375 }
376 }
377
378 if (update)
379 m_group.SendGroupRootTerseUpdate();
380 }
381
382 m_currentFrame.TimeMS -= (int)timerInterval;
383 624
384 if (m_currentFrame.TimeMS <= 0) 625 }
385 { 626 catch ( Exception ex)
386 m_group.RootPart.Velocity = Vector3.Zero; 627 {
387 m_group.RootPart.UpdateAngularVelocity(Vector3.Zero); 628 // still happening sometimes
388 m_group.SendGroupRootTerseUpdate(); 629 // lets try to see where
630 m_log.Warn("[KeyFrame]: timer overrun" + ex.Message);
631 }
389 632
390 m_frames.RemoveAt(0); 633 finally
391 if (m_frames.Count > 0) 634 {
392 m_currentFrame = m_frames[0]; 635 // make sure we do not let this frozen
636 m_inOnTimer = false;
637 }
393 } 638 }
394 } 639 }
395 640
396 public Byte[] Serialize() 641 public Byte[] Serialize()
397 { 642 {
643 StopTimer();
398 MemoryStream ms = new MemoryStream(); 644 MemoryStream ms = new MemoryStream();
399 m_timer.Stop();
400 645
401 BinaryFormatter fmt = new BinaryFormatter(); 646 BinaryFormatter fmt = new BinaryFormatter();
402 SceneObjectGroup tmp = m_group; 647 SceneObjectGroup tmp = m_group;
403 m_group = null; 648 m_group = null;
404 m_serializedPosition = tmp.AbsolutePosition; 649 if (!m_selected && tmp != null)
650 m_serializedPosition = tmp.AbsolutePosition;
405 fmt.Serialize(ms, this); 651 fmt.Serialize(ms, this);
406 m_group = tmp; 652 m_group = tmp;
653 if (m_running && !m_waitingCrossing)
654 StartTimer();
655
407 return ms.ToArray(); 656 return ms.ToArray();
408 } 657 }
409 658
659 public void StartCrossingCheck()
660 {
661 // timer will be restart by crossingFailure
662 // or never since crossing worked and this
663 // should be deleted
664 StopTimer();
665
666 m_isCrossing = true;
667 m_waitingCrossing = true;
668
669// to remove / retune to smoth crossings
670 if (m_group.RootPart.Velocity != Vector3.Zero)
671 {
672 m_group.RootPart.Velocity = Vector3.Zero;
673 m_group.SendGroupRootTerseUpdate();
674 }
675 }
676
410 public void CrossingFailure() 677 public void CrossingFailure()
411 { 678 {
412 // The serialization has stopped the timer, so let's wait a moment 679 m_waitingCrossing = false;
413 // then retry the crossing. We'll get back here if it fails. 680
414 Util.FireAndForget(delegate (object x) 681 if (m_group != null)
415 { 682 {
416 Thread.Sleep(60000); 683 m_group.RootPart.Velocity = Vector3.Zero;
417 if (m_running) 684 m_group.SendGroupRootTerseUpdate();
418 m_timer.Start(); 685
419 }); 686 if (m_running && m_timer != null)
687 {
688 m_timer.Interval = 60000;
689 StartTimer();
690 }
691 }
420 } 692 }
421 } 693 }
422} 694}
diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
index 7e781c3..16c0d25 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
@@ -422,6 +422,20 @@ namespace OpenSim.Region.Framework.Scenes
422 ); 422 );
423 } 423 }
424 424
425 private class DescendentsRequestData
426 {
427 public IClientAPI RemoteClient;
428 public UUID FolderID;
429 public UUID OwnerID;
430 public bool FetchFolders;
431 public bool FetchItems;
432 public int SortOrder;
433 }
434
435 private Queue<DescendentsRequestData> m_descendentsRequestQueue = new Queue<DescendentsRequestData>();
436 private Object m_descendentsRequestLock = new Object();
437 private bool m_descendentsRequestProcessing = false;
438
425 /// <summary> 439 /// <summary>
426 /// Tell the client about the various child items and folders contained in the requested folder. 440 /// Tell the client about the various child items and folders contained in the requested folder.
427 /// </summary> 441 /// </summary>
@@ -458,17 +472,38 @@ namespace OpenSim.Region.Framework.Scenes
458 } 472 }
459 } 473 }
460 474
461 // We're going to send the reply async, because there may be 475 lock (m_descendentsRequestLock)
462 // an enormous quantity of packets -- basically the entire inventory! 476 {
463 // We don't want to block the client thread while all that is happening. 477 if (!m_descendentsRequestProcessing)
464 SendInventoryDelegate d = SendInventoryAsync; 478 {
465 d.BeginInvoke(remoteClient, folderID, ownerID, fetchFolders, fetchItems, sortOrder, SendInventoryComplete, d); 479 m_descendentsRequestProcessing = true;
480
481 // We're going to send the reply async, because there may be
482 // an enormous quantity of packets -- basically the entire inventory!
483 // We don't want to block the client thread while all that is happening.
484 SendInventoryDelegate d = SendInventoryAsync;
485 d.BeginInvoke(remoteClient, folderID, ownerID, fetchFolders, fetchItems, sortOrder, SendInventoryComplete, d);
486
487 return;
488 }
489
490 DescendentsRequestData req = new DescendentsRequestData();
491 req.RemoteClient = remoteClient;
492 req.FolderID = folderID;
493 req.OwnerID = ownerID;
494 req.FetchFolders = fetchFolders;
495 req.FetchItems = fetchItems;
496 req.SortOrder = sortOrder;
497
498 m_descendentsRequestQueue.Enqueue(req);
499 }
466 } 500 }
467 501
468 delegate void SendInventoryDelegate(IClientAPI remoteClient, UUID folderID, UUID ownerID, bool fetchFolders, bool fetchItems, int sortOrder); 502 delegate void SendInventoryDelegate(IClientAPI remoteClient, UUID folderID, UUID ownerID, bool fetchFolders, bool fetchItems, int sortOrder);
469 503
470 void SendInventoryAsync(IClientAPI remoteClient, UUID folderID, UUID ownerID, bool fetchFolders, bool fetchItems, int sortOrder) 504 void SendInventoryAsync(IClientAPI remoteClient, UUID folderID, UUID ownerID, bool fetchFolders, bool fetchItems, int sortOrder)
471 { 505 {
506 Thread.Sleep(20);
472 SendInventoryUpdate(remoteClient, new InventoryFolderBase(folderID), fetchFolders, fetchItems); 507 SendInventoryUpdate(remoteClient, new InventoryFolderBase(folderID), fetchFolders, fetchItems);
473 } 508 }
474 509
@@ -476,6 +511,21 @@ namespace OpenSim.Region.Framework.Scenes
476 { 511 {
477 SendInventoryDelegate d = (SendInventoryDelegate)iar.AsyncState; 512 SendInventoryDelegate d = (SendInventoryDelegate)iar.AsyncState;
478 d.EndInvoke(iar); 513 d.EndInvoke(iar);
514
515 lock (m_descendentsRequestLock)
516 {
517 if (m_descendentsRequestQueue.Count > 0)
518 {
519 DescendentsRequestData req = m_descendentsRequestQueue.Dequeue();
520
521 d = SendInventoryAsync;
522 d.BeginInvoke(req.RemoteClient, req.FolderID, req.OwnerID, req.FetchFolders, req.FetchItems, req.SortOrder, SendInventoryComplete, d);
523
524 return;
525 }
526
527 m_descendentsRequestProcessing = false;
528 }
479 } 529 }
480 530
481 /// <summary> 531 /// <summary>
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 5b529c3..8fb6c3b 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -2376,6 +2376,12 @@ namespace OpenSim.Region.Framework.Scenes
2376 2376
2377 foreach (SceneObjectPart part in partList) 2377 foreach (SceneObjectPart part in partList)
2378 { 2378 {
2379 if (part.KeyframeMotion != null)
2380 {
2381 part.KeyframeMotion.Delete();
2382 part.KeyframeMotion = null;
2383 }
2384
2379 if (part.IsJoint() && ((part.Flags & PrimFlags.Physics) != 0)) 2385 if (part.IsJoint() && ((part.Flags & PrimFlags.Physics) != 0))
2380 { 2386 {
2381 PhysicsScene.RequestJointDeletion(part.Name); // FIXME: what if the name changed? 2387 PhysicsScene.RequestJointDeletion(part.Name); // FIXME: what if the name changed?
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index fcb1571..0448c25 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -509,6 +509,9 @@ namespace OpenSim.Region.Framework.Scenes
509 Vector3 newpos = Vector3.Zero; 509 Vector3 newpos = Vector3.Zero;
510 OpenSim.Services.Interfaces.GridRegion destination = null; 510 OpenSim.Services.Interfaces.GridRegion destination = null;
511 511
512 if (m_rootPart.KeyframeMotion != null)
513 m_rootPart.KeyframeMotion.StartCrossingCheck();
514
512 bool canCross = true; 515 bool canCross = true;
513 foreach (ScenePresence av in m_linkedAvatars) 516 foreach (ScenePresence av in m_linkedAvatars)
514 { 517 {
@@ -551,7 +554,7 @@ namespace OpenSim.Region.Framework.Scenes
551 av.ParentID = 0; 554 av.ParentID = 0;
552 } 555 }
553 556
554// m_linkedAvatars.Clear(); 557 // m_linkedAvatars.Clear();
555 m_scene.CrossPrimGroupIntoNewRegion(val, this, true); 558 m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
556 559
557 // Normalize 560 // Normalize
@@ -599,11 +602,16 @@ namespace OpenSim.Region.Framework.Scenes
599 avsToCross.Clear(); 602 avsToCross.Clear();
600 603
601 } 604 }
602 else if (RootPart.PhysActor != null) 605 else
603 { 606 {
604 RootPart.PhysActor.CrossingFailure(); 607 if (m_rootPart.KeyframeMotion != null)
605 } 608 m_rootPart.KeyframeMotion.CrossingFailure();
606 609
610 if (RootPart.PhysActor != null)
611 {
612 RootPart.PhysActor.CrossingFailure();
613 }
614 }
607 Vector3 oldp = AbsolutePosition; 615 Vector3 oldp = AbsolutePosition;
608 val.X = Util.Clamp<float>(oldp.X, 0.5f, (float)Constants.RegionSize - 0.5f); 616 val.X = Util.Clamp<float>(oldp.X, 0.5f, (float)Constants.RegionSize - 0.5f);
609 val.Y = Util.Clamp<float>(oldp.Y, 0.5f, (float)Constants.RegionSize - 0.5f); 617 val.Y = Util.Clamp<float>(oldp.Y, 0.5f, (float)Constants.RegionSize - 0.5f);
@@ -2054,15 +2062,16 @@ namespace OpenSim.Region.Framework.Scenes
2054 HasGroupChangedDueToDelink = false; 2062 HasGroupChangedDueToDelink = false;
2055 2063
2056 m_scene.EventManager.TriggerOnSceneObjectPreSave(backup_group, this); 2064 m_scene.EventManager.TriggerOnSceneObjectPreSave(backup_group, this);
2065/*
2057 backup_group.ForEachPart(delegate(SceneObjectPart part) 2066 backup_group.ForEachPart(delegate(SceneObjectPart part)
2058 { 2067 {
2059 if (part.KeyframeMotion != null) 2068 if (part.KeyframeMotion != null)
2060 { 2069 {
2061 part.KeyframeMotion = KeyframeMotion.FromData(backup_group, part.KeyframeMotion.Serialize()); 2070 part.KeyframeMotion = KeyframeMotion.FromData(backup_group, part.KeyframeMotion.Serialize());
2062 part.KeyframeMotion.UpdateSceneObject(this); 2071// part.KeyframeMotion.UpdateSceneObject(this);
2063 } 2072 }
2064 }); 2073 });
2065 2074*/
2066 datastore.StoreObject(backup_group, m_scene.RegionInfo.RegionID); 2075 datastore.StoreObject(backup_group, m_scene.RegionInfo.RegionID);
2067 2076
2068 backup_group.ForEachPart(delegate(SceneObjectPart part) 2077 backup_group.ForEachPart(delegate(SceneObjectPart part)
@@ -3025,7 +3034,8 @@ namespace OpenSim.Region.Framework.Scenes
3025 /// <param name="objectGroup"></param> 3034 /// <param name="objectGroup"></param>
3026 public virtual void DetachFromBackup() 3035 public virtual void DetachFromBackup()
3027 { 3036 {
3028 m_scene.SceneGraph.FireDetachFromBackup(this); 3037 if (m_scene != null)
3038 m_scene.SceneGraph.FireDetachFromBackup(this);
3029 if (m_isBackedUp && Scene != null) 3039 if (m_isBackedUp && Scene != null)
3030 m_scene.EventManager.OnBackup -= ProcessBackup; 3040 m_scene.EventManager.OnBackup -= ProcessBackup;
3031 3041
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 4ed3413..8e419f9 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -769,7 +769,7 @@ namespace OpenSim.Region.Framework.Scenes
769 { 769 {
770 m_groupPosition = value; 770 m_groupPosition = value;
771 PhysicsActor actor = PhysActor; 771 PhysicsActor actor = PhysActor;
772 if (actor != null) 772 if (actor != null && ParentGroup.Scene.PhysicsScene != null)
773 { 773 {
774 try 774 try
775 { 775 {
@@ -2110,6 +2110,9 @@ namespace OpenSim.Region.Framework.Scenes
2110 Array.Copy(Shape.ExtraParams, extraP, extraP.Length); 2110 Array.Copy(Shape.ExtraParams, extraP, extraP.Length);
2111 dupe.Shape.ExtraParams = extraP; 2111 dupe.Shape.ExtraParams = extraP;
2112 2112
2113 if (KeyframeMotion != null)
2114 dupe.KeyframeMotion = KeyframeMotion.Copy(null);
2115
2113 if (userExposed) 2116 if (userExposed)
2114 { 2117 {
2115 if (dupe.m_shape.SculptEntry && dupe.m_shape.SculptTexture != UUID.Zero) 2118 if (dupe.m_shape.SculptEntry && dupe.m_shape.SculptTexture != UUID.Zero)
@@ -3407,6 +3410,9 @@ namespace OpenSim.Region.Framework.Scenes
3407 /// </summary> 3410 /// </summary>
3408 public void SendTerseUpdateToAllClients() 3411 public void SendTerseUpdateToAllClients()
3409 { 3412 {
3413 if (ParentGroup == null || ParentGroup.Scene == null)
3414 return;
3415
3410 ParentGroup.Scene.ForEachClient(delegate(IClientAPI client) 3416 ParentGroup.Scene.ForEachClient(delegate(IClientAPI client)
3411 { 3417 {
3412 SendTerseUpdateToClient(client); 3418 SendTerseUpdateToClient(client);
diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
index 134bd9d..123c158 100644
--- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
+++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
@@ -1241,7 +1241,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1241 1241
1242 if (sog.RootPart.KeyframeMotion != null) 1242 if (sog.RootPart.KeyframeMotion != null)
1243 { 1243 {
1244 Byte[] data = sog.RootPart.KeyframeMotion.Serialize(); 1244 Byte[] data = sog.RootPart.KeyframeMotion.Serialize();
1245 1245
1246 writer.WriteStartElement(String.Empty, "KeyframeMotion", String.Empty); 1246 writer.WriteStartElement(String.Empty, "KeyframeMotion", String.Empty);
1247 writer.WriteBase64(data, 0, data.Length); 1247 writer.WriteBase64(data, 0, data.Length);