aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework/Scenes
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/Framework/Scenes/KeyframeMotion.cs368
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs6
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs29
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs5
-rw-r--r--OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs2
5 files changed, 299 insertions, 111 deletions
diff --git a/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs
index 6ee09b7..4e6425f 100644
--- a/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs
+++ b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs
@@ -58,12 +58,31 @@ namespace OpenSim.Region.Framework.Scenes
58 private Vector3 m_serializedPosition; 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_skipOnTimer;
82
83 // retry position for cross fail
84 [NonSerialized()]
85 private Vector3 m_nextPosition;
67 86
68 [NonSerialized()] 87 [NonSerialized()]
69 private SceneObjectGroup m_group; 88 private SceneObjectGroup m_group;
@@ -88,7 +107,7 @@ namespace OpenSim.Region.Framework.Scenes
88 { 107 {
89 set 108 set
90 { 109 {
91 if (value) 110 if (!value)
92 { 111 {
93 // Once we're let go, recompute positions 112 // Once we're let go, recompute positions
94 if (m_selected) 113 if (m_selected)
@@ -100,7 +119,8 @@ namespace OpenSim.Region.Framework.Scenes
100 if (!m_selected) 119 if (!m_selected)
101 m_serializedPosition = m_group.AbsolutePosition; 120 m_serializedPosition = m_group.AbsolutePosition;
102 } 121 }
103 m_selected = value; } 122 m_selected = value;
123 }
104 } 124 }
105 125
106 public static KeyframeMotion FromData(SceneObjectGroup grp, Byte[] data) 126 public static KeyframeMotion FromData(SceneObjectGroup grp, Byte[] data)
@@ -111,31 +131,65 @@ namespace OpenSim.Region.Framework.Scenes
111 131
112 KeyframeMotion newMotion = (KeyframeMotion)fmt.Deserialize(ms); 132 KeyframeMotion newMotion = (KeyframeMotion)fmt.Deserialize(ms);
113 133
134/*
135 * create timer in start()
136 * this was creating unneeded timers
137
114 // This will be started when position is updated 138 // This will be started when position is updated
139
115 newMotion.m_timer = new Timer(); 140 newMotion.m_timer = new Timer();
116 newMotion.m_timer.Interval = (int)timerInterval; 141 newMotion.m_timer.Interval = (int)timerInterval;
117 newMotion.m_timer.AutoReset = true; 142 newMotion.m_timer.AutoReset = true;
118 newMotion.m_timer.Elapsed += newMotion.OnTimer; 143 newMotion.m_timer.Elapsed += newMotion.OnTimer;
144*/
145 newMotion.m_group = grp;
119 146
147 if (grp != null && grp.IsSelected)
148 newMotion.m_selected = true;
149
150 newMotion.m_onTimerLock = new object();
151 newMotion.m_skipOnTimer = false;
152 newMotion.m_inOnTimer = false;
120 return newMotion; 153 return newMotion;
121 } 154 }
122 155
123 public void UpdateSceneObject(SceneObjectGroup grp) 156 public void UpdateSceneObject(SceneObjectGroup grp)
124 { 157 {
125 m_group = grp; 158// 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 { 159 {
132 Keyframe k = m_frames[i]; 160 m_skipOnTimer = true;
133 k.Position += offset; 161 if (m_timer != null)
134 m_frames[i] = k; 162 m_timer.Stop();
135 } 163
164 m_group = grp;
165 Vector3 grppos = grp.AbsolutePosition;
166 Vector3 offset = grppos - m_serializedPosition;
167 // avoid doing it more than once
168 // current this will happen draging a prim to other region
169 m_serializedPosition = grppos;
170
171 m_basePosition += offset;
172 m_currentFrame.Position += offset;
173
174 m_nextPosition += offset;
175/*
176 for (int i = 0; i < m_frames.Count; i++)
177 {
178 Keyframe k = m_frames[i];
179 k.Position += offset;
180 m_frames[i] = k;
181 }
182*/
183 for (int i = 0; i < m_frames.Count; i++)
184 {
185 Keyframe k = m_frames[i];
186 k.Position += offset;
187 m_frames[i]=k;
188 }
136 189
137 if (m_running) 190 if (m_running)
138 Start(); 191 Start();
192 }
139 } 193 }
140 194
141 public KeyframeMotion(SceneObjectGroup grp, PlayMode mode, DataFormat data) 195 public KeyframeMotion(SceneObjectGroup grp, PlayMode mode, DataFormat data)
@@ -143,13 +197,16 @@ namespace OpenSim.Region.Framework.Scenes
143 m_mode = mode; 197 m_mode = mode;
144 m_data = data; 198 m_data = data;
145 199
200 m_onTimerLock = new object();
201
146 m_group = grp; 202 m_group = grp;
147 m_basePosition = grp.AbsolutePosition; 203 m_basePosition = grp.AbsolutePosition;
148 m_baseRotation = grp.GroupRotation; 204 m_baseRotation = grp.GroupRotation;
149 205/*
150 m_timer.Interval = (int)timerInterval; 206 m_timer.Interval = (int)timerInterval;
151 m_timer.AutoReset = true; 207 m_timer.AutoReset = true;
152 m_timer.Elapsed += OnTimer; 208 m_timer.Elapsed += OnTimer;
209 */
153 } 210 }
154 211
155 public void SetKeyframes(Keyframe[] frames) 212 public void SetKeyframes(Keyframe[] frames)
@@ -157,19 +214,63 @@ namespace OpenSim.Region.Framework.Scenes
157 m_keyframes = frames; 214 m_keyframes = frames;
158 } 215 }
159 216
217 public void Delete()
218 {
219 m_skipOnTimer = true;
220 m_frames.Clear();
221 m_keyframes = null;
222 m_running = false;
223
224 if (m_timer == null)
225 return;
226
227 m_timer.Stop();
228 m_timer.Elapsed -= OnTimer;
229 m_timer = null;
230 }
231
160 public void Start() 232 public void Start()
161 { 233 {
162 if (m_keyframes.Length > 0) 234 if (m_keyframes.Length > 0)
235 {
236 if (m_timer == null)
237 {
238 m_timer = new Timer();
239 m_timer.Interval = (int)timerInterval;
240 m_timer.AutoReset = true;
241 m_timer.Elapsed += OnTimer;
242 }
243
244 m_skipOnTimer = false;
245 m_inOnTimer = false;
246
163 m_timer.Start(); 247 m_timer.Start();
164 m_running = true; 248 m_running = true;
249 }
250 else
251 {
252 m_running = false;
253 m_skipOnTimer = true;
254 if (m_timer != null)
255 {
256 m_timer.Stop();
257 m_timer.Elapsed -= OnTimer;
258 m_timer = null;
259 }
260 }
165 } 261 }
166 262
167 public void Stop() 263 public void Stop()
168 { 264 {
265 m_skipOnTimer = true;
266
169 // Failed object creation 267 // Failed object creation
170 if (m_timer == null) 268 if (m_timer == null)
171 return; 269 return;
270
172 m_timer.Stop(); 271 m_timer.Stop();
272 m_timer.Elapsed -= OnTimer;
273 m_timer = null;
173 274
174 m_basePosition = m_group.AbsolutePosition; 275 m_basePosition = m_group.AbsolutePosition;
175 m_baseRotation = m_group.GroupRotation; 276 m_baseRotation = m_group.GroupRotation;
@@ -184,6 +285,8 @@ namespace OpenSim.Region.Framework.Scenes
184 285
185 public void Pause() 286 public void Pause()
186 { 287 {
288 m_skipOnTimer = true;
289
187 m_group.RootPart.Velocity = Vector3.Zero; 290 m_group.RootPart.Velocity = Vector3.Zero;
188 m_group.RootPart.UpdateAngularVelocity(Vector3.Zero); 291 m_group.RootPart.UpdateAngularVelocity(Vector3.Zero);
189 m_group.SendGroupRootTerseUpdate(); 292 m_group.SendGroupRootTerseUpdate();
@@ -284,138 +387,197 @@ namespace OpenSim.Region.Framework.Scenes
284 387
285 protected void OnTimer(object sender, ElapsedEventArgs e) 388 protected void OnTimer(object sender, ElapsedEventArgs e)
286 { 389 {
287 if (m_frames.Count == 0) 390 if (m_inOnTimer)
288 {
289 GetNextList();
290
291 if (m_frames.Count == 0)
292 {
293 Stop();
294 return;
295 }
296
297 m_currentFrame = m_frames[0];
298 }
299
300 if (m_selected)
301 { 391 {
302 if (m_group.RootPart.Velocity != Vector3.Zero) 392 m_log.Error("[KeyFrame]: timer overrun");
303 {
304 m_group.RootPart.Velocity = Vector3.Zero;
305 m_group.SendGroupRootTerseUpdate();
306 }
307 return; 393 return;
308 } 394 }
309 395
310 // Do the frame processing 396// lock (m_onTimerLock)
311 double steps = (double)m_currentFrame.TimeMS / timerInterval;
312 float complete = ((float)m_currentFrame.TimeTotal - (float)m_currentFrame.TimeMS) / (float)m_currentFrame.TimeTotal;
313
314 if (steps <= 1.0)
315 { 397 {
316 m_currentFrame.TimeMS = 0; 398 if (m_skipOnTimer)
317 399 return;
318 m_group.AbsolutePosition = (Vector3)m_currentFrame.Position;
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
327 bool update = false;
328 400
329 if (Vector3.Mag(motionThisFrame) >= 0.05f) 401 m_inOnTimer = true;
402 try
330 { 403 {
331 m_group.AbsolutePosition += motionThisFrame; 404 if (m_frames.Count == 0)
332 m_group.RootPart.Velocity = v; 405 {
333 update = true; 406 GetNextList();
334 }
335 407
336 if ((Quaternion)m_currentFrame.Rotation != m_group.GroupRotation) 408 if (m_frames.Count == 0)
337 { 409 {
338 Quaternion current = m_group.GroupRotation; 410 Stop();
411 m_inOnTimer = false;
412 return;
413 }
339 414
340 Quaternion step = Quaternion.Slerp(m_currentFrame.StartRotation, (Quaternion)m_currentFrame.Rotation, complete); 415 m_currentFrame = m_frames[0];
416 }
341 417
342 float angle = 0; 418 if (m_selected)
419 {
420 if (m_group.RootPart.Velocity != Vector3.Zero)
421 {
422 m_group.RootPart.Velocity = Vector3.Zero;
423 m_group.SendGroupRootTerseUpdate();
424 }
425 m_inOnTimer = false;
426 return;
427 }
343 428
344 float aa = current.X * current.X + current.Y * current.Y + current.Z * current.Z + current.W * current.W; 429 // Do the frame processing
345 float bb = step.X * step.X + step.Y * step.Y + step.Z * step.Z + step.W * step.W; 430 double steps = (double)m_currentFrame.TimeMS / timerInterval;
346 float aa_bb = aa * bb; 431 float complete = ((float)m_currentFrame.TimeTotal - (float)m_currentFrame.TimeMS) / (float)m_currentFrame.TimeTotal;
347 432
348 if (aa_bb == 0) 433 if (steps <= 1.0)
349 { 434 {
350 angle = 0; 435 m_currentFrame.TimeMS = 0;
436
437 // m_group.AbsolutePosition = (Vector3)m_currentFrame.Position;
438 m_nextPosition = (Vector3)m_currentFrame.Position;
439 m_group.AbsolutePosition = m_nextPosition;
440
441 m_group.UpdateGroupRotationR((Quaternion)m_currentFrame.Rotation);
351 } 442 }
352 else 443 else
353 { 444 {
354 float ab = current.X * step.X + 445 Vector3 v = (Vector3)m_currentFrame.Position - m_group.AbsolutePosition;
355 current.Y * step.Y + 446 Vector3 motionThisFrame = v / (float)steps;
356 current.Z * step.Z + 447 v = v * 1000 / m_currentFrame.TimeMS;
357 current.W * step.W;
358 float q = (ab * ab) / aa_bb;
359 448
360 if (q > 1.0f) 449 bool update = false;
450
451 if (Vector3.Mag(motionThisFrame) >= 0.05f)
361 { 452 {
362 angle = 0; 453 // m_group.AbsolutePosition += motionThisFrame;
454 m_nextPosition = m_group.AbsolutePosition + motionThisFrame;
455 m_group.AbsolutePosition = m_nextPosition;
456
457 m_group.RootPart.Velocity = v;
458 update = true;
363 } 459 }
364 else 460
461 if ((Quaternion)m_currentFrame.Rotation != m_group.GroupRotation)
365 { 462 {
366 angle = (float)Math.Acos(2 * q - 1); 463 Quaternion current = m_group.GroupRotation;
464
465 Quaternion step = Quaternion.Slerp(m_currentFrame.StartRotation, (Quaternion)m_currentFrame.Rotation, complete);
466
467 float angle = 0;
468
469 float aa = current.X * current.X + current.Y * current.Y + current.Z * current.Z + current.W * current.W;
470 float bb = step.X * step.X + step.Y * step.Y + step.Z * step.Z + step.W * step.W;
471 float aa_bb = aa * bb;
472
473 if (aa_bb == 0)
474 {
475 angle = 0;
476 }
477 else
478 {
479 float ab = current.X * step.X +
480 current.Y * step.Y +
481 current.Z * step.Z +
482 current.W * step.W;
483 float q = (ab * ab) / aa_bb;
484
485 if (q > 1.0f)
486 {
487 angle = 0;
488 }
489 else
490 {
491 angle = (float)Math.Acos(2 * q - 1);
492 }
493 }
494
495 if (angle > 0.01f)
496 {
497 m_group.UpdateGroupRotationR(step);
498 //m_group.RootPart.UpdateAngularVelocity(m_currentFrame.AngularVelocity / 2);
499 update = true;
500 }
367 } 501 }
502
503 if (update)
504 m_group.SendGroupRootTerseUpdate();
368 } 505 }
369 506
370 if (angle > 0.01f) 507 m_currentFrame.TimeMS -= (int)timerInterval;
508
509 if (m_currentFrame.TimeMS <= 0)
371 { 510 {
372 m_group.UpdateGroupRotationR(step); 511 m_group.RootPart.Velocity = Vector3.Zero;
373 //m_group.RootPart.UpdateAngularVelocity(m_currentFrame.AngularVelocity / 2); 512 m_group.RootPart.UpdateAngularVelocity(Vector3.Zero);
374 update = true; 513 m_group.SendGroupRootTerseUpdate();
514
515 m_frames.RemoveAt(0);
516 if (m_frames.Count > 0)
517 m_currentFrame = m_frames[0];
375 } 518 }
376 } 519 }
377 520 finally
378 if (update) 521 {
379 m_group.SendGroupRootTerseUpdate(); 522 m_inOnTimer = false;
523 }
380 } 524 }
525 }
381 526
382 m_currentFrame.TimeMS -= (int)timerInterval; 527 public Byte[] Serialize(bool StopMoveTimer)
383 528 {
384 if (m_currentFrame.TimeMS <= 0) 529 MemoryStream ms = new MemoryStream();
530 if (StopMoveTimer && m_timer != null)
385 { 531 {
386 m_group.RootPart.Velocity = Vector3.Zero; 532 m_skipOnTimer = true;
387 m_group.RootPart.UpdateAngularVelocity(Vector3.Zero); 533 m_timer.Stop();
388 m_group.SendGroupRootTerseUpdate(); 534 }
389 535
390 m_frames.RemoveAt(0); 536// lock (m_onTimerLock)
391 if (m_frames.Count > 0) 537 {
392 m_currentFrame = m_frames[0]; 538 BinaryFormatter fmt = new BinaryFormatter();
539 SceneObjectGroup tmp = m_group;
540 m_group = null;
541 if(!m_selected)
542 m_serializedPosition = tmp.AbsolutePosition;
543 fmt.Serialize(ms, this);
544 m_group = tmp;
545 return ms.ToArray();
393 } 546 }
394 } 547 }
395 548
396 public Byte[] Serialize() 549 public void StartCrossingCheck()
397 { 550 {
398 MemoryStream ms = new MemoryStream(); 551 m_skipOnTimer = true;
399 m_timer.Stop(); 552 if (m_timer != null)
553 m_timer.Stop();
400 554
401 BinaryFormatter fmt = new BinaryFormatter(); 555 if (m_group.RootPart.Velocity != Vector3.Zero)
402 SceneObjectGroup tmp = m_group; 556 {
403 m_group = null; 557 m_group.RootPart.Velocity = Vector3.Zero;
404 m_serializedPosition = tmp.AbsolutePosition; 558 m_group.SendGroupRootTerseUpdate();
405 fmt.Serialize(ms, this); 559 }
406 m_group = tmp;
407 return ms.ToArray();
408 } 560 }
409 561
410 public void CrossingFailure() 562 public void CrossingFailure()
411 { 563 {
412 // The serialization has stopped the timer, so let's wait a moment 564 // The serialization has stopped the timer, so let's wait a moment
413 // then retry the crossing. We'll get back here if it fails. 565 // then retry the crossing. We'll get back here if it fails.
566 // if it is a open border there is no serialization
567 // so make sure timer is actually stopped
568
569 m_group.RootPart.Velocity = Vector3.Zero;
570 m_group.SendGroupRootTerseUpdate();
571
414 Util.FireAndForget(delegate (object x) 572 Util.FireAndForget(delegate (object x)
415 { 573 {
416 Thread.Sleep(60000); 574 Thread.Sleep(60000);
417 if (m_running) 575 if (m_running)
576 {
577 m_skipOnTimer = false;
418 m_timer.Start(); 578 m_timer.Start();
579 m_group.AbsolutePosition = m_nextPosition;
580 }
419 }); 581 });
420 } 582 }
421 } 583 }
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 57fcf51..0237021 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -2346,6 +2346,12 @@ namespace OpenSim.Region.Framework.Scenes
2346 2346
2347 foreach (SceneObjectPart part in partList) 2347 foreach (SceneObjectPart part in partList)
2348 { 2348 {
2349 if (part.KeyframeMotion != null)
2350 {
2351 part.KeyframeMotion.Delete();
2352 part.KeyframeMotion = null;
2353 }
2354
2349 if (part.IsJoint() && ((part.Flags & PrimFlags.Physics) != 0)) 2355 if (part.IsJoint() && ((part.Flags & PrimFlags.Physics) != 0))
2350 { 2356 {
2351 PhysicsScene.RequestJointDeletion(part.Name); // FIXME: what if the name changed? 2357 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 eee53d7..65a1da2 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);
@@ -2058,8 +2066,8 @@ namespace OpenSim.Region.Framework.Scenes
2058 { 2066 {
2059 if (part.KeyframeMotion != null) 2067 if (part.KeyframeMotion != null)
2060 { 2068 {
2061 part.KeyframeMotion = KeyframeMotion.FromData(backup_group, part.KeyframeMotion.Serialize()); 2069 part.KeyframeMotion = KeyframeMotion.FromData(backup_group, part.KeyframeMotion.Serialize(false));
2062 part.KeyframeMotion.UpdateSceneObject(this); 2070// part.KeyframeMotion.UpdateSceneObject(this);
2063 } 2071 }
2064 }); 2072 });
2065 2073
@@ -4407,6 +4415,15 @@ namespace OpenSim.Region.Framework.Scenes
4407 public virtual ISceneObject CloneForNewScene() 4415 public virtual ISceneObject CloneForNewScene()
4408 { 4416 {
4409 SceneObjectGroup sog = Copy(false); 4417 SceneObjectGroup sog = Copy(false);
4418 sog.ForEachPart(delegate(SceneObjectPart part)
4419 {
4420 if (part.KeyframeMotion != null)
4421 {
4422 part.KeyframeMotion = KeyframeMotion.FromData(sog, part.KeyframeMotion.Serialize(true));
4423 // this is called later
4424// part.KeyframeMotion.UpdateSceneObject(this);
4425 }
4426 });
4410 sog.IsDeleted = false; 4427 sog.IsDeleted = false;
4411 return sog; 4428 return sog;
4412 } 4429 }
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index ed626d0..bf5fc99 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 {
@@ -3408,6 +3408,9 @@ namespace OpenSim.Region.Framework.Scenes
3408 /// </summary> 3408 /// </summary>
3409 public void SendTerseUpdateToAllClients() 3409 public void SendTerseUpdateToAllClients()
3410 { 3410 {
3411 if (ParentGroup == null || ParentGroup.Scene == null)
3412 return;
3413
3411 ParentGroup.Scene.ForEachClient(delegate(IClientAPI client) 3414 ParentGroup.Scene.ForEachClient(delegate(IClientAPI client)
3412 { 3415 {
3413 SendTerseUpdateToClient(client); 3416 SendTerseUpdateToClient(client);
diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
index 134bd9d..1c75607 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(true);
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);