diff options
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/KeyframeMotion.cs')
-rw-r--r-- | OpenSim/Region/Framework/Scenes/KeyframeMotion.cs | 280 |
1 files changed, 164 insertions, 116 deletions
diff --git a/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs index bbf3b51..cdd8d2d 100644 --- a/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs +++ b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs | |||
@@ -292,14 +292,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
292 | 292 | ||
293 | private void StartTimer() | 293 | private void StartTimer() |
294 | { | 294 | { |
295 | KeyframeTimer.Add(this); | 295 | lock (m_frames) |
296 | m_timerStopped = false; | 296 | { |
297 | KeyframeTimer.Add(this); | ||
298 | m_timerStopped = false; | ||
299 | } | ||
297 | } | 300 | } |
298 | 301 | ||
299 | private void StopTimer() | 302 | private void StopTimer() |
300 | { | 303 | { |
301 | m_timerStopped = true; | 304 | lock (m_frames) |
302 | KeyframeTimer.Remove(this); | 305 | m_timerStopped = true; |
303 | } | 306 | } |
304 | 307 | ||
305 | public static KeyframeMotion FromData(SceneObjectGroup grp, Byte[] data) | 308 | public static KeyframeMotion FromData(SceneObjectGroup grp, Byte[] data) |
@@ -348,24 +351,26 @@ namespace OpenSim.Region.Framework.Scenes | |||
348 | m_group = grp; | 351 | m_group = grp; |
349 | m_scene = grp.Scene; | 352 | m_scene = grp.Scene; |
350 | 353 | ||
351 | Vector3 grppos = grp.AbsolutePosition; | ||
352 | Vector3 offset = grppos - m_serializedPosition; | ||
353 | // avoid doing it more than once | ||
354 | // current this will happen dragging a prim to other region | ||
355 | m_serializedPosition = grppos; | ||
356 | 354 | ||
357 | m_basePosition += offset; | 355 | lock (m_frames) |
358 | m_nextPosition += offset; | ||
359 | |||
360 | m_currentFrame.StartPosition += offset; | ||
361 | m_currentFrame.Position += offset; | ||
362 | |||
363 | for (int i = 0; i < m_frames.Count; i++) | ||
364 | { | 356 | { |
365 | Keyframe k = m_frames[i]; | 357 | Vector3 grppos = grp.AbsolutePosition; |
366 | k.StartPosition += offset; | 358 | Vector3 offset = grppos - m_serializedPosition; |
367 | k.Position += offset; | 359 | // avoid doing it more than once |
368 | m_frames[i]=k; | 360 | // current this will happen draging a prim to other region |
361 | m_serializedPosition = grppos; | ||
362 | |||
363 | m_basePosition += offset; | ||
364 | m_currentFrame.Position += offset; | ||
365 | |||
366 | m_nextPosition += offset; | ||
367 | |||
368 | for (int i = 0; i < m_frames.Count; i++) | ||
369 | { | ||
370 | Keyframe k = m_frames[i]; | ||
371 | k.Position += offset; | ||
372 | m_frames[i] = k; | ||
373 | } | ||
369 | } | 374 | } |
370 | 375 | ||
371 | if (m_running) | 376 | if (m_running) |
@@ -410,25 +415,28 @@ namespace OpenSim.Region.Framework.Scenes | |||
410 | m_keyframes.CopyTo(newmotion.m_keyframes, 0); | 415 | m_keyframes.CopyTo(newmotion.m_keyframes, 0); |
411 | } | 416 | } |
412 | 417 | ||
413 | newmotion.m_frames = new List<Keyframe>(m_frames); | 418 | lock (m_frames) |
419 | { | ||
420 | newmotion.m_frames = new List<Keyframe>(m_frames); | ||
414 | 421 | ||
415 | newmotion.m_basePosition = m_basePosition; | 422 | newmotion.m_basePosition = m_basePosition; |
416 | newmotion.m_baseRotation = m_baseRotation; | 423 | newmotion.m_baseRotation = m_baseRotation; |
417 | 424 | ||
418 | if (m_selected) | 425 | if (m_selected) |
419 | newmotion.m_serializedPosition = m_serializedPosition; | ||
420 | else | ||
421 | { | ||
422 | if (m_group != null) | ||
423 | newmotion.m_serializedPosition = m_group.AbsolutePosition; | ||
424 | else | ||
425 | newmotion.m_serializedPosition = m_serializedPosition; | 426 | newmotion.m_serializedPosition = m_serializedPosition; |
426 | } | 427 | else |
428 | { | ||
429 | if (m_group != null) | ||
430 | newmotion.m_serializedPosition = m_group.AbsolutePosition; | ||
431 | else | ||
432 | newmotion.m_serializedPosition = m_serializedPosition; | ||
433 | } | ||
427 | 434 | ||
428 | newmotion.m_currentFrame = m_currentFrame; | 435 | newmotion.m_currentFrame = m_currentFrame; |
429 | 436 | ||
430 | newmotion.m_iterations = m_iterations; | 437 | newmotion.m_iterations = m_iterations; |
431 | newmotion.m_running = m_running; | 438 | newmotion.m_running = m_running; |
439 | } | ||
432 | 440 | ||
433 | if (m_running && !m_waitingCrossing) | 441 | if (m_running && !m_waitingCrossing) |
434 | StartTimer(); | 442 | StartTimer(); |
@@ -458,19 +466,18 @@ namespace OpenSim.Region.Framework.Scenes | |||
458 | } | 466 | } |
459 | else | 467 | else |
460 | { | 468 | { |
461 | m_running = false; | ||
462 | StopTimer(); | 469 | StopTimer(); |
470 | m_running = false; | ||
463 | } | 471 | } |
464 | } | 472 | } |
465 | 473 | ||
466 | public void Stop() | 474 | public void Stop() |
467 | { | 475 | { |
476 | StopTimer(); | ||
468 | m_running = false; | 477 | m_running = false; |
469 | m_isCrossing = false; | 478 | m_isCrossing = false; |
470 | m_waitingCrossing = false; | 479 | m_waitingCrossing = false; |
471 | 480 | ||
472 | StopTimer(); | ||
473 | |||
474 | m_basePosition = m_group.AbsolutePosition; | 481 | m_basePosition = m_group.AbsolutePosition; |
475 | m_baseRotation = m_group.GroupRotation; | 482 | m_baseRotation = m_group.GroupRotation; |
476 | 483 | ||
@@ -483,14 +490,34 @@ namespace OpenSim.Region.Framework.Scenes | |||
483 | 490 | ||
484 | public void Pause() | 491 | public void Pause() |
485 | { | 492 | { |
486 | m_running = false; | ||
487 | StopTimer(); | 493 | StopTimer(); |
494 | m_running = false; | ||
488 | 495 | ||
489 | m_group.RootPart.Velocity = Vector3.Zero; | 496 | m_group.RootPart.Velocity = Vector3.Zero; |
490 | m_group.RootPart.AngularVelocity = Vector3.Zero; | 497 | m_group.RootPart.AngularVelocity = Vector3.Zero; |
491 | m_group.SendGroupRootTerseUpdate(); | 498 | m_group.SendGroupRootTerseUpdate(); |
492 | // m_group.RootPart.ScheduleTerseUpdate(); | 499 | // m_group.RootPart.ScheduleTerseUpdate(); |
500 | } | ||
493 | 501 | ||
502 | public void Suspend() | ||
503 | { | ||
504 | lock (m_frames) | ||
505 | { | ||
506 | if (m_timerStopped) | ||
507 | return; | ||
508 | m_timerStopped = true; | ||
509 | } | ||
510 | } | ||
511 | |||
512 | public void Resume() | ||
513 | { | ||
514 | lock (m_frames) | ||
515 | { | ||
516 | if (!m_timerStopped) | ||
517 | return; | ||
518 | if (m_running && !m_waitingCrossing) | ||
519 | StartTimer(); | ||
520 | } | ||
494 | } | 521 | } |
495 | 522 | ||
496 | private void GetNextList() | 523 | private void GetNextList() |
@@ -581,6 +608,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
581 | 608 | ||
582 | pos = (Vector3)k.Position; | 609 | pos = (Vector3)k.Position; |
583 | rot = (Quaternion)k.Rotation; | 610 | rot = (Quaternion)k.Rotation; |
611 | |||
584 | } | 612 | } |
585 | 613 | ||
586 | m_basePosition = pos; | 614 | m_basePosition = pos; |
@@ -592,15 +620,41 @@ namespace OpenSim.Region.Framework.Scenes | |||
592 | 620 | ||
593 | public void OnTimer(double tickDuration) | 621 | public void OnTimer(double tickDuration) |
594 | { | 622 | { |
623 | if (!Monitor.TryEnter(m_frames)) | ||
624 | return; | ||
625 | if (m_timerStopped) | ||
626 | KeyframeTimer.Remove(this); | ||
627 | else | ||
628 | DoOnTimer(tickDuration); | ||
629 | Monitor.Exit(m_frames); | ||
630 | } | ||
631 | |||
632 | private void Done() | ||
633 | { | ||
634 | KeyframeTimer.Remove(this); | ||
635 | m_timerStopped = true; | ||
636 | m_running = false; | ||
637 | m_isCrossing = false; | ||
638 | m_waitingCrossing = false; | ||
639 | |||
640 | m_basePosition = m_group.AbsolutePosition; | ||
641 | m_baseRotation = m_group.GroupRotation; | ||
642 | |||
643 | m_group.RootPart.Velocity = Vector3.Zero; | ||
644 | m_group.RootPart.AngularVelocity = Vector3.Zero; | ||
645 | m_group.SendGroupRootTerseUpdate(); | ||
646 | // m_group.RootPart.ScheduleTerseUpdate(); | ||
647 | m_frames.Clear(); | ||
648 | } | ||
649 | |||
650 | private void DoOnTimer(double tickDuration) | ||
651 | { | ||
595 | if (m_skipLoops > 0) | 652 | if (m_skipLoops > 0) |
596 | { | 653 | { |
597 | m_skipLoops--; | 654 | m_skipLoops--; |
598 | return; | 655 | return; |
599 | } | 656 | } |
600 | 657 | ||
601 | if (m_timerStopped) // trap events still in air even after a timer.stop | ||
602 | return; | ||
603 | |||
604 | if (m_group == null) | 658 | if (m_group == null) |
605 | return; | 659 | return; |
606 | 660 | ||
@@ -612,7 +666,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
612 | { | 666 | { |
613 | m_group.RootPart.Velocity = Vector3.Zero; | 667 | m_group.RootPart.Velocity = Vector3.Zero; |
614 | m_group.SendGroupRootTerseUpdate(); | 668 | m_group.SendGroupRootTerseUpdate(); |
615 | |||
616 | } | 669 | } |
617 | return; | 670 | return; |
618 | } | 671 | } |
@@ -635,32 +688,22 @@ namespace OpenSim.Region.Framework.Scenes | |||
635 | 688 | ||
636 | if (m_frames.Count == 0) | 689 | if (m_frames.Count == 0) |
637 | { | 690 | { |
638 | if (!m_running) return; | 691 | lock (m_frames) |
639 | |||
640 | GetNextList(); | ||
641 | |||
642 | if (m_frames.Count == 0) | ||
643 | { | 692 | { |
644 | Stop(); | 693 | GetNextList(); |
645 | // Scene scene = m_group.Scene; | ||
646 | // | ||
647 | // IScriptModule[] scriptModules = scene.RequestModuleInterfaces<IScriptModule>(); | ||
648 | // foreach (IScriptModule m in scriptModules) | ||
649 | // { | ||
650 | // if (m == null) | ||
651 | // continue; | ||
652 | // m.PostObjectEvent(m_group.RootPart.UUID, "moving_end", new object[0]); | ||
653 | // } | ||
654 | |||
655 | m_group.Scene.EventManager.TriggerMovingEndEvent(m_group.RootPart.LocalId); | ||
656 | |||
657 | return; | ||
658 | } | ||
659 | 694 | ||
660 | m_currentFrame = m_frames[0]; | 695 | if (m_frames.Count == 0) |
661 | m_currentFrame.TimeMS += (int)tickDuration; | 696 | { |
697 | Done(); | ||
698 | m_group.Scene.EventManager.TriggerMovingEndEvent(m_group.RootPart.LocalId); | ||
699 | return; | ||
700 | } | ||
662 | 701 | ||
702 | m_currentFrame = m_frames[0]; | ||
703 | m_currentFrame.TimeMS += (int)tickDuration; | ||
704 | } | ||
663 | //force a update on a keyframe transition | 705 | //force a update on a keyframe transition |
706 | m_nextPosition = m_group.AbsolutePosition; | ||
664 | update = true; | 707 | update = true; |
665 | } | 708 | } |
666 | 709 | ||
@@ -681,9 +724,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
681 | // m_group.UpdateGroupRotationR((Quaternion)m_currentFrame.Rotation); | 724 | // m_group.UpdateGroupRotationR((Quaternion)m_currentFrame.Rotation); |
682 | 725 | ||
683 | m_group.RootPart.RotationOffset = (Quaternion)m_currentFrame.Rotation; | 726 | m_group.RootPart.RotationOffset = (Quaternion)m_currentFrame.Rotation; |
684 | m_frames.RemoveAt(0); | 727 | |
685 | if (m_frames.Count > 0) | 728 | lock (m_frames) |
686 | m_currentFrame = m_frames[0]; | 729 | { |
730 | m_frames.RemoveAt(0); | ||
731 | if (m_frames.Count > 0) | ||
732 | m_currentFrame = m_frames[0]; | ||
733 | } | ||
687 | 734 | ||
688 | update = true; | 735 | update = true; |
689 | } | 736 | } |
@@ -692,17 +739,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
692 | float completed = ((float)m_currentFrame.TimeTotal - (float)m_currentFrame.TimeMS) / (float)m_currentFrame.TimeTotal; | 739 | float completed = ((float)m_currentFrame.TimeTotal - (float)m_currentFrame.TimeMS) / (float)m_currentFrame.TimeTotal; |
693 | bool lastStep = m_currentFrame.TimeMS <= tickDuration; | 740 | bool lastStep = m_currentFrame.TimeMS <= tickDuration; |
694 | 741 | ||
695 | Vector3 positionThisStep = m_currentFrame.StartPosition + (m_currentFrame.Position.Value - m_currentFrame.StartPosition) * completed; | 742 | Vector3 v = (Vector3)m_currentFrame.Position - m_group.AbsolutePosition; |
696 | Vector3 motionThisStep = positionThisStep - m_group.AbsolutePosition; | 743 | Vector3 motionThisFrame = v / (float)remainingSteps; |
744 | v = v * 1000 / m_currentFrame.TimeMS; | ||
697 | 745 | ||
698 | float mag = Vector3.Mag(motionThisStep); | 746 | m_nextPosition = m_group.AbsolutePosition + motionThisFrame; |
699 | 747 | ||
700 | if ((mag >= 0.02f) || lastStep) | 748 | if (Vector3.Mag(motionThisFrame) >= 0.05f) |
701 | { | ||
702 | m_nextPosition = m_group.AbsolutePosition + motionThisStep; | ||
703 | m_group.AbsolutePosition = m_nextPosition; | ||
704 | update = true; | 749 | update = true; |
705 | } | ||
706 | 750 | ||
707 | //int totalSteps = m_currentFrame.TimeTotal / (int)tickDuration; | 751 | //int totalSteps = m_currentFrame.TimeTotal / (int)tickDuration; |
708 | //m_log.DebugFormat("KeyframeMotion.OnTimer: step {0}/{1}, curPosition={2}, finalPosition={3}, motionThisStep={4} (scene {5})", | 752 | //m_log.DebugFormat("KeyframeMotion.OnTimer: step {0}/{1}, curPosition={2}, finalPosition={3}, motionThisStep={4} (scene {5})", |
@@ -714,43 +758,41 @@ namespace OpenSim.Region.Framework.Scenes | |||
714 | 758 | ||
715 | Quaternion step = Quaternion.Slerp(m_currentFrame.StartRotation, (Quaternion)m_currentFrame.Rotation, completed); | 759 | Quaternion step = Quaternion.Slerp(m_currentFrame.StartRotation, (Quaternion)m_currentFrame.Rotation, completed); |
716 | step.Normalize(); | 760 | step.Normalize(); |
717 | /* use simpler change detection | 761 | /* use simpler change detection |
718 | * float angle = 0; | 762 | * float angle = 0; |
719 | 763 | ||
720 | float aa = current.X * current.X + current.Y * current.Y + current.Z * current.Z + current.W * current.W; | 764 | float aa = current.X * current.X + current.Y * current.Y + current.Z * current.Z + current.W * current.W; |
721 | float bb = step.X * step.X + step.Y * step.Y + step.Z * step.Z + step.W * step.W; | 765 | float bb = step.X * step.X + step.Y * step.Y + step.Z * step.Z + step.W * step.W; |
722 | float aa_bb = aa * bb; | 766 | float aa_bb = aa * bb; |
723 | 767 | ||
724 | if (aa_bb == 0) | 768 | if (aa_bb == 0) |
725 | { | 769 | { |
726 | angle = 0; | 770 | angle = 0; |
727 | } | 771 | } |
728 | else | 772 | else |
729 | { | 773 | { |
730 | float ab = current.X * step.X + | 774 | float ab = current.X * step.X + |
731 | current.Y * step.Y + | 775 | current.Y * step.Y + |
732 | current.Z * step.Z + | 776 | current.Z * step.Z + |
733 | current.W * step.W; | 777 | current.W * step.W; |
734 | float q = (ab * ab) / aa_bb; | 778 | float q = (ab * ab) / aa_bb; |
735 | 779 | ||
736 | if (q > 1.0f) | 780 | if (q > 1.0f) |
737 | { | 781 | { |
738 | angle = 0; | 782 | angle = 0; |
739 | } | 783 | } |
740 | else | 784 | else |
741 | { | 785 | { |
742 | angle = (float)Math.Acos(2 * q - 1); | 786 | angle = (float)Math.Acos(2 * q - 1); |
743 | } | 787 | } |
744 | } | 788 | } |
745 | 789 | ||
746 | if (angle > 0.01f) | 790 | if (angle > 0.01f) |
747 | */ | 791 | */ |
748 | if(Math.Abs(step.X - current.X) > 0.001f | 792 | if (Math.Abs(step.X - current.X) > 0.001f |
749 | || Math.Abs(step.Y - current.Y) > 0.001f | 793 | || Math.Abs(step.Y - current.Y) > 0.001f |
750 | || Math.Abs(step.Z - current.Z) > 0.001f | 794 | || Math.Abs(step.Z - current.Z) > 0.001f) |
751 | || lastStep) | 795 | // assuming w is a dependente var |
752 | // assuming w is a dependente var | ||
753 | |||
754 | { | 796 | { |
755 | // m_group.UpdateGroupRotationR(step); | 797 | // m_group.UpdateGroupRotationR(step); |
756 | m_group.RootPart.RotationOffset = step; | 798 | m_group.RootPart.RotationOffset = step; |
@@ -763,25 +805,31 @@ namespace OpenSim.Region.Framework.Scenes | |||
763 | 805 | ||
764 | if (update) | 806 | if (update) |
765 | { | 807 | { |
808 | m_group.AbsolutePosition = m_nextPosition; | ||
766 | m_group.SendGroupRootTerseUpdate(); | 809 | m_group.SendGroupRootTerseUpdate(); |
767 | } | 810 | } |
768 | } | 811 | } |
769 | 812 | ||
770 | public Byte[] Serialize() | 813 | public Byte[] Serialize() |
771 | { | 814 | { |
815 | bool timerWasStopped; | ||
816 | lock (m_frames) | ||
817 | { | ||
818 | timerWasStopped = m_timerStopped; | ||
819 | } | ||
772 | StopTimer(); | 820 | StopTimer(); |
773 | 821 | ||
774 | SceneObjectGroup tmp = m_group; | 822 | SceneObjectGroup tmp = m_group; |
775 | m_group = null; | 823 | m_group = null; |
776 | if (!m_selected && tmp != null) | 824 | |
777 | m_serializedPosition = tmp.AbsolutePosition; | ||
778 | |||
779 | using (MemoryStream ms = new MemoryStream()) | 825 | using (MemoryStream ms = new MemoryStream()) |
780 | { | 826 | { |
781 | BinaryFormatter fmt = new BinaryFormatter(); | 827 | BinaryFormatter fmt = new BinaryFormatter(); |
828 | if (!m_selected && tmp != null) | ||
829 | m_serializedPosition = tmp.AbsolutePosition; | ||
782 | fmt.Serialize(ms, this); | 830 | fmt.Serialize(ms, this); |
783 | m_group = tmp; | 831 | m_group = tmp; |
784 | if (m_running && !m_waitingCrossing) | 832 | if (!timerWasStopped && m_running && !m_waitingCrossing) |
785 | StartTimer(); | 833 | StartTimer(); |
786 | 834 | ||
787 | return ms.ToArray(); | 835 | return ms.ToArray(); |