aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs')
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs585
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