diff options
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs')
-rw-r--r-- | OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 585 |
1 files changed, 387 insertions, 198 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index c5a6171..f35a7c5 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | |||
@@ -106,6 +106,72 @@ namespace OpenSim.Region.Framework.Scenes | |||
106 | private bool m_hasGroupChanged = false; | 106 | private bool m_hasGroupChanged = false; |
107 | private long timeFirstChanged; | 107 | private long timeFirstChanged; |
108 | private long timeLastChanged; | 108 | private long timeLastChanged; |
109 | private System.Threading.ReaderWriterLockSlim m_partsLock = new System.Threading.ReaderWriterLockSlim(); | ||
110 | |||
111 | public void lockPartsForRead(bool locked) | ||
112 | { | ||
113 | if (locked) | ||
114 | { | ||
115 | if (m_partsLock.RecursiveReadCount > 0) | ||
116 | { | ||
117 | m_log.Error("[SceneObjectGroup.m_parts] Recursive read lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue."); | ||
118 | m_partsLock.ExitReadLock(); | ||
119 | } | ||
120 | if (m_partsLock.RecursiveWriteCount > 0) | ||
121 | { | ||
122 | m_log.Error("[SceneObjectGroup.m_parts] Recursive read lock requested. This should not happen and means something needs to be fixed."); | ||
123 | m_partsLock.ExitWriteLock(); | ||
124 | } | ||
125 | |||
126 | while (!m_partsLock.TryEnterReadLock(60000)) | ||
127 | { | ||
128 | m_log.Error("[SceneObjectGroup.m_parts] Thread lock detected while trying to aquire READ lock of m_parts in SceneObjectGroup. I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed."); | ||
129 | if (m_partsLock.IsWriteLockHeld) | ||
130 | { | ||
131 | m_partsLock = new System.Threading.ReaderWriterLockSlim(); | ||
132 | } | ||
133 | } | ||
134 | } | ||
135 | else | ||
136 | { | ||
137 | if (m_partsLock.RecursiveReadCount > 0) | ||
138 | { | ||
139 | m_partsLock.ExitReadLock(); | ||
140 | } | ||
141 | } | ||
142 | } | ||
143 | public void lockPartsForWrite(bool locked) | ||
144 | { | ||
145 | if (locked) | ||
146 | { | ||
147 | if (m_partsLock.RecursiveReadCount > 0) | ||
148 | { | ||
149 | m_log.Error("[SceneObjectGroup.m_parts] Recursive write lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue."); | ||
150 | m_partsLock.ExitReadLock(); | ||
151 | } | ||
152 | if (m_partsLock.RecursiveWriteCount > 0) | ||
153 | { | ||
154 | m_log.Error("[SceneObjectGroup.m_parts] Recursive write lock requested. This should not happen and means something needs to be fixed."); | ||
155 | m_partsLock.ExitWriteLock(); | ||
156 | } | ||
157 | |||
158 | while (!m_partsLock.TryEnterWriteLock(60000)) | ||
159 | { | ||
160 | m_log.Error("[SceneObjectGroup.m_parts] Thread lock detected while trying to aquire WRITE lock of m_scripts in XEngine. I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed."); | ||
161 | if (m_partsLock.IsWriteLockHeld) | ||
162 | { | ||
163 | m_partsLock = new System.Threading.ReaderWriterLockSlim(); | ||
164 | } | ||
165 | } | ||
166 | } | ||
167 | else | ||
168 | { | ||
169 | if (m_partsLock.RecursiveWriteCount > 0) | ||
170 | { | ||
171 | m_partsLock.ExitWriteLock(); | ||
172 | } | ||
173 | } | ||
174 | } | ||
109 | 175 | ||
110 | public bool HasGroupChanged | 176 | public bool HasGroupChanged |
111 | { | 177 | { |
@@ -258,13 +324,16 @@ namespace OpenSim.Region.Framework.Scenes | |||
258 | set | 324 | set |
259 | { | 325 | { |
260 | m_regionHandle = value; | 326 | m_regionHandle = value; |
261 | lock (m_parts) | 327 | lockPartsForRead(true); |
262 | { | 328 | { |
263 | foreach (SceneObjectPart part in m_parts.Values) | 329 | foreach (SceneObjectPart part in m_parts.Values) |
264 | { | 330 | { |
331 | |||
265 | part.RegionHandle = m_regionHandle; | 332 | part.RegionHandle = m_regionHandle; |
333 | |||
266 | } | 334 | } |
267 | } | 335 | } |
336 | lockPartsForRead(false); | ||
268 | } | 337 | } |
269 | } | 338 | } |
270 | 339 | ||
@@ -298,6 +367,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
298 | { | 367 | { |
299 | m_scene.CrossPrimGroupIntoNewRegion(val, this, true); | 368 | m_scene.CrossPrimGroupIntoNewRegion(val, this, true); |
300 | } | 369 | } |
370 | |||
371 | lockPartsForRead(true); | ||
372 | |||
301 | if (RootPart.GetStatusSandbox()) | 373 | if (RootPart.GetStatusSandbox()) |
302 | { | 374 | { |
303 | if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) | 375 | if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) |
@@ -308,14 +380,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
308 | return; | 380 | return; |
309 | } | 381 | } |
310 | } | 382 | } |
311 | lock (m_parts) | 383 | |
384 | foreach (SceneObjectPart part in m_parts.Values) | ||
312 | { | 385 | { |
313 | foreach (SceneObjectPart part in m_parts.Values) | 386 | part.GroupPosition = val; |
314 | { | ||
315 | part.GroupPosition = val; | ||
316 | } | ||
317 | } | 387 | } |
318 | 388 | ||
389 | lockPartsForRead(false); | ||
390 | |||
319 | //if (m_rootPart.PhysActor != null) | 391 | //if (m_rootPart.PhysActor != null) |
320 | //{ | 392 | //{ |
321 | //m_rootPart.PhysActor.Position = | 393 | //m_rootPart.PhysActor.Position = |
@@ -504,13 +576,16 @@ namespace OpenSim.Region.Framework.Scenes | |||
504 | 576 | ||
505 | public void SetFromItemID(UUID AssetId) | 577 | public void SetFromItemID(UUID AssetId) |
506 | { | 578 | { |
507 | lock (m_parts) | 579 | lockPartsForRead(true); |
508 | { | 580 | { |
509 | foreach (SceneObjectPart part in m_parts.Values) | 581 | foreach (SceneObjectPart part in m_parts.Values) |
510 | { | 582 | { |
583 | |||
511 | part.FromItemID = AssetId; | 584 | part.FromItemID = AssetId; |
585 | |||
512 | } | 586 | } |
513 | } | 587 | } |
588 | lockPartsForRead(false); | ||
514 | } | 589 | } |
515 | 590 | ||
516 | public UUID GetFromItemID() | 591 | public UUID GetFromItemID() |
@@ -577,10 +652,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
577 | Vector3 maxScale = Vector3.Zero; | 652 | Vector3 maxScale = Vector3.Zero; |
578 | Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f); | 653 | Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f); |
579 | 654 | ||
580 | lock (m_parts) | 655 | lockPartsForRead(true); |
581 | { | 656 | { |
582 | foreach (SceneObjectPart part in m_parts.Values) | 657 | foreach (SceneObjectPart part in m_parts.Values) |
583 | { | 658 | { |
659 | |||
584 | Vector3 partscale = part.Scale; | 660 | Vector3 partscale = part.Scale; |
585 | Vector3 partoffset = part.OffsetPosition; | 661 | Vector3 partoffset = part.OffsetPosition; |
586 | 662 | ||
@@ -591,8 +667,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
591 | maxScale.X = (partscale.X + partoffset.X > maxScale.X) ? partscale.X + partoffset.X : maxScale.X; | 667 | maxScale.X = (partscale.X + partoffset.X > maxScale.X) ? partscale.X + partoffset.X : maxScale.X; |
592 | maxScale.Y = (partscale.Y + partoffset.Y > maxScale.Y) ? partscale.Y + partoffset.Y : maxScale.Y; | 668 | maxScale.Y = (partscale.Y + partoffset.Y > maxScale.Y) ? partscale.Y + partoffset.Y : maxScale.Y; |
593 | maxScale.Z = (partscale.Z + partoffset.Z > maxScale.Z) ? partscale.Z + partoffset.Z : maxScale.Z; | 669 | maxScale.Z = (partscale.Z + partoffset.Z > maxScale.Z) ? partscale.Z + partoffset.Z : maxScale.Z; |
670 | |||
594 | } | 671 | } |
595 | } | 672 | } |
673 | lockPartsForRead(false); | ||
674 | |||
596 | finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X; | 675 | finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X; |
597 | finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y; | 676 | finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y; |
598 | finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z; | 677 | finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z; |
@@ -608,10 +687,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
608 | 687 | ||
609 | EntityIntersection result = new EntityIntersection(); | 688 | EntityIntersection result = new EntityIntersection(); |
610 | 689 | ||
611 | lock (m_parts) | 690 | lockPartsForRead(true); |
612 | { | 691 | { |
613 | foreach (SceneObjectPart part in m_parts.Values) | 692 | foreach (SceneObjectPart part in m_parts.Values) |
614 | { | 693 | { |
694 | |||
615 | // Temporary commented to stop compiler warning | 695 | // Temporary commented to stop compiler warning |
616 | //Vector3 partPosition = | 696 | //Vector3 partPosition = |
617 | // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z); | 697 | // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z); |
@@ -639,8 +719,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
639 | result.distance = inter.distance; | 719 | result.distance = inter.distance; |
640 | } | 720 | } |
641 | } | 721 | } |
722 | |||
642 | } | 723 | } |
643 | } | 724 | } |
725 | lockPartsForRead(false); | ||
644 | return result; | 726 | return result; |
645 | } | 727 | } |
646 | 728 | ||
@@ -653,10 +735,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
653 | public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight) | 735 | public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight) |
654 | { | 736 | { |
655 | float maxX = -256f, maxY = -256f, maxZ = -256f, minX = 256f, minY = 256f, minZ = 256f; | 737 | float maxX = -256f, maxY = -256f, maxZ = -256f, minX = 256f, minY = 256f, minZ = 256f; |
656 | lock (m_parts) | 738 | lockPartsForRead(true); |
657 | { | 739 | { |
658 | foreach (SceneObjectPart part in m_parts.Values) | 740 | foreach (SceneObjectPart part in m_parts.Values) |
659 | { | 741 | { |
742 | |||
660 | Vector3 worldPos = part.GetWorldPosition(); | 743 | Vector3 worldPos = part.GetWorldPosition(); |
661 | Vector3 offset = worldPos - AbsolutePosition; | 744 | Vector3 offset = worldPos - AbsolutePosition; |
662 | Quaternion worldRot; | 745 | Quaternion worldRot; |
@@ -715,6 +798,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
715 | backBottomRight.Y = orig.Y + (part.Scale.Y / 2); | 798 | backBottomRight.Y = orig.Y + (part.Scale.Y / 2); |
716 | backBottomRight.Z = orig.Z - (part.Scale.Z / 2); | 799 | backBottomRight.Z = orig.Z - (part.Scale.Z / 2); |
717 | 800 | ||
801 | |||
802 | |||
718 | //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z); | 803 | //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z); |
719 | //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z); | 804 | //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z); |
720 | //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z); | 805 | //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z); |
@@ -886,6 +971,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
886 | minZ = backBottomLeft.Z; | 971 | minZ = backBottomLeft.Z; |
887 | } | 972 | } |
888 | } | 973 | } |
974 | lockPartsForRead(false); | ||
889 | 975 | ||
890 | Vector3 boundingBox = new Vector3(maxX - minX, maxY - minY, maxZ - minZ); | 976 | Vector3 boundingBox = new Vector3(maxX - minX, maxY - minY, maxZ - minZ); |
891 | 977 | ||
@@ -914,17 +1000,20 @@ namespace OpenSim.Region.Framework.Scenes | |||
914 | Dictionary<UUID,string> states = new Dictionary<UUID,string>(); | 1000 | Dictionary<UUID,string> states = new Dictionary<UUID,string>(); |
915 | 1001 | ||
916 | // Capture script state while holding the lock | 1002 | // Capture script state while holding the lock |
917 | lock (m_parts) | 1003 | lockPartsForRead(true); |
918 | { | 1004 | { |
919 | foreach (SceneObjectPart part in m_parts.Values) | 1005 | foreach (SceneObjectPart part in m_parts.Values) |
920 | { | 1006 | { |
1007 | |||
921 | Dictionary<UUID,string> pstates = part.Inventory.GetScriptStates(); | 1008 | Dictionary<UUID,string> pstates = part.Inventory.GetScriptStates(); |
922 | foreach (UUID itemid in pstates.Keys) | 1009 | foreach (UUID itemid in pstates.Keys) |
923 | { | 1010 | { |
924 | states.Add(itemid, pstates[itemid]); | 1011 | states.Add(itemid, pstates[itemid]); |
925 | } | 1012 | } |
1013 | |||
926 | } | 1014 | } |
927 | } | 1015 | } |
1016 | lockPartsForRead(false); | ||
928 | 1017 | ||
929 | if (states.Count > 0) | 1018 | if (states.Count > 0) |
930 | { | 1019 | { |
@@ -1086,13 +1175,16 @@ namespace OpenSim.Region.Framework.Scenes | |||
1086 | 1175 | ||
1087 | public override void UpdateMovement() | 1176 | public override void UpdateMovement() |
1088 | { | 1177 | { |
1089 | lock (m_parts) | 1178 | lockPartsForRead(true); |
1090 | { | 1179 | { |
1091 | foreach (SceneObjectPart part in m_parts.Values) | 1180 | foreach (SceneObjectPart part in m_parts.Values) |
1092 | { | 1181 | { |
1182 | |||
1093 | part.UpdateMovement(); | 1183 | part.UpdateMovement(); |
1184 | |||
1094 | } | 1185 | } |
1095 | } | 1186 | } |
1187 | lockPartsForRead(false); | ||
1096 | } | 1188 | } |
1097 | 1189 | ||
1098 | public ushort GetTimeDilation() | 1190 | public ushort GetTimeDilation() |
@@ -1136,7 +1228,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1136 | /// <param name="part"></param> | 1228 | /// <param name="part"></param> |
1137 | public void AddPart(SceneObjectPart part) | 1229 | public void AddPart(SceneObjectPart part) |
1138 | { | 1230 | { |
1139 | lock (m_parts) | 1231 | lockPartsForWrite(true); |
1140 | { | 1232 | { |
1141 | part.SetParent(this); | 1233 | part.SetParent(this); |
1142 | m_parts.Add(part.UUID, part); | 1234 | m_parts.Add(part.UUID, part); |
@@ -1146,6 +1238,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1146 | if (part.LinkNum == 2 && RootPart != null) | 1238 | if (part.LinkNum == 2 && RootPart != null) |
1147 | RootPart.LinkNum = 1; | 1239 | RootPart.LinkNum = 1; |
1148 | } | 1240 | } |
1241 | lockPartsForWrite(false); | ||
1149 | } | 1242 | } |
1150 | 1243 | ||
1151 | /// <summary> | 1244 | /// <summary> |
@@ -1153,28 +1246,33 @@ namespace OpenSim.Region.Framework.Scenes | |||
1153 | /// </summary> | 1246 | /// </summary> |
1154 | private void UpdateParentIDs() | 1247 | private void UpdateParentIDs() |
1155 | { | 1248 | { |
1156 | lock (m_parts) | 1249 | lockPartsForRead(true); |
1157 | { | 1250 | { |
1158 | foreach (SceneObjectPart part in m_parts.Values) | 1251 | foreach (SceneObjectPart part in m_parts.Values) |
1159 | { | 1252 | { |
1253 | |||
1160 | if (part.UUID != m_rootPart.UUID) | 1254 | if (part.UUID != m_rootPart.UUID) |
1161 | { | 1255 | { |
1162 | part.ParentID = m_rootPart.LocalId; | 1256 | part.ParentID = m_rootPart.LocalId; |
1163 | } | 1257 | } |
1258 | |||
1164 | } | 1259 | } |
1165 | } | 1260 | } |
1261 | lockPartsForRead(false); | ||
1166 | } | 1262 | } |
1167 | 1263 | ||
1168 | public void RegenerateFullIDs() | 1264 | public void RegenerateFullIDs() |
1169 | { | 1265 | { |
1170 | lock (m_parts) | 1266 | lockPartsForRead(true); |
1171 | { | 1267 | { |
1172 | foreach (SceneObjectPart part in m_parts.Values) | 1268 | foreach (SceneObjectPart part in m_parts.Values) |
1173 | { | 1269 | { |
1270 | |||
1174 | part.UUID = UUID.Random(); | 1271 | part.UUID = UUID.Random(); |
1175 | 1272 | ||
1176 | } | 1273 | } |
1177 | } | 1274 | } |
1275 | lockPartsForRead(false); | ||
1178 | } | 1276 | } |
1179 | 1277 | ||
1180 | // helper provided for parts. | 1278 | // helper provided for parts. |
@@ -1255,29 +1353,33 @@ namespace OpenSim.Region.Framework.Scenes | |||
1255 | 1353 | ||
1256 | DetachFromBackup(); | 1354 | DetachFromBackup(); |
1257 | 1355 | ||
1258 | lock (m_parts) | 1356 | lockPartsForRead(true); |
1357 | List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values); | ||
1358 | lockPartsForRead(false); | ||
1359 | |||
1360 | foreach (SceneObjectPart part in values) | ||
1259 | { | 1361 | { |
1260 | foreach (SceneObjectPart part in m_parts.Values) | ||
1261 | { | ||
1262 | // part.Inventory.RemoveScriptInstances(); | 1362 | // part.Inventory.RemoveScriptInstances(); |
1263 | 1363 | ||
1264 | ScenePresence[] avatars = Scene.GetScenePresences(); | 1364 | ScenePresence[] avatars = Scene.GetScenePresences(); |
1265 | for (int i = 0; i < avatars.Length; i++) | 1365 | for (int i = 0; i < avatars.Length; i++) |
1366 | { | ||
1367 | if (avatars[i].ParentID == LocalId) | ||
1266 | { | 1368 | { |
1267 | if (avatars[i].ParentID == LocalId) | 1369 | avatars[i].StandUp(); |
1268 | { | 1370 | } |
1269 | avatars[i].StandUp(); | ||
1270 | } | ||
1271 | 1371 | ||
1272 | if (!silent) | 1372 | if (!silent) |
1273 | { | 1373 | { |
1274 | part.UpdateFlag = 0; | 1374 | part.UpdateFlag = 0; |
1275 | if (part == m_rootPart) | 1375 | if (part == m_rootPart) |
1276 | avatars[i].ControllingClient.SendKillObject(m_regionHandle, part.LocalId); | 1376 | avatars[i].ControllingClient.SendKillObject(m_regionHandle, part.LocalId); |
1277 | } | ||
1278 | } | 1377 | } |
1279 | } | 1378 | } |
1379 | |||
1280 | } | 1380 | } |
1381 | |||
1382 | |||
1281 | } | 1383 | } |
1282 | 1384 | ||
1283 | public void AddScriptLPS(int count) | 1385 | public void AddScriptLPS(int count) |
@@ -1302,17 +1404,20 @@ namespace OpenSim.Region.Framework.Scenes | |||
1302 | 1404 | ||
1303 | scriptEvents aggregateScriptEvents=0; | 1405 | scriptEvents aggregateScriptEvents=0; |
1304 | 1406 | ||
1305 | lock (m_parts) | 1407 | lockPartsForRead(true); |
1306 | { | 1408 | { |
1307 | foreach (SceneObjectPart part in m_parts.Values) | 1409 | foreach (SceneObjectPart part in m_parts.Values) |
1308 | { | 1410 | { |
1411 | |||
1309 | if (part == null) | 1412 | if (part == null) |
1310 | continue; | 1413 | continue; |
1311 | if (part != RootPart) | 1414 | if (part != RootPart) |
1312 | part.ObjectFlags = objectflagupdate; | 1415 | part.ObjectFlags = objectflagupdate; |
1313 | aggregateScriptEvents |= part.AggregateScriptEvents; | 1416 | aggregateScriptEvents |= part.AggregateScriptEvents; |
1417 | |||
1314 | } | 1418 | } |
1315 | } | 1419 | } |
1420 | lockPartsForRead(false); | ||
1316 | 1421 | ||
1317 | m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0); | 1422 | m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0); |
1318 | m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0); | 1423 | m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0); |
@@ -1354,42 +1459,52 @@ namespace OpenSim.Region.Framework.Scenes | |||
1354 | /// <param name="m_physicalPrim"></param> | 1459 | /// <param name="m_physicalPrim"></param> |
1355 | public void ApplyPhysics(bool m_physicalPrim) | 1460 | public void ApplyPhysics(bool m_physicalPrim) |
1356 | { | 1461 | { |
1357 | lock (m_parts) | 1462 | lockPartsForRead(true); |
1463 | |||
1464 | if (m_parts.Count > 1) | ||
1358 | { | 1465 | { |
1359 | if (m_parts.Count > 1) | 1466 | List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values); |
1467 | lockPartsForRead(false); | ||
1468 | m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim); | ||
1469 | foreach (SceneObjectPart part in values) | ||
1360 | { | 1470 | { |
1361 | m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim); | 1471 | |
1362 | foreach (SceneObjectPart part in m_parts.Values) | 1472 | if (part.LocalId != m_rootPart.LocalId) |
1363 | { | 1473 | { |
1364 | if (part.LocalId != m_rootPart.LocalId) | 1474 | part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim); |
1365 | { | ||
1366 | part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim); | ||
1367 | } | ||
1368 | } | 1475 | } |
1369 | 1476 | ||
1370 | // Hack to get the physics scene geometries in the right spot | ||
1371 | ResetChildPrimPhysicsPositions(); | ||
1372 | } | ||
1373 | else | ||
1374 | { | ||
1375 | m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim); | ||
1376 | } | 1477 | } |
1478 | // Hack to get the physics scene geometries in the right spot | ||
1479 | ResetChildPrimPhysicsPositions(); | ||
1480 | } | ||
1481 | else | ||
1482 | { | ||
1483 | lockPartsForRead(false); | ||
1484 | m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim); | ||
1377 | } | 1485 | } |
1378 | } | 1486 | } |
1379 | 1487 | ||
1380 | public void SetOwnerId(UUID userId) | 1488 | public void SetOwnerId(UUID userId) |
1381 | { | 1489 | { |
1382 | ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); | 1490 | ForEachPart(delegate(SceneObjectPart part) |
1491 | { | ||
1492 | |||
1493 | part.OwnerID = userId; | ||
1494 | |||
1495 | }); | ||
1383 | } | 1496 | } |
1384 | 1497 | ||
1385 | public void ForEachPart(Action<SceneObjectPart> whatToDo) | 1498 | public void ForEachPart(Action<SceneObjectPart> whatToDo) |
1386 | { | 1499 | { |
1387 | lock (m_parts) | 1500 | lockPartsForRead(true); |
1501 | List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values); | ||
1502 | lockPartsForRead(false); | ||
1503 | foreach (SceneObjectPart part in values) | ||
1388 | { | 1504 | { |
1389 | foreach (SceneObjectPart part in m_parts.Values) | 1505 | |
1390 | { | 1506 | whatToDo(part); |
1391 | whatToDo(part); | 1507 | |
1392 | } | ||
1393 | } | 1508 | } |
1394 | } | 1509 | } |
1395 | 1510 | ||
@@ -1488,14 +1603,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
1488 | { | 1603 | { |
1489 | SendPartFullUpdate(remoteClient, RootPart, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID)); | 1604 | SendPartFullUpdate(remoteClient, RootPart, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID)); |
1490 | 1605 | ||
1491 | lock (m_parts) | 1606 | lockPartsForRead(true); |
1492 | { | 1607 | { |
1493 | foreach (SceneObjectPart part in m_parts.Values) | 1608 | foreach (SceneObjectPart part in m_parts.Values) |
1494 | { | 1609 | { |
1610 | |||
1495 | if (part != RootPart) | 1611 | if (part != RootPart) |
1496 | SendPartFullUpdate(remoteClient, part, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID)); | 1612 | SendPartFullUpdate(remoteClient, part, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID)); |
1613 | |||
1497 | } | 1614 | } |
1498 | } | 1615 | } |
1616 | lockPartsForRead(false); | ||
1499 | } | 1617 | } |
1500 | 1618 | ||
1501 | /// <summary> | 1619 | /// <summary> |
@@ -1593,10 +1711,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
1593 | 1711 | ||
1594 | List<SceneObjectPart> partList; | 1712 | List<SceneObjectPart> partList; |
1595 | 1713 | ||
1596 | lock (m_parts) | 1714 | lockPartsForRead(true); |
1597 | { | 1715 | |
1598 | partList = new List<SceneObjectPart>(m_parts.Values); | 1716 | partList = new List<SceneObjectPart>(m_parts.Values); |
1599 | } | 1717 | |
1718 | lockPartsForRead(false); | ||
1600 | 1719 | ||
1601 | partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) | 1720 | partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) |
1602 | { | 1721 | { |
@@ -1819,6 +1938,33 @@ namespace OpenSim.Region.Framework.Scenes | |||
1819 | } | 1938 | } |
1820 | } | 1939 | } |
1821 | 1940 | ||
1941 | public void rotLookAt(Quaternion target, float strength, float damping) | ||
1942 | { | ||
1943 | SceneObjectPart rootpart = m_rootPart; | ||
1944 | if (rootpart != null) | ||
1945 | { | ||
1946 | if (IsAttachment) | ||
1947 | { | ||
1948 | /* | ||
1949 | ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar); | ||
1950 | if (avatar != null) | ||
1951 | { | ||
1952 | Rotate the Av? | ||
1953 | } */ | ||
1954 | } | ||
1955 | else | ||
1956 | { | ||
1957 | if (rootpart.PhysActor != null) | ||
1958 | { | ||
1959 | rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W); | ||
1960 | rootpart.PhysActor.APIDStrength = strength; | ||
1961 | rootpart.PhysActor.APIDDamping = damping; | ||
1962 | rootpart.PhysActor.APIDActive = true; | ||
1963 | } | ||
1964 | } | ||
1965 | } | ||
1966 | } | ||
1967 | |||
1822 | public void stopLookAt() | 1968 | public void stopLookAt() |
1823 | { | 1969 | { |
1824 | SceneObjectPart rootpart = m_rootPart; | 1970 | SceneObjectPart rootpart = m_rootPart; |
@@ -1893,10 +2039,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
1893 | SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); | 2039 | SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); |
1894 | newPart.SetParent(this); | 2040 | newPart.SetParent(this); |
1895 | 2041 | ||
1896 | lock (m_parts) | 2042 | lockPartsForWrite(true); |
1897 | { | 2043 | { |
1898 | m_parts.Add(newPart.UUID, newPart); | 2044 | m_parts.Add(newPart.UUID, newPart); |
1899 | } | 2045 | } |
2046 | lockPartsForWrite(false); | ||
1900 | 2047 | ||
1901 | SetPartAsNonRoot(newPart); | 2048 | SetPartAsNonRoot(newPart); |
1902 | 2049 | ||
@@ -1959,7 +2106,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1959 | //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0) | 2106 | //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0) |
1960 | // return; | 2107 | // return; |
1961 | 2108 | ||
1962 | lock (m_parts) | 2109 | lockPartsForRead(true); |
1963 | { | 2110 | { |
1964 | bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0); | 2111 | bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0); |
1965 | 2112 | ||
@@ -1979,34 +2126,43 @@ namespace OpenSim.Region.Framework.Scenes | |||
1979 | { | 2126 | { |
1980 | if (!IsSelected) | 2127 | if (!IsSelected) |
1981 | part.UpdateLookAt(); | 2128 | part.UpdateLookAt(); |
2129 | |||
1982 | part.SendScheduledUpdates(); | 2130 | part.SendScheduledUpdates(); |
2131 | |||
1983 | } | 2132 | } |
1984 | } | 2133 | } |
2134 | lockPartsForRead(false); | ||
1985 | } | 2135 | } |
1986 | 2136 | ||
1987 | public void ScheduleFullUpdateToAvatar(ScenePresence presence) | 2137 | public void ScheduleFullUpdateToAvatar(ScenePresence presence) |
1988 | { | 2138 | { |
1989 | RootPart.AddFullUpdateToAvatar(presence); | 2139 | RootPart.AddFullUpdateToAvatar(presence); |
1990 | 2140 | ||
1991 | lock (m_parts) | 2141 | lockPartsForRead(true); |
1992 | { | 2142 | { |
1993 | foreach (SceneObjectPart part in m_parts.Values) | 2143 | foreach (SceneObjectPart part in m_parts.Values) |
1994 | { | 2144 | { |
2145 | |||
1995 | if (part != RootPart) | 2146 | if (part != RootPart) |
1996 | part.AddFullUpdateToAvatar(presence); | 2147 | part.AddFullUpdateToAvatar(presence); |
2148 | |||
1997 | } | 2149 | } |
1998 | } | 2150 | } |
2151 | lockPartsForRead(false); | ||
1999 | } | 2152 | } |
2000 | 2153 | ||
2001 | public void ScheduleTerseUpdateToAvatar(ScenePresence presence) | 2154 | public void ScheduleTerseUpdateToAvatar(ScenePresence presence) |
2002 | { | 2155 | { |
2003 | lock (m_parts) | 2156 | lockPartsForRead(true); |
2004 | { | 2157 | { |
2005 | foreach (SceneObjectPart part in m_parts.Values) | 2158 | foreach (SceneObjectPart part in m_parts.Values) |
2006 | { | 2159 | { |
2160 | |||
2007 | part.AddTerseUpdateToAvatar(presence); | 2161 | part.AddTerseUpdateToAvatar(presence); |
2162 | |||
2008 | } | 2163 | } |
2009 | } | 2164 | } |
2165 | lockPartsForRead(false); | ||
2010 | } | 2166 | } |
2011 | 2167 | ||
2012 | /// <summary> | 2168 | /// <summary> |
@@ -2017,14 +2173,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
2017 | checkAtTargets(); | 2173 | checkAtTargets(); |
2018 | RootPart.ScheduleFullUpdate(); | 2174 | RootPart.ScheduleFullUpdate(); |
2019 | 2175 | ||
2020 | lock (m_parts) | 2176 | lockPartsForRead(true); |
2021 | { | 2177 | { |
2022 | foreach (SceneObjectPart part in m_parts.Values) | 2178 | foreach (SceneObjectPart part in m_parts.Values) |
2023 | { | 2179 | { |
2180 | |||
2024 | if (part != RootPart) | 2181 | if (part != RootPart) |
2025 | part.ScheduleFullUpdate(); | 2182 | part.ScheduleFullUpdate(); |
2183 | |||
2026 | } | 2184 | } |
2027 | } | 2185 | } |
2186 | lockPartsForRead(false); | ||
2028 | } | 2187 | } |
2029 | 2188 | ||
2030 | /// <summary> | 2189 | /// <summary> |
@@ -2032,13 +2191,16 @@ namespace OpenSim.Region.Framework.Scenes | |||
2032 | /// </summary> | 2191 | /// </summary> |
2033 | public void ScheduleGroupForTerseUpdate() | 2192 | public void ScheduleGroupForTerseUpdate() |
2034 | { | 2193 | { |
2035 | lock (m_parts) | 2194 | lockPartsForRead(true); |
2036 | { | 2195 | { |
2037 | foreach (SceneObjectPart part in m_parts.Values) | 2196 | foreach (SceneObjectPart part in m_parts.Values) |
2038 | { | 2197 | { |
2198 | |||
2039 | part.ScheduleTerseUpdate(); | 2199 | part.ScheduleTerseUpdate(); |
2200 | |||
2040 | } | 2201 | } |
2041 | } | 2202 | } |
2203 | lockPartsForRead(false); | ||
2042 | } | 2204 | } |
2043 | 2205 | ||
2044 | /// <summary> | 2206 | /// <summary> |
@@ -2051,14 +2213,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
2051 | 2213 | ||
2052 | RootPart.SendFullUpdateToAllClients(); | 2214 | RootPart.SendFullUpdateToAllClients(); |
2053 | 2215 | ||
2054 | lock (m_parts) | 2216 | lockPartsForRead(true); |
2055 | { | 2217 | { |
2056 | foreach (SceneObjectPart part in m_parts.Values) | 2218 | foreach (SceneObjectPart part in m_parts.Values) |
2057 | { | 2219 | { |
2220 | |||
2058 | if (part != RootPart) | 2221 | if (part != RootPart) |
2059 | part.SendFullUpdateToAllClients(); | 2222 | part.SendFullUpdateToAllClients(); |
2223 | |||
2060 | } | 2224 | } |
2061 | } | 2225 | } |
2226 | lockPartsForRead(false); | ||
2062 | } | 2227 | } |
2063 | 2228 | ||
2064 | /// <summary> | 2229 | /// <summary> |
@@ -2089,14 +2254,15 @@ namespace OpenSim.Region.Framework.Scenes | |||
2089 | { | 2254 | { |
2090 | if (IsDeleted) | 2255 | if (IsDeleted) |
2091 | return; | 2256 | return; |
2092 | 2257 | ||
2093 | lock (m_parts) | 2258 | lockPartsForRead(true); |
2094 | { | 2259 | { |
2095 | foreach (SceneObjectPart part in m_parts.Values) | 2260 | foreach (SceneObjectPart part in m_parts.Values) |
2096 | { | 2261 | { |
2097 | part.SendTerseUpdateToAllClients(); | 2262 | part.SendTerseUpdateToAllClients(); |
2098 | } | 2263 | } |
2099 | } | 2264 | } |
2265 | lockPartsForRead(false); | ||
2100 | } | 2266 | } |
2101 | 2267 | ||
2102 | #endregion | 2268 | #endregion |
@@ -2110,16 +2276,18 @@ namespace OpenSim.Region.Framework.Scenes | |||
2110 | /// <returns>null if no child part with that linknum or child part</returns> | 2276 | /// <returns>null if no child part with that linknum or child part</returns> |
2111 | public SceneObjectPart GetLinkNumPart(int linknum) | 2277 | public SceneObjectPart GetLinkNumPart(int linknum) |
2112 | { | 2278 | { |
2113 | lock (m_parts) | 2279 | lockPartsForRead(true); |
2114 | { | 2280 | { |
2115 | foreach (SceneObjectPart part in m_parts.Values) | 2281 | foreach (SceneObjectPart part in m_parts.Values) |
2116 | { | 2282 | { |
2117 | if (part.LinkNum == linknum) | 2283 | if (part.LinkNum == linknum) |
2118 | { | 2284 | { |
2285 | lockPartsForRead(false); | ||
2119 | return part; | 2286 | return part; |
2120 | } | 2287 | } |
2121 | } | 2288 | } |
2122 | } | 2289 | } |
2290 | lockPartsForRead(false); | ||
2123 | 2291 | ||
2124 | return null; | 2292 | return null; |
2125 | } | 2293 | } |
@@ -2147,17 +2315,19 @@ namespace OpenSim.Region.Framework.Scenes | |||
2147 | public SceneObjectPart GetChildPart(uint localID) | 2315 | public SceneObjectPart GetChildPart(uint localID) |
2148 | { | 2316 | { |
2149 | //m_log.DebugFormat("Entered looking for {0}", localID); | 2317 | //m_log.DebugFormat("Entered looking for {0}", localID); |
2150 | lock (m_parts) | 2318 | lockPartsForRead(true); |
2151 | { | 2319 | { |
2152 | foreach (SceneObjectPart part in m_parts.Values) | 2320 | foreach (SceneObjectPart part in m_parts.Values) |
2153 | { | 2321 | { |
2154 | //m_log.DebugFormat("Found {0}", part.LocalId); | 2322 | //m_log.DebugFormat("Found {0}", part.LocalId); |
2155 | if (part.LocalId == localID) | 2323 | if (part.LocalId == localID) |
2156 | { | 2324 | { |
2325 | lockPartsForRead(false); | ||
2157 | return part; | 2326 | return part; |
2158 | } | 2327 | } |
2159 | } | 2328 | } |
2160 | } | 2329 | } |
2330 | lockPartsForRead(false); | ||
2161 | 2331 | ||
2162 | return null; | 2332 | return null; |
2163 | } | 2333 | } |
@@ -2187,17 +2357,19 @@ namespace OpenSim.Region.Framework.Scenes | |||
2187 | public bool HasChildPrim(uint localID) | 2357 | public bool HasChildPrim(uint localID) |
2188 | { | 2358 | { |
2189 | //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID); | 2359 | //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID); |
2190 | lock (m_parts) | 2360 | lockPartsForRead(true); |
2191 | { | 2361 | { |
2192 | foreach (SceneObjectPart part in m_parts.Values) | 2362 | foreach (SceneObjectPart part in m_parts.Values) |
2193 | { | 2363 | { |
2194 | //m_log.DebugFormat("Found {0}", part.LocalId); | 2364 | //m_log.DebugFormat("Found {0}", part.LocalId); |
2195 | if (part.LocalId == localID) | 2365 | if (part.LocalId == localID) |
2196 | { | 2366 | { |
2367 | lockPartsForRead(false); | ||
2197 | return true; | 2368 | return true; |
2198 | } | 2369 | } |
2199 | } | 2370 | } |
2200 | } | 2371 | } |
2372 | lockPartsForRead(false); | ||
2201 | 2373 | ||
2202 | return false; | 2374 | return false; |
2203 | } | 2375 | } |
@@ -2247,53 +2419,57 @@ namespace OpenSim.Region.Framework.Scenes | |||
2247 | if (m_rootPart.LinkNum == 0) | 2419 | if (m_rootPart.LinkNum == 0) |
2248 | m_rootPart.LinkNum = 1; | 2420 | m_rootPart.LinkNum = 1; |
2249 | 2421 | ||
2250 | lock (m_parts) | 2422 | lockPartsForWrite(true); |
2251 | { | 2423 | |
2252 | m_parts.Add(linkPart.UUID, linkPart); | 2424 | m_parts.Add(linkPart.UUID, linkPart); |
2425 | |||
2426 | lockPartsForWrite(false); | ||
2253 | 2427 | ||
2254 | // Insert in terms of link numbers, the new links | 2428 | // Insert in terms of link numbers, the new links |
2255 | // before the current ones (with the exception of | 2429 | // before the current ones (with the exception of |
2256 | // the root prim. Shuffle the old ones up | 2430 | // the root prim. Shuffle the old ones up |
2257 | foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts) | 2431 | lockPartsForRead(true); |
2432 | foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts) | ||
2433 | { | ||
2434 | if (kvp.Value.LinkNum != 1) | ||
2258 | { | 2435 | { |
2259 | if (kvp.Value.LinkNum != 1) | 2436 | // Don't update root prim link number |
2260 | { | 2437 | kvp.Value.LinkNum += objectGroup.PrimCount; |
2261 | // Don't update root prim link number | ||
2262 | kvp.Value.LinkNum += objectGroup.PrimCount; | ||
2263 | } | ||
2264 | } | 2438 | } |
2439 | } | ||
2440 | lockPartsForRead(false); | ||
2265 | 2441 | ||
2266 | linkPart.LinkNum = 2; | 2442 | linkPart.LinkNum = 2; |
2267 | 2443 | ||
2268 | linkPart.SetParent(this); | 2444 | linkPart.SetParent(this); |
2269 | linkPart.AddFlag(PrimFlags.CreateSelected); | 2445 | linkPart.AddFlag(PrimFlags.CreateSelected); |
2270 | 2446 | ||
2271 | //if (linkPart.PhysActor != null) | 2447 | //if (linkPart.PhysActor != null) |
2272 | //{ | 2448 | //{ |
2273 | // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); | 2449 | // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); |
2274 | 2450 | ||
2275 | //linkPart.PhysActor = null; | 2451 | //linkPart.PhysActor = null; |
2276 | //} | 2452 | //} |
2277 | 2453 | ||
2278 | //TODO: rest of parts | 2454 | //TODO: rest of parts |
2279 | int linkNum = 3; | 2455 | int linkNum = 3; |
2280 | foreach (SceneObjectPart part in objectGroup.Children.Values) | 2456 | foreach (SceneObjectPart part in objectGroup.Children.Values) |
2457 | { | ||
2458 | if (part.UUID != objectGroup.m_rootPart.UUID) | ||
2281 | { | 2459 | { |
2282 | if (part.UUID != objectGroup.m_rootPart.UUID) | 2460 | LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++); |
2283 | { | ||
2284 | LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++); | ||
2285 | } | ||
2286 | part.ClearUndoState(); | ||
2287 | } | 2461 | } |
2462 | part.ClearUndoState(); | ||
2288 | } | 2463 | } |
2289 | 2464 | ||
2290 | m_scene.UnlinkSceneObject(objectGroup.UUID, true); | 2465 | m_scene.UnlinkSceneObject(objectGroup.UUID, true); |
2291 | objectGroup.m_isDeleted = true; | 2466 | objectGroup.m_isDeleted = true; |
2467 | |||
2468 | objectGroup.lockPartsForWrite(true); | ||
2292 | 2469 | ||
2293 | lock (objectGroup.m_parts) | 2470 | objectGroup.m_parts.Clear(); |
2294 | { | 2471 | |
2295 | objectGroup.m_parts.Clear(); | 2472 | objectGroup.lockPartsForWrite(false); |
2296 | } | ||
2297 | 2473 | ||
2298 | // Can't do this yet since backup still makes use of the root part without any synchronization | 2474 | // Can't do this yet since backup still makes use of the root part without any synchronization |
2299 | // objectGroup.m_rootPart = null; | 2475 | // objectGroup.m_rootPart = null; |
@@ -2363,11 +2539,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
2363 | Quaternion worldRot = linkPart.GetWorldRotation(); | 2539 | Quaternion worldRot = linkPart.GetWorldRotation(); |
2364 | 2540 | ||
2365 | // Remove the part from this object | 2541 | // Remove the part from this object |
2366 | lock (m_parts) | 2542 | lockPartsForWrite(true); |
2367 | { | 2543 | { |
2368 | m_parts.Remove(linkPart.UUID); | 2544 | m_parts.Remove(linkPart.UUID); |
2369 | } | 2545 | } |
2370 | 2546 | lockPartsForWrite(false); | |
2547 | lockPartsForRead(true); | ||
2371 | if (m_parts.Count == 1 && RootPart != null) //Single prim is left | 2548 | if (m_parts.Count == 1 && RootPart != null) //Single prim is left |
2372 | RootPart.LinkNum = 0; | 2549 | RootPart.LinkNum = 0; |
2373 | else | 2550 | else |
@@ -2378,6 +2555,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2378 | p.LinkNum--; | 2555 | p.LinkNum--; |
2379 | } | 2556 | } |
2380 | } | 2557 | } |
2558 | lockPartsForRead(false); | ||
2381 | 2559 | ||
2382 | linkPart.ParentID = 0; | 2560 | linkPart.ParentID = 0; |
2383 | linkPart.LinkNum = 0; | 2561 | linkPart.LinkNum = 0; |
@@ -2699,9 +2877,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
2699 | 2877 | ||
2700 | if (selectionPart != null) | 2878 | if (selectionPart != null) |
2701 | { | 2879 | { |
2702 | lock (m_parts) | 2880 | lockPartsForRead(true); |
2881 | List<SceneObjectPart> parts = new List<SceneObjectPart>(m_parts.Values); | ||
2882 | lockPartsForRead(false); | ||
2883 | foreach (SceneObjectPart part in parts) | ||
2703 | { | 2884 | { |
2704 | foreach (SceneObjectPart part in m_parts.Values) | 2885 | if (part.Scale.X > 10.0 || part.Scale.Y > 10.0 || part.Scale.Z > 10.0) |
2705 | { | 2886 | { |
2706 | if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax || | 2887 | if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax || |
2707 | part.Scale.Y > m_scene.RegionInfo.PhysPrimMax || | 2888 | part.Scale.Y > m_scene.RegionInfo.PhysPrimMax || |
@@ -2711,12 +2892,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
2711 | break; | 2892 | break; |
2712 | } | 2893 | } |
2713 | } | 2894 | } |
2895 | } | ||
2714 | 2896 | ||
2715 | foreach (SceneObjectPart part in m_parts.Values) | 2897 | foreach (SceneObjectPart part in parts) |
2716 | { | 2898 | { |
2717 | part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect); | 2899 | part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect); |
2718 | } | ||
2719 | } | 2900 | } |
2901 | |||
2720 | } | 2902 | } |
2721 | } | 2903 | } |
2722 | 2904 | ||
@@ -2802,11 +2984,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
2802 | scale.Y = m_scene.m_maxNonphys; | 2984 | scale.Y = m_scene.m_maxNonphys; |
2803 | if (scale.Z > m_scene.m_maxNonphys) | 2985 | if (scale.Z > m_scene.m_maxNonphys) |
2804 | scale.Z = m_scene.m_maxNonphys; | 2986 | scale.Z = m_scene.m_maxNonphys; |
2805 | |||
2806 | SceneObjectPart part = GetChildPart(localID); | 2987 | SceneObjectPart part = GetChildPart(localID); |
2807 | if (part != null) | 2988 | if (part != null) |
2808 | { | 2989 | { |
2809 | part.Resize(scale); | ||
2810 | if (part.PhysActor != null) | 2990 | if (part.PhysActor != null) |
2811 | { | 2991 | { |
2812 | if (part.PhysActor.IsPhysical) | 2992 | if (part.PhysActor.IsPhysical) |
@@ -2821,7 +3001,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2821 | part.PhysActor.Size = scale; | 3001 | part.PhysActor.Size = scale; |
2822 | m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); | 3002 | m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); |
2823 | } | 3003 | } |
2824 | //if (part.UUID != m_rootPart.UUID) | 3004 | part.Resize(scale); |
2825 | 3005 | ||
2826 | HasGroupChanged = true; | 3006 | HasGroupChanged = true; |
2827 | ScheduleGroupForFullUpdate(); | 3007 | ScheduleGroupForFullUpdate(); |
@@ -2863,73 +3043,71 @@ namespace OpenSim.Region.Framework.Scenes | |||
2863 | float y = (scale.Y / part.Scale.Y); | 3043 | float y = (scale.Y / part.Scale.Y); |
2864 | float z = (scale.Z / part.Scale.Z); | 3044 | float z = (scale.Z / part.Scale.Z); |
2865 | 3045 | ||
2866 | lock (m_parts) | 3046 | lockPartsForRead(true); |
3047 | if (x > 1.0f || y > 1.0f || z > 1.0f) | ||
2867 | { | 3048 | { |
2868 | if (x > 1.0f || y > 1.0f || z > 1.0f) | 3049 | foreach (SceneObjectPart obPart in m_parts.Values) |
2869 | { | 3050 | { |
2870 | foreach (SceneObjectPart obPart in m_parts.Values) | 3051 | if (obPart.UUID != m_rootPart.UUID) |
2871 | { | 3052 | { |
2872 | if (obPart.UUID != m_rootPart.UUID) | 3053 | obPart.IgnoreUndoUpdate = true; |
2873 | { | 3054 | Vector3 oldSize = new Vector3(obPart.Scale); |
2874 | obPart.IgnoreUndoUpdate = true; | ||
2875 | Vector3 oldSize = new Vector3(obPart.Scale); | ||
2876 | 3055 | ||
2877 | float f = 1.0f; | 3056 | float f = 1.0f; |
2878 | float a = 1.0f; | 3057 | float a = 1.0f; |
2879 | 3058 | ||
2880 | if (part.PhysActor != null && part.PhysActor.IsPhysical) | 3059 | if (part.PhysActor != null && part.PhysActor.IsPhysical) |
3060 | { | ||
3061 | if (oldSize.X*x > m_scene.m_maxPhys) | ||
2881 | { | 3062 | { |
2882 | if (oldSize.X*x > m_scene.m_maxPhys) | 3063 | f = m_scene.m_maxPhys / oldSize.X; |
2883 | { | 3064 | a = f / x; |
2884 | f = m_scene.m_maxPhys / oldSize.X; | 3065 | x *= a; |
2885 | a = f / x; | 3066 | y *= a; |
2886 | x *= a; | 3067 | z *= a; |
2887 | y *= a; | ||
2888 | z *= a; | ||
2889 | } | ||
2890 | if (oldSize.Y*y > m_scene.m_maxPhys) | ||
2891 | { | ||
2892 | f = m_scene.m_maxPhys / oldSize.Y; | ||
2893 | a = f / y; | ||
2894 | x *= a; | ||
2895 | y *= a; | ||
2896 | z *= a; | ||
2897 | } | ||
2898 | if (oldSize.Z*z > m_scene.m_maxPhys) | ||
2899 | { | ||
2900 | f = m_scene.m_maxPhys / oldSize.Z; | ||
2901 | a = f / z; | ||
2902 | x *= a; | ||
2903 | y *= a; | ||
2904 | z *= a; | ||
2905 | } | ||
2906 | } | 3068 | } |
2907 | else | 3069 | if (oldSize.Y*y > m_scene.m_maxPhys) |
3070 | { | ||
3071 | f = m_scene.m_maxPhys / oldSize.Y; | ||
3072 | a = f / y; | ||
3073 | x *= a; | ||
3074 | y *= a; | ||
3075 | z *= a; | ||
3076 | } | ||
3077 | if (oldSize.Z*z > m_scene.m_maxPhys) | ||
3078 | { | ||
3079 | f = m_scene.m_maxPhys / oldSize.Z; | ||
3080 | a = f / z; | ||
3081 | x *= a; | ||
3082 | y *= a; | ||
3083 | z *= a; | ||
3084 | } | ||
3085 | } | ||
3086 | else | ||
3087 | { | ||
3088 | if (oldSize.X*x > m_scene.m_maxNonphys) | ||
3089 | { | ||
3090 | f = m_scene.m_maxNonphys / oldSize.X; | ||
3091 | a = f / x; | ||
3092 | x *= a; | ||
3093 | y *= a; | ||
3094 | z *= a; | ||
3095 | } | ||
3096 | if (oldSize.Y*y > m_scene.m_maxNonphys) | ||
3097 | { | ||
3098 | f = m_scene.m_maxNonphys / oldSize.Y; | ||
3099 | a = f / y; | ||
3100 | x *= a; | ||
3101 | y *= a; | ||
3102 | z *= a; | ||
3103 | } | ||
3104 | if (oldSize.Z*z > m_scene.m_maxNonphys) | ||
2908 | { | 3105 | { |
2909 | if (oldSize.X*x > m_scene.m_maxNonphys) | 3106 | f = m_scene.m_maxNonphys / oldSize.Z; |
2910 | { | 3107 | a = f / z; |
2911 | f = m_scene.m_maxNonphys / oldSize.X; | 3108 | x *= a; |
2912 | a = f / x; | 3109 | y *= a; |
2913 | x *= a; | 3110 | z *= a; |
2914 | y *= a; | ||
2915 | z *= a; | ||
2916 | } | ||
2917 | if (oldSize.Y*y > m_scene.m_maxNonphys) | ||
2918 | { | ||
2919 | f = m_scene.m_maxNonphys / oldSize.Y; | ||
2920 | a = f / y; | ||
2921 | x *= a; | ||
2922 | y *= a; | ||
2923 | z *= a; | ||
2924 | } | ||
2925 | if (oldSize.Z*z > m_scene.m_maxNonphys) | ||
2926 | { | ||
2927 | f = m_scene.m_maxNonphys / oldSize.Z; | ||
2928 | a = f / z; | ||
2929 | x *= a; | ||
2930 | y *= a; | ||
2931 | z *= a; | ||
2932 | } | ||
2933 | } | 3111 | } |
2934 | obPart.IgnoreUndoUpdate = false; | 3112 | obPart.IgnoreUndoUpdate = false; |
2935 | obPart.StoreUndoState(); | 3113 | obPart.StoreUndoState(); |
@@ -2937,6 +3115,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2937 | } | 3115 | } |
2938 | } | 3116 | } |
2939 | } | 3117 | } |
3118 | lockPartsForRead(false); | ||
2940 | 3119 | ||
2941 | Vector3 prevScale = part.Scale; | 3120 | Vector3 prevScale = part.Scale; |
2942 | prevScale.X *= x; | 3121 | prevScale.X *= x; |
@@ -2944,7 +3123,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2944 | prevScale.Z *= z; | 3123 | prevScale.Z *= z; |
2945 | part.Resize(prevScale); | 3124 | part.Resize(prevScale); |
2946 | 3125 | ||
2947 | lock (m_parts) | 3126 | lockPartsForRead(true); |
2948 | { | 3127 | { |
2949 | foreach (SceneObjectPart obPart in m_parts.Values) | 3128 | foreach (SceneObjectPart obPart in m_parts.Values) |
2950 | { | 3129 | { |
@@ -2966,6 +3145,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2966 | obPart.StoreUndoState(); | 3145 | obPart.StoreUndoState(); |
2967 | } | 3146 | } |
2968 | } | 3147 | } |
3148 | lockPartsForRead(false); | ||
2969 | 3149 | ||
2970 | if (part.PhysActor != null) | 3150 | if (part.PhysActor != null) |
2971 | { | 3151 | { |
@@ -3068,7 +3248,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3068 | axDiff *= Quaternion.Inverse(partRotation); | 3248 | axDiff *= Quaternion.Inverse(partRotation); |
3069 | diff = axDiff; | 3249 | diff = axDiff; |
3070 | 3250 | ||
3071 | lock (m_parts) | 3251 | lockPartsForRead(true); |
3072 | { | 3252 | { |
3073 | foreach (SceneObjectPart obPart in m_parts.Values) | 3253 | foreach (SceneObjectPart obPart in m_parts.Values) |
3074 | { | 3254 | { |
@@ -3078,6 +3258,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3078 | } | 3258 | } |
3079 | } | 3259 | } |
3080 | } | 3260 | } |
3261 | lockPartsForRead(false); | ||
3081 | 3262 | ||
3082 | AbsolutePosition = newPos; | 3263 | AbsolutePosition = newPos; |
3083 | 3264 | ||
@@ -3211,25 +3392,25 @@ namespace OpenSim.Region.Framework.Scenes | |||
3211 | m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); | 3392 | m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); |
3212 | } | 3393 | } |
3213 | 3394 | ||
3214 | lock (m_parts) | 3395 | lockPartsForRead(true); |
3396 | |||
3397 | foreach (SceneObjectPart prim in m_parts.Values) | ||
3215 | { | 3398 | { |
3216 | foreach (SceneObjectPart prim in m_parts.Values) | 3399 | if (prim.UUID != m_rootPart.UUID) |
3217 | { | 3400 | { |
3218 | if (prim.UUID != m_rootPart.UUID) | 3401 | prim.IgnoreUndoUpdate = true; |
3219 | { | 3402 | Vector3 axPos = prim.OffsetPosition; |
3220 | prim.IgnoreUndoUpdate = true; | 3403 | axPos *= oldParentRot; |
3221 | Vector3 axPos = prim.OffsetPosition; | 3404 | axPos *= Quaternion.Inverse(axRot); |
3222 | axPos *= oldParentRot; | 3405 | prim.OffsetPosition = axPos; |
3223 | axPos *= Quaternion.Inverse(axRot); | 3406 | Quaternion primsRot = prim.RotationOffset; |
3224 | prim.OffsetPosition = axPos; | 3407 | Quaternion newRot = primsRot * oldParentRot; |
3225 | Quaternion primsRot = prim.RotationOffset; | 3408 | newRot *= Quaternion.Inverse(axRot); |
3226 | Quaternion newRot = primsRot * oldParentRot; | 3409 | prim.RotationOffset = newRot; |
3227 | newRot *= Quaternion.Inverse(axRot); | 3410 | prim.ScheduleTerseUpdate(); |
3228 | prim.RotationOffset = newRot; | ||
3229 | prim.ScheduleTerseUpdate(); | ||
3230 | } | ||
3231 | } | 3411 | } |
3232 | } | 3412 | } |
3413 | |||
3233 | foreach (SceneObjectPart childpart in Children.Values) | 3414 | foreach (SceneObjectPart childpart in Children.Values) |
3234 | { | 3415 | { |
3235 | if (childpart != m_rootPart) | 3416 | if (childpart != m_rootPart) |
@@ -3238,6 +3419,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
3238 | childpart.StoreUndoState(); | 3419 | childpart.StoreUndoState(); |
3239 | } | 3420 | } |
3240 | } | 3421 | } |
3422 | |||
3423 | lockPartsForRead(false); | ||
3424 | |||
3241 | m_rootPart.ScheduleTerseUpdate(); | 3425 | m_rootPart.ScheduleTerseUpdate(); |
3242 | } | 3426 | } |
3243 | 3427 | ||
@@ -3359,7 +3543,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3359 | if (atTargets.Count > 0) | 3543 | if (atTargets.Count > 0) |
3360 | { | 3544 | { |
3361 | uint[] localids = new uint[0]; | 3545 | uint[] localids = new uint[0]; |
3362 | lock (m_parts) | 3546 | lockPartsForRead(true); |
3363 | { | 3547 | { |
3364 | localids = new uint[m_parts.Count]; | 3548 | localids = new uint[m_parts.Count]; |
3365 | int cntr = 0; | 3549 | int cntr = 0; |
@@ -3369,6 +3553,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3369 | cntr++; | 3553 | cntr++; |
3370 | } | 3554 | } |
3371 | } | 3555 | } |
3556 | lockPartsForRead(false); | ||
3372 | 3557 | ||
3373 | for (int ctr = 0; ctr < localids.Length; ctr++) | 3558 | for (int ctr = 0; ctr < localids.Length; ctr++) |
3374 | { | 3559 | { |
@@ -3387,7 +3572,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3387 | { | 3572 | { |
3388 | //trigger not_at_target | 3573 | //trigger not_at_target |
3389 | uint[] localids = new uint[0]; | 3574 | uint[] localids = new uint[0]; |
3390 | lock (m_parts) | 3575 | lockPartsForRead(true); |
3391 | { | 3576 | { |
3392 | localids = new uint[m_parts.Count]; | 3577 | localids = new uint[m_parts.Count]; |
3393 | int cntr = 0; | 3578 | int cntr = 0; |
@@ -3397,7 +3582,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
3397 | cntr++; | 3582 | cntr++; |
3398 | } | 3583 | } |
3399 | } | 3584 | } |
3400 | 3585 | lockPartsForRead(false); | |
3586 | |||
3401 | for (int ctr = 0; ctr < localids.Length; ctr++) | 3587 | for (int ctr = 0; ctr < localids.Length; ctr++) |
3402 | { | 3588 | { |
3403 | m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]); | 3589 | m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]); |
@@ -3489,19 +3675,20 @@ namespace OpenSim.Region.Framework.Scenes | |||
3489 | public float GetMass() | 3675 | public float GetMass() |
3490 | { | 3676 | { |
3491 | float retmass = 0f; | 3677 | float retmass = 0f; |
3492 | lock (m_parts) | 3678 | lockPartsForRead(true); |
3493 | { | 3679 | { |
3494 | foreach (SceneObjectPart part in m_parts.Values) | 3680 | foreach (SceneObjectPart part in m_parts.Values) |
3495 | { | 3681 | { |
3496 | retmass += part.GetMass(); | 3682 | retmass += part.GetMass(); |
3497 | } | 3683 | } |
3498 | } | 3684 | } |
3685 | lockPartsForRead(false); | ||
3499 | return retmass; | 3686 | return retmass; |
3500 | } | 3687 | } |
3501 | 3688 | ||
3502 | public void CheckSculptAndLoad() | 3689 | public void CheckSculptAndLoad() |
3503 | { | 3690 | { |
3504 | lock (m_parts) | 3691 | lockPartsForRead(true); |
3505 | { | 3692 | { |
3506 | if (!IsDeleted) | 3693 | if (!IsDeleted) |
3507 | { | 3694 | { |
@@ -3526,6 +3713,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3526 | } | 3713 | } |
3527 | } | 3714 | } |
3528 | } | 3715 | } |
3716 | lockPartsForRead(false); | ||
3529 | } | 3717 | } |
3530 | 3718 | ||
3531 | protected void AssetReceived(string id, Object sender, AssetBase asset) | 3719 | protected void AssetReceived(string id, Object sender, AssetBase asset) |
@@ -3546,7 +3734,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3546 | /// <param name="client"></param> | 3734 | /// <param name="client"></param> |
3547 | public void SetGroup(UUID GroupID, IClientAPI client) | 3735 | public void SetGroup(UUID GroupID, IClientAPI client) |
3548 | { | 3736 | { |
3549 | lock (m_parts) | 3737 | lockPartsForRead(true); |
3550 | { | 3738 | { |
3551 | foreach (SceneObjectPart part in m_parts.Values) | 3739 | foreach (SceneObjectPart part in m_parts.Values) |
3552 | { | 3740 | { |
@@ -3556,7 +3744,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3556 | 3744 | ||
3557 | HasGroupChanged = true; | 3745 | HasGroupChanged = true; |
3558 | } | 3746 | } |
3559 | 3747 | lockPartsForRead(false); | |
3560 | ScheduleGroupForFullUpdate(); | 3748 | ScheduleGroupForFullUpdate(); |
3561 | } | 3749 | } |
3562 | 3750 | ||
@@ -3575,11 +3763,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
3575 | 3763 | ||
3576 | public void SetAttachmentPoint(byte point) | 3764 | public void SetAttachmentPoint(byte point) |
3577 | { | 3765 | { |
3578 | lock (m_parts) | 3766 | lockPartsForRead(true); |
3579 | { | 3767 | { |
3580 | foreach (SceneObjectPart part in m_parts.Values) | 3768 | foreach (SceneObjectPart part in m_parts.Values) |
3581 | part.SetAttachmentPoint(point); | 3769 | part.SetAttachmentPoint(point); |
3582 | } | 3770 | } |
3771 | lockPartsForRead(false); | ||
3583 | } | 3772 | } |
3584 | 3773 | ||
3585 | #region ISceneObject | 3774 | #region ISceneObject |