diff options
author | Justin Clarke Casey | 2008-03-18 20:42:01 +0000 |
---|---|---|
committer | Justin Clarke Casey | 2008-03-18 20:42:01 +0000 |
commit | d135dad051accc7378f4d375891956f3aa11b31c (patch) | |
tree | ad2477731a5ec0eca8dea95c0aa084697f8a9029 | |
parent | * Stop (which currently removes) all scripts in an object when that object is... (diff) | |
download | opensim-SC-d135dad051accc7378f4d375891956f3aa11b31c.zip opensim-SC-d135dad051accc7378f4d375891956f3aa11b31c.tar.gz opensim-SC-d135dad051accc7378f4d375891956f3aa11b31c.tar.bz2 opensim-SC-d135dad051accc7378f4d375891956f3aa11b31c.tar.xz |
* Add a large amount of extra locking to m_parts in SceneObjectGroup
* Should help stop any InvalidOperationExceptions caused by concurrent read/write
* The extra locking should be okay, but I'm really surprised we've got away without mucho crashes due to this...
-rw-r--r-- | OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs | 360 |
1 files changed, 235 insertions, 125 deletions
diff --git a/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs index 8b30b58..327956e 100644 --- a/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs | |||
@@ -48,6 +48,10 @@ namespace OpenSim.Region.Environment.Scenes | |||
48 | private Encoding enc = Encoding.ASCII; | 48 | private Encoding enc = Encoding.ASCII; |
49 | 49 | ||
50 | protected SceneObjectPart m_rootPart; | 50 | protected SceneObjectPart m_rootPart; |
51 | |||
52 | /// <summary> | ||
53 | /// The constituent parts of this group | ||
54 | /// </summary> | ||
51 | protected Dictionary<LLUUID, SceneObjectPart> m_parts = new Dictionary<LLUUID, SceneObjectPart>(); | 55 | protected Dictionary<LLUUID, SceneObjectPart> m_parts = new Dictionary<LLUUID, SceneObjectPart>(); |
52 | 56 | ||
53 | protected ulong m_regionHandle; | 57 | protected ulong m_regionHandle; |
@@ -389,34 +393,37 @@ namespace OpenSim.Region.Environment.Scenes | |||
389 | 393 | ||
390 | EntityIntersection returnresult = new EntityIntersection(); | 394 | EntityIntersection returnresult = new EntityIntersection(); |
391 | 395 | ||
392 | foreach (SceneObjectPart part in m_parts.Values) | 396 | lock (m_parts) |
393 | { | 397 | { |
394 | // Temporary commented to stop compiler warning | 398 | foreach (SceneObjectPart part in m_parts.Values) |
395 | //Vector3 partPosition = | 399 | { |
396 | // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z); | 400 | // Temporary commented to stop compiler warning |
397 | Quaternion parentrotation = | 401 | //Vector3 partPosition = |
398 | new Quaternion(GroupRotation.W, GroupRotation.X, GroupRotation.Y, GroupRotation.Z); | 402 | // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z); |
403 | Quaternion parentrotation = | ||
404 | new Quaternion(GroupRotation.W, GroupRotation.X, GroupRotation.Y, GroupRotation.Z); | ||
399 | 405 | ||
400 | // Telling the prim to raytrace. | 406 | // Telling the prim to raytrace. |
401 | EntityIntersection inter = part.TestIntersection(hRay, parentrotation); | 407 | EntityIntersection inter = part.TestIntersection(hRay, parentrotation); |
402 | 408 | ||
403 | // This may need to be updated to the maximum draw distance possible.. | 409 | // This may need to be updated to the maximum draw distance possible.. |
404 | // We might (and probably will) be checking for prim creation from other sims | 410 | // We might (and probably will) be checking for prim creation from other sims |
405 | // when the camera crosses the border. | 411 | // when the camera crosses the border. |
406 | float idist = (float)Constants.RegionSize; | 412 | float idist = (float)Constants.RegionSize; |
407 | 413 | ||
408 | 414 | ||
409 | if (inter.HitTF) | 415 | if (inter.HitTF) |
410 | { | ||
411 | // We need to find the closest prim to return to the testcaller along the ray | ||
412 | if (inter.distance < idist) | ||
413 | { | 416 | { |
414 | idist = inter.distance; | 417 | // We need to find the closest prim to return to the testcaller along the ray |
415 | returnresult.HitTF = true; | 418 | if (inter.distance < idist) |
416 | returnresult.ipoint = inter.ipoint; | 419 | { |
417 | returnresult.obj = part; | 420 | idist = inter.distance; |
418 | returnresult.normal = inter.normal; | 421 | returnresult.HitTF = true; |
419 | returnresult.distance = inter.distance; | 422 | returnresult.ipoint = inter.ipoint; |
423 | returnresult.obj = part; | ||
424 | returnresult.normal = inter.normal; | ||
425 | returnresult.distance = inter.distance; | ||
426 | } | ||
420 | } | 427 | } |
421 | } | 428 | } |
422 | } | 429 | } |
@@ -476,15 +483,20 @@ namespace OpenSim.Region.Environment.Scenes | |||
476 | m_rootPart.ToXml(writer); | 483 | m_rootPart.ToXml(writer); |
477 | writer.WriteEndElement(); | 484 | writer.WriteEndElement(); |
478 | writer.WriteStartElement(String.Empty, "OtherParts", String.Empty); | 485 | writer.WriteStartElement(String.Empty, "OtherParts", String.Empty); |
479 | foreach (SceneObjectPart part in m_parts.Values) | 486 | |
487 | lock (m_parts) | ||
480 | { | 488 | { |
481 | if (part.UUID != m_rootPart.UUID) | 489 | foreach (SceneObjectPart part in m_parts.Values) |
482 | { | 490 | { |
483 | writer.WriteStartElement(String.Empty, "Part", String.Empty); | 491 | if (part.UUID != m_rootPart.UUID) |
484 | part.ToXml(writer); | 492 | { |
485 | writer.WriteEndElement(); | 493 | writer.WriteStartElement(String.Empty, "Part", String.Empty); |
494 | part.ToXml(writer); | ||
495 | writer.WriteEndElement(); | ||
496 | } | ||
486 | } | 497 | } |
487 | } | 498 | } |
499 | |||
488 | writer.WriteEndElement(); | 500 | writer.WriteEndElement(); |
489 | writer.WriteEndElement(); | 501 | writer.WriteEndElement(); |
490 | } | 502 | } |
@@ -507,13 +519,18 @@ namespace OpenSim.Region.Environment.Scenes | |||
507 | writer.WriteStartElement(String.Empty, "SceneObjectGroup", String.Empty); | 519 | writer.WriteStartElement(String.Empty, "SceneObjectGroup", String.Empty); |
508 | m_rootPart.ToXml(writer); | 520 | m_rootPart.ToXml(writer); |
509 | writer.WriteStartElement(String.Empty, "OtherParts", String.Empty); | 521 | writer.WriteStartElement(String.Empty, "OtherParts", String.Empty); |
510 | foreach (SceneObjectPart part in m_parts.Values) | 522 | |
523 | lock (m_parts) | ||
511 | { | 524 | { |
512 | if (part.UUID != m_rootPart.UUID) | 525 | foreach (SceneObjectPart part in m_parts.Values) |
513 | { | 526 | { |
514 | part.ToXml(writer); | 527 | if (part.UUID != m_rootPart.UUID) |
528 | { | ||
529 | part.ToXml(writer); | ||
530 | } | ||
515 | } | 531 | } |
516 | } | 532 | } |
533 | |||
517 | writer.WriteEndElement(); | 534 | writer.WriteEndElement(); |
518 | writer.WriteEndElement(); | 535 | writer.WriteEndElement(); |
519 | } | 536 | } |
@@ -593,7 +610,12 @@ namespace OpenSim.Region.Environment.Scenes | |||
593 | { | 610 | { |
594 | SceneObjectPart newPart = part.Copy(m_scene.PrimIDAllocate(), OwnerID, GroupID, m_parts.Count); | 611 | SceneObjectPart newPart = part.Copy(m_scene.PrimIDAllocate(), OwnerID, GroupID, m_parts.Count); |
595 | newPart.SetParent(this); | 612 | newPart.SetParent(this); |
596 | m_parts.Add(newPart.UUID, newPart); | 613 | |
614 | lock (m_parts) | ||
615 | { | ||
616 | m_parts.Add(newPart.UUID, newPart); | ||
617 | } | ||
618 | |||
597 | SetPartAsRoot(newPart); | 619 | SetPartAsRoot(newPart); |
598 | } | 620 | } |
599 | 621 | ||
@@ -685,7 +707,12 @@ namespace OpenSim.Region.Environment.Scenes | |||
685 | { | 707 | { |
686 | SceneObjectPart newPart = part.Copy(m_scene.PrimIDAllocate(), OwnerID, GroupID, m_parts.Count); | 708 | SceneObjectPart newPart = part.Copy(m_scene.PrimIDAllocate(), OwnerID, GroupID, m_parts.Count); |
687 | newPart.SetParent(this); | 709 | newPart.SetParent(this); |
688 | m_parts.Add(newPart.UUID, newPart); | 710 | |
711 | lock (m_parts) | ||
712 | { | ||
713 | m_parts.Add(newPart.UUID, newPart); | ||
714 | } | ||
715 | |||
689 | SetPartAsNonRoot(newPart); | 716 | SetPartAsNonRoot(newPart); |
690 | } | 717 | } |
691 | 718 | ||
@@ -697,6 +724,8 @@ namespace OpenSim.Region.Environment.Scenes | |||
697 | /// </summary> | 724 | /// </summary> |
698 | public void ResetIDs() | 725 | public void ResetIDs() |
699 | { | 726 | { |
727 | // As this is only ever called for prims which are not currently part of the scene (and hence | ||
728 | // not accessible by clients), there should be no need to lock | ||
700 | List<SceneObjectPart> partsList = new List<SceneObjectPart>(m_parts.Values); | 729 | List<SceneObjectPart> partsList = new List<SceneObjectPart>(m_parts.Values); |
701 | m_parts.Clear(); | 730 | m_parts.Clear(); |
702 | foreach (SceneObjectPart part in partsList) | 731 | foreach (SceneObjectPart part in partsList) |
@@ -754,46 +783,57 @@ namespace OpenSim.Region.Environment.Scenes | |||
754 | /// </summary> | 783 | /// </summary> |
755 | public override void Update() | 784 | public override void Update() |
756 | { | 785 | { |
757 | if (Util.GetDistanceTo(lastPhysGroupPos, AbsolutePosition) > 0.02) | 786 | lock (m_parts) |
758 | { | 787 | { |
759 | foreach (SceneObjectPart part in m_parts.Values) | 788 | if (Util.GetDistanceTo(lastPhysGroupPos, AbsolutePosition) > 0.02) |
789 | { | ||
790 | foreach (SceneObjectPart part in m_parts.Values) | ||
791 | { | ||
792 | if (part.UpdateFlag == 0) part.UpdateFlag = 1; | ||
793 | } | ||
794 | |||
795 | lastPhysGroupPos = AbsolutePosition; | ||
796 | } | ||
797 | |||
798 | if ((Math.Abs(lastPhysGroupRot.W - GroupRotation.W) > 0.1) | ||
799 | || (Math.Abs(lastPhysGroupRot.X - GroupRotation.X) > 0.1) | ||
800 | || (Math.Abs(lastPhysGroupRot.Y - GroupRotation.Y) > 0.1) | ||
801 | || (Math.Abs(lastPhysGroupRot.Z - GroupRotation.Z) > 0.1)) | ||
760 | { | 802 | { |
761 | if (part.UpdateFlag == 0) part.UpdateFlag = 1; | 803 | foreach (SceneObjectPart part in m_parts.Values) |
804 | { | ||
805 | if (part.UpdateFlag == 0) part.UpdateFlag = 1; | ||
806 | } | ||
807 | |||
808 | lastPhysGroupRot = GroupRotation; | ||
762 | } | 809 | } |
763 | lastPhysGroupPos = AbsolutePosition; | 810 | |
764 | } | ||
765 | |||
766 | if ((Math.Abs(lastPhysGroupRot.W - GroupRotation.W) > 0.1) | ||
767 | || (Math.Abs(lastPhysGroupRot.X - GroupRotation.X) > 0.1) | ||
768 | || (Math.Abs(lastPhysGroupRot.Y - GroupRotation.Y) > 0.1) | ||
769 | || (Math.Abs(lastPhysGroupRot.Z - GroupRotation.Z) > 0.1)) | ||
770 | { | ||
771 | foreach (SceneObjectPart part in m_parts.Values) | 811 | foreach (SceneObjectPart part in m_parts.Values) |
772 | { | 812 | { |
773 | if (part.UpdateFlag == 0) part.UpdateFlag = 1; | 813 | part.SendScheduledUpdates(); |
774 | } | 814 | } |
775 | lastPhysGroupRot = GroupRotation; | ||
776 | } | ||
777 | |||
778 | foreach (SceneObjectPart part in m_parts.Values) | ||
779 | { | ||
780 | part.SendScheduledUpdates(); | ||
781 | } | 815 | } |
782 | } | 816 | } |
783 | 817 | ||
784 | public void ScheduleFullUpdateToAvatar(ScenePresence presence) | 818 | public void ScheduleFullUpdateToAvatar(ScenePresence presence) |
785 | { | 819 | { |
786 | foreach (SceneObjectPart part in m_parts.Values) | 820 | lock (m_parts) |
787 | { | 821 | { |
788 | part.AddFullUpdateToAvatar(presence); | 822 | foreach (SceneObjectPart part in m_parts.Values) |
823 | { | ||
824 | part.AddFullUpdateToAvatar(presence); | ||
825 | } | ||
789 | } | 826 | } |
790 | } | 827 | } |
791 | 828 | ||
792 | public void ScheduleTerseUpdateToAvatar(ScenePresence presence) | 829 | public void ScheduleTerseUpdateToAvatar(ScenePresence presence) |
793 | { | 830 | { |
794 | foreach (SceneObjectPart part in m_parts.Values) | 831 | lock (m_parts) |
795 | { | 832 | { |
796 | part.AddTerseUpdateToAvatar(presence); | 833 | foreach (SceneObjectPart part in m_parts.Values) |
834 | { | ||
835 | part.AddTerseUpdateToAvatar(presence); | ||
836 | } | ||
797 | } | 837 | } |
798 | } | 838 | } |
799 | 839 | ||
@@ -803,9 +843,13 @@ namespace OpenSim.Region.Environment.Scenes | |||
803 | public void ScheduleGroupForFullUpdate() | 843 | public void ScheduleGroupForFullUpdate() |
804 | { | 844 | { |
805 | HasGroupChanged = true; | 845 | HasGroupChanged = true; |
806 | foreach (SceneObjectPart part in m_parts.Values) | 846 | |
847 | lock (m_parts) | ||
807 | { | 848 | { |
808 | part.ScheduleFullUpdate(); | 849 | foreach (SceneObjectPart part in m_parts.Values) |
850 | { | ||
851 | part.ScheduleFullUpdate(); | ||
852 | } | ||
809 | } | 853 | } |
810 | } | 854 | } |
811 | 855 | ||
@@ -815,9 +859,13 @@ namespace OpenSim.Region.Environment.Scenes | |||
815 | public void ScheduleGroupForTerseUpdate() | 859 | public void ScheduleGroupForTerseUpdate() |
816 | { | 860 | { |
817 | HasGroupChanged = true; | 861 | HasGroupChanged = true; |
818 | foreach (SceneObjectPart part in m_parts.Values) | 862 | |
863 | lock (m_parts) | ||
819 | { | 864 | { |
820 | part.ScheduleTerseUpdate(); | 865 | foreach (SceneObjectPart part in m_parts.Values) |
866 | { | ||
867 | part.ScheduleTerseUpdate(); | ||
868 | } | ||
821 | } | 869 | } |
822 | } | 870 | } |
823 | 871 | ||
@@ -827,9 +875,13 @@ namespace OpenSim.Region.Environment.Scenes | |||
827 | public void SendGroupFullUpdate() | 875 | public void SendGroupFullUpdate() |
828 | { | 876 | { |
829 | HasGroupChanged = true; | 877 | HasGroupChanged = true; |
830 | foreach (SceneObjectPart part in m_parts.Values) | 878 | |
879 | lock (m_parts) | ||
831 | { | 880 | { |
832 | part.SendFullUpdateToAllClients(); | 881 | foreach (SceneObjectPart part in m_parts.Values) |
882 | { | ||
883 | part.SendFullUpdateToAllClients(); | ||
884 | } | ||
833 | } | 885 | } |
834 | } | 886 | } |
835 | 887 | ||
@@ -844,9 +896,13 @@ namespace OpenSim.Region.Environment.Scenes | |||
844 | public void SendGroupTerseUpdate() | 896 | public void SendGroupTerseUpdate() |
845 | { | 897 | { |
846 | HasGroupChanged = true; | 898 | HasGroupChanged = true; |
847 | foreach (SceneObjectPart part in m_parts.Values) | 899 | |
900 | lock (m_parts) | ||
848 | { | 901 | { |
849 | part.SendTerseUpdateToAllClients(); | 902 | foreach (SceneObjectPart part in m_parts.Values) |
903 | { | ||
904 | part.SendTerseUpdateToAllClients(); | ||
905 | } | ||
850 | } | 906 | } |
851 | } | 907 | } |
852 | 908 | ||
@@ -861,13 +917,17 @@ namespace OpenSim.Region.Environment.Scenes | |||
861 | /// <returns>null if no child part with that linknum or child part</returns> | 917 | /// <returns>null if no child part with that linknum or child part</returns> |
862 | public SceneObjectPart GetLinkNumPart(int linknum) | 918 | public SceneObjectPart GetLinkNumPart(int linknum) |
863 | { | 919 | { |
864 | foreach (SceneObjectPart part in m_parts.Values) | 920 | lock (m_parts) |
865 | { | 921 | { |
866 | if (part.LinkNum == linknum) | 922 | foreach (SceneObjectPart part in m_parts.Values) |
867 | { | 923 | { |
868 | return part; | 924 | if (part.LinkNum == linknum) |
925 | { | ||
926 | return part; | ||
927 | } | ||
869 | } | 928 | } |
870 | } | 929 | } |
930 | |||
871 | return null; | 931 | return null; |
872 | } | 932 | } |
873 | 933 | ||
@@ -893,13 +953,17 @@ namespace OpenSim.Region.Environment.Scenes | |||
893 | /// <returns>null if a child part with the local ID was not found</returns> | 953 | /// <returns>null if a child part with the local ID was not found</returns> |
894 | public SceneObjectPart GetChildPart(uint localID) | 954 | public SceneObjectPart GetChildPart(uint localID) |
895 | { | 955 | { |
896 | foreach (SceneObjectPart part in m_parts.Values) | 956 | lock (m_parts) |
897 | { | 957 | { |
898 | if (part.LocalId == localID) | 958 | foreach (SceneObjectPart part in m_parts.Values) |
899 | { | 959 | { |
900 | return part; | 960 | if (part.LocalId == localID) |
961 | { | ||
962 | return part; | ||
963 | } | ||
901 | } | 964 | } |
902 | } | 965 | } |
966 | |||
903 | return null; | 967 | return null; |
904 | } | 968 | } |
905 | 969 | ||
@@ -926,11 +990,14 @@ namespace OpenSim.Region.Environment.Scenes | |||
926 | /// <returns></returns> | 990 | /// <returns></returns> |
927 | public bool HasChildPrim(uint localID) | 991 | public bool HasChildPrim(uint localID) |
928 | { | 992 | { |
929 | foreach (SceneObjectPart part in m_parts.Values) | 993 | lock (m_parts) |
930 | { | 994 | { |
931 | if (part.LocalId == localID) | 995 | foreach (SceneObjectPart part in m_parts.Values) |
932 | { | 996 | { |
933 | return true; | 997 | if (part.LocalId == localID) |
998 | { | ||
999 | return true; | ||
1000 | } | ||
934 | } | 1001 | } |
935 | } | 1002 | } |
936 | return false; | 1003 | return false; |
@@ -988,7 +1055,11 @@ namespace OpenSim.Region.Environment.Scenes | |||
988 | 1055 | ||
989 | linkPart.LinkNum = m_parts.Count; | 1056 | linkPart.LinkNum = m_parts.Count; |
990 | 1057 | ||
991 | m_parts.Add(linkPart.UUID, linkPart); | 1058 | lock (m_parts) |
1059 | { | ||
1060 | m_parts.Add(linkPart.UUID, linkPart); | ||
1061 | } | ||
1062 | |||
992 | linkPart.SetParent(this); | 1063 | linkPart.SetParent(this); |
993 | 1064 | ||
994 | //if (linkPart.PhysActor != null) | 1065 | //if (linkPart.PhysActor != null) |
@@ -1038,7 +1109,11 @@ namespace OpenSim.Region.Environment.Scenes | |||
1038 | LLQuaternion worldRot = linkPart.GetWorldRotation(); | 1109 | LLQuaternion worldRot = linkPart.GetWorldRotation(); |
1039 | 1110 | ||
1040 | // Remove the part from this object | 1111 | // Remove the part from this object |
1041 | m_parts.Remove(linkPart.UUID); | 1112 | lock (m_parts) |
1113 | { | ||
1114 | m_parts.Remove(linkPart.UUID); | ||
1115 | } | ||
1116 | |||
1042 | linkPart.ParentID = 0; | 1117 | linkPart.ParentID = 0; |
1043 | 1118 | ||
1044 | if (linkPart.PhysActor != null) | 1119 | if (linkPart.PhysActor != null) |
@@ -1121,7 +1196,11 @@ namespace OpenSim.Region.Environment.Scenes | |||
1121 | part.SetParent(this); | 1196 | part.SetParent(this); |
1122 | part.ParentID = m_rootPart.LocalId; | 1197 | part.ParentID = m_rootPart.LocalId; |
1123 | part.LinkNum = m_parts.Count; | 1198 | part.LinkNum = m_parts.Count; |
1124 | m_parts.Add(part.UUID, part); | 1199 | |
1200 | lock (m_parts) | ||
1201 | { | ||
1202 | m_parts.Add(part.UUID, part); | ||
1203 | } | ||
1125 | 1204 | ||
1126 | Vector3 axiomOldPos = new Vector3(part.OffsetPosition.X, part.OffsetPosition.Y, part.OffsetPosition.Z); | 1205 | Vector3 axiomOldPos = new Vector3(part.OffsetPosition.X, part.OffsetPosition.Y, part.OffsetPosition.Z); |
1127 | axiomOldPos = oldGroupRotation*axiomOldPos; | 1206 | axiomOldPos = oldGroupRotation*axiomOldPos; |
@@ -1297,16 +1376,19 @@ namespace OpenSim.Region.Environment.Scenes | |||
1297 | if (part != null) | 1376 | if (part != null) |
1298 | { | 1377 | { |
1299 | // If we have children | 1378 | // If we have children |
1300 | if (m_parts.Count > 1) | 1379 | lock (m_parts) |
1301 | { | 1380 | { |
1302 | foreach (SceneObjectPart parts in m_parts.Values) | 1381 | if (m_parts.Count > 1) |
1303 | { | 1382 | { |
1304 | parts.UpdatePrimFlags(type, inUse, data); | 1383 | foreach (SceneObjectPart parts in m_parts.Values) |
1384 | { | ||
1385 | parts.UpdatePrimFlags(type, inUse, data); | ||
1386 | } | ||
1387 | } | ||
1388 | else | ||
1389 | { | ||
1390 | part.UpdatePrimFlags(type, inUse, data); | ||
1305 | } | 1391 | } |
1306 | } | ||
1307 | else | ||
1308 | { | ||
1309 | part.UpdatePrimFlags(type, inUse, data); | ||
1310 | } | 1392 | } |
1311 | } | 1393 | } |
1312 | } | 1394 | } |
@@ -1465,13 +1547,17 @@ namespace OpenSim.Region.Environment.Scenes | |||
1465 | diff.Y = axDiff.y; | 1547 | diff.Y = axDiff.y; |
1466 | diff.Z = axDiff.z; | 1548 | diff.Z = axDiff.z; |
1467 | 1549 | ||
1468 | foreach (SceneObjectPart obPart in m_parts.Values) | 1550 | lock (m_parts) |
1469 | { | 1551 | { |
1470 | if (obPart.UUID != m_rootPart.UUID) | 1552 | foreach (SceneObjectPart obPart in m_parts.Values) |
1471 | { | 1553 | { |
1472 | obPart.OffsetPosition = obPart.OffsetPosition + diff; | 1554 | if (obPart.UUID != m_rootPart.UUID) |
1555 | { | ||
1556 | obPart.OffsetPosition = obPart.OffsetPosition + diff; | ||
1557 | } | ||
1473 | } | 1558 | } |
1474 | } | 1559 | } |
1560 | |||
1475 | AbsolutePosition = newPos; | 1561 | AbsolutePosition = newPos; |
1476 | ScheduleGroupForTerseUpdate(); | 1562 | ScheduleGroupForTerseUpdate(); |
1477 | } | 1563 | } |
@@ -1562,23 +1648,27 @@ namespace OpenSim.Region.Environment.Scenes | |||
1562 | m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); | 1648 | m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); |
1563 | } | 1649 | } |
1564 | 1650 | ||
1565 | foreach (SceneObjectPart prim in m_parts.Values) | 1651 | lock (m_parts) |
1566 | { | 1652 | { |
1567 | if (prim.UUID != m_rootPart.UUID) | 1653 | foreach (SceneObjectPart prim in m_parts.Values) |
1568 | { | 1654 | { |
1569 | Vector3 axPos = new Vector3(prim.OffsetPosition.X, prim.OffsetPosition.Y, prim.OffsetPosition.Z); | 1655 | if (prim.UUID != m_rootPart.UUID) |
1570 | axPos = oldParentRot*axPos; | 1656 | { |
1571 | axPos = axRot.Inverse()*axPos; | 1657 | Vector3 axPos = new Vector3(prim.OffsetPosition.X, prim.OffsetPosition.Y, prim.OffsetPosition.Z); |
1572 | prim.OffsetPosition = new LLVector3(axPos.x, axPos.y, axPos.z); | 1658 | axPos = oldParentRot*axPos; |
1573 | Quaternion primsRot = | 1659 | axPos = axRot.Inverse()*axPos; |
1574 | new Quaternion(prim.RotationOffset.W, prim.RotationOffset.X, prim.RotationOffset.Y, | 1660 | prim.OffsetPosition = new LLVector3(axPos.x, axPos.y, axPos.z); |
1575 | prim.RotationOffset.Z); | 1661 | Quaternion primsRot = |
1576 | Quaternion newRot = oldParentRot*primsRot; | 1662 | new Quaternion(prim.RotationOffset.W, prim.RotationOffset.X, prim.RotationOffset.Y, |
1577 | newRot = axRot.Inverse()*newRot; | 1663 | prim.RotationOffset.Z); |
1578 | prim.RotationOffset = new LLQuaternion(newRot.x, newRot.y, newRot.z, newRot.w); | 1664 | Quaternion newRot = oldParentRot*primsRot; |
1579 | prim.ScheduleTerseUpdate(); | 1665 | newRot = axRot.Inverse()*newRot; |
1666 | prim.RotationOffset = new LLQuaternion(newRot.x, newRot.y, newRot.z, newRot.w); | ||
1667 | prim.ScheduleTerseUpdate(); | ||
1668 | } | ||
1580 | } | 1669 | } |
1581 | } | 1670 | } |
1671 | |||
1582 | m_rootPart.ScheduleTerseUpdate(); | 1672 | m_rootPart.ScheduleTerseUpdate(); |
1583 | } | 1673 | } |
1584 | 1674 | ||
@@ -1693,15 +1783,20 @@ namespace OpenSim.Region.Environment.Scenes | |||
1693 | 1783 | ||
1694 | public override void UpdateMovement() | 1784 | public override void UpdateMovement() |
1695 | { | 1785 | { |
1696 | foreach (SceneObjectPart part in m_parts.Values) | 1786 | lock (m_parts) |
1697 | { | 1787 | { |
1698 | part.UpdateMovement(); | 1788 | foreach (SceneObjectPart part in m_parts.Values) |
1789 | { | ||
1790 | part.UpdateMovement(); | ||
1791 | } | ||
1699 | } | 1792 | } |
1700 | } | 1793 | } |
1794 | |||
1701 | public float GetTimeDilation() | 1795 | public float GetTimeDilation() |
1702 | { | 1796 | { |
1703 | return m_scene.TimeDilation; | 1797 | return m_scene.TimeDilation; |
1704 | } | 1798 | } |
1799 | |||
1705 | /// <summary> | 1800 | /// <summary> |
1706 | /// Added as a way for the storage provider to reset the scene, | 1801 | /// Added as a way for the storage provider to reset the scene, |
1707 | /// most likely a better way to do this sort of thing but for now... | 1802 | /// most likely a better way to do this sort of thing but for now... |
@@ -1719,12 +1814,17 @@ namespace OpenSim.Region.Environment.Scenes | |||
1719 | /// <param name="part"></param> | 1814 | /// <param name="part"></param> |
1720 | public void AddPart(SceneObjectPart part) | 1815 | public void AddPart(SceneObjectPart part) |
1721 | { | 1816 | { |
1722 | lock (m_parts) { | 1817 | lock (m_parts) |
1818 | { | ||
1723 | part.SetParent(this); | 1819 | part.SetParent(this); |
1724 | part.LinkNum = m_parts.Count; | 1820 | part.LinkNum = m_parts.Count; |
1725 | try { | 1821 | |
1822 | try | ||
1823 | { | ||
1726 | m_parts.Add(part.UUID, part); | 1824 | m_parts.Add(part.UUID, part); |
1727 | } catch (Exception e) { | 1825 | } |
1826 | catch (Exception e) | ||
1827 | { | ||
1728 | m_log.Error("Failed to add scened object part", e); | 1828 | m_log.Error("Failed to add scened object part", e); |
1729 | } | 1829 | } |
1730 | } | 1830 | } |
@@ -1735,20 +1835,26 @@ namespace OpenSim.Region.Environment.Scenes | |||
1735 | /// </summary> | 1835 | /// </summary> |
1736 | public void UpdateParentIDs() | 1836 | public void UpdateParentIDs() |
1737 | { | 1837 | { |
1738 | foreach (SceneObjectPart part in m_parts.Values) | 1838 | lock (m_parts) |
1739 | { | 1839 | { |
1740 | if (part.UUID != m_rootPart.UUID) | 1840 | foreach (SceneObjectPart part in m_parts.Values) |
1741 | { | 1841 | { |
1742 | part.ParentID = m_rootPart.LocalId; | 1842 | if (part.UUID != m_rootPart.UUID) |
1843 | { | ||
1844 | part.ParentID = m_rootPart.LocalId; | ||
1845 | } | ||
1743 | } | 1846 | } |
1744 | } | 1847 | } |
1745 | } | 1848 | } |
1746 | 1849 | ||
1747 | public void RegenerateFullIDs() | 1850 | public void RegenerateFullIDs() |
1748 | { | 1851 | { |
1749 | foreach (SceneObjectPart part in m_parts.Values) | 1852 | lock (m_parts) |
1750 | { | 1853 | { |
1751 | part.UUID = LLUUID.Random(); | 1854 | foreach (SceneObjectPart part in m_parts.Values) |
1855 | { | ||
1856 | part.UUID = LLUUID.Random(); | ||
1857 | } | ||
1752 | } | 1858 | } |
1753 | } | 1859 | } |
1754 | 1860 | ||
@@ -1803,17 +1909,21 @@ namespace OpenSim.Region.Environment.Scenes | |||
1803 | public void DeleteGroup() | 1909 | public void DeleteGroup() |
1804 | { | 1910 | { |
1805 | DetachFromBackup(this); | 1911 | DetachFromBackup(this); |
1806 | foreach (SceneObjectPart part in m_parts.Values) | 1912 | |
1913 | lock (m_parts) | ||
1807 | { | 1914 | { |
1808 | List<ScenePresence> avatars = GetScenePresences(); | 1915 | foreach (SceneObjectPart part in m_parts.Values) |
1809 | for (int i = 0; i < avatars.Count; i++) | ||
1810 | { | 1916 | { |
1811 | if (avatars[i].ParentID == LocalId) | 1917 | List<ScenePresence> avatars = GetScenePresences(); |
1918 | for (int i = 0; i < avatars.Count; i++) | ||
1812 | { | 1919 | { |
1813 | avatars[i].StandUp(); | 1920 | if (avatars[i].ParentID == LocalId) |
1814 | } | 1921 | { |
1922 | avatars[i].StandUp(); | ||
1923 | } | ||
1815 | 1924 | ||
1816 | avatars[i].ControllingClient.SendKillObject(m_regionHandle, part.LocalId); | 1925 | avatars[i].ControllingClient.SendKillObject(m_regionHandle, part.LocalId); |
1926 | } | ||
1817 | } | 1927 | } |
1818 | } | 1928 | } |
1819 | } | 1929 | } |
@@ -1829,10 +1939,10 @@ namespace OpenSim.Region.Environment.Scenes | |||
1829 | { | 1939 | { |
1830 | part.StopScripts(); | 1940 | part.StopScripts(); |
1831 | } | 1941 | } |
1942 | |||
1943 | m_rootPart = null; | ||
1944 | m_parts.Clear(); | ||
1832 | } | 1945 | } |
1833 | |||
1834 | m_rootPart = null; | ||
1835 | m_parts.Clear(); | ||
1836 | } | 1946 | } |
1837 | 1947 | ||
1838 | public void AddScriptLPS(int count) | 1948 | public void AddScriptLPS(int count) |
@@ -1858,9 +1968,9 @@ namespace OpenSim.Region.Environment.Scenes | |||
1858 | 1968 | ||
1859 | public void ApplyPhysics(bool m_physicalPrim) | 1969 | public void ApplyPhysics(bool m_physicalPrim) |
1860 | { | 1970 | { |
1861 | if (m_parts.Count > 1) | 1971 | lock (m_parts) |
1862 | { | 1972 | { |
1863 | lock (m_parts) | 1973 | if (m_parts.Count > 1) |
1864 | { | 1974 | { |
1865 | m_rootPart.ApplyPhysics(m_rootPart.ObjectFlags, m_physicalPrim); | 1975 | m_rootPart.ApplyPhysics(m_rootPart.ObjectFlags, m_physicalPrim); |
1866 | foreach (SceneObjectPart part in m_parts.Values) | 1976 | foreach (SceneObjectPart part in m_parts.Values) |
@@ -1874,10 +1984,10 @@ namespace OpenSim.Region.Environment.Scenes | |||
1874 | 1984 | ||
1875 | } | 1985 | } |
1876 | } | 1986 | } |
1877 | } | 1987 | else |
1878 | else | 1988 | { |
1879 | { | 1989 | m_rootPart.ApplyPhysics(m_rootPart.ObjectFlags, m_physicalPrim); |
1880 | m_rootPart.ApplyPhysics(m_rootPart.ObjectFlags, m_physicalPrim); | 1990 | } |
1881 | } | 1991 | } |
1882 | } | 1992 | } |
1883 | 1993 | ||