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.cs601
1 files changed, 392 insertions, 209 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 8aefd50..3895d93 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)
@@ -305,17 +377,18 @@ namespace OpenSim.Region.Framework.Scenes
305 RootPart.ScriptSetPhysicsStatus(false); 377 RootPart.ScriptSetPhysicsStatus(false);
306 Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"), 378 Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"),
307 ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false); 379 ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false);
380 lockPartsForRead(false);
308 return; 381 return;
309 } 382 }
310 } 383 }
311 lock (m_parts) 384
385 foreach (SceneObjectPart part in m_parts.Values)
312 { 386 {
313 foreach (SceneObjectPart part in m_parts.Values) 387 part.GroupPosition = val;
314 {
315 part.GroupPosition = val;
316 }
317 } 388 }
318 389
390 lockPartsForRead(false);
391
319 //if (m_rootPart.PhysActor != null) 392 //if (m_rootPart.PhysActor != null)
320 //{ 393 //{
321 //m_rootPart.PhysActor.Position = 394 //m_rootPart.PhysActor.Position =
@@ -504,13 +577,16 @@ namespace OpenSim.Region.Framework.Scenes
504 577
505 public void SetFromItemID(UUID AssetId) 578 public void SetFromItemID(UUID AssetId)
506 { 579 {
507 lock (m_parts) 580 lockPartsForRead(true);
508 { 581 {
509 foreach (SceneObjectPart part in m_parts.Values) 582 foreach (SceneObjectPart part in m_parts.Values)
510 { 583 {
584
511 part.FromItemID = AssetId; 585 part.FromItemID = AssetId;
586
512 } 587 }
513 } 588 }
589 lockPartsForRead(false);
514 } 590 }
515 591
516 public UUID GetFromItemID() 592 public UUID GetFromItemID()
@@ -579,10 +655,11 @@ namespace OpenSim.Region.Framework.Scenes
579 Vector3 maxScale = Vector3.Zero; 655 Vector3 maxScale = Vector3.Zero;
580 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f); 656 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f);
581 657
582 lock (m_parts) 658 lockPartsForRead(true);
583 { 659 {
584 foreach (SceneObjectPart part in m_parts.Values) 660 foreach (SceneObjectPart part in m_parts.Values)
585 { 661 {
662
586 Vector3 partscale = part.Scale; 663 Vector3 partscale = part.Scale;
587 Vector3 partoffset = part.OffsetPosition; 664 Vector3 partoffset = part.OffsetPosition;
588 665
@@ -593,8 +670,11 @@ namespace OpenSim.Region.Framework.Scenes
593 maxScale.X = (partscale.X + partoffset.X > maxScale.X) ? partscale.X + partoffset.X : maxScale.X; 670 maxScale.X = (partscale.X + partoffset.X > maxScale.X) ? partscale.X + partoffset.X : maxScale.X;
594 maxScale.Y = (partscale.Y + partoffset.Y > maxScale.Y) ? partscale.Y + partoffset.Y : maxScale.Y; 671 maxScale.Y = (partscale.Y + partoffset.Y > maxScale.Y) ? partscale.Y + partoffset.Y : maxScale.Y;
595 maxScale.Z = (partscale.Z + partoffset.Z > maxScale.Z) ? partscale.Z + partoffset.Z : maxScale.Z; 672 maxScale.Z = (partscale.Z + partoffset.Z > maxScale.Z) ? partscale.Z + partoffset.Z : maxScale.Z;
673
596 } 674 }
597 } 675 }
676 lockPartsForRead(false);
677
598 finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X; 678 finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X;
599 finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y; 679 finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y;
600 finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z; 680 finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z;
@@ -610,10 +690,11 @@ namespace OpenSim.Region.Framework.Scenes
610 690
611 EntityIntersection result = new EntityIntersection(); 691 EntityIntersection result = new EntityIntersection();
612 692
613 lock (m_parts) 693 lockPartsForRead(true);
614 { 694 {
615 foreach (SceneObjectPart part in m_parts.Values) 695 foreach (SceneObjectPart part in m_parts.Values)
616 { 696 {
697
617 // Temporary commented to stop compiler warning 698 // Temporary commented to stop compiler warning
618 //Vector3 partPosition = 699 //Vector3 partPosition =
619 // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z); 700 // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z);
@@ -641,8 +722,10 @@ namespace OpenSim.Region.Framework.Scenes
641 result.distance = inter.distance; 722 result.distance = inter.distance;
642 } 723 }
643 } 724 }
725
644 } 726 }
645 } 727 }
728 lockPartsForRead(false);
646 return result; 729 return result;
647 } 730 }
648 731
@@ -655,10 +738,11 @@ namespace OpenSim.Region.Framework.Scenes
655 public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight) 738 public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight)
656 { 739 {
657 float maxX = -256f, maxY = -256f, maxZ = -256f, minX = 256f, minY = 256f, minZ = 256f; 740 float maxX = -256f, maxY = -256f, maxZ = -256f, minX = 256f, minY = 256f, minZ = 256f;
658 lock (m_parts) 741 lockPartsForRead(true);
659 { 742 {
660 foreach (SceneObjectPart part in m_parts.Values) 743 foreach (SceneObjectPart part in m_parts.Values)
661 { 744 {
745
662 Vector3 worldPos = part.GetWorldPosition(); 746 Vector3 worldPos = part.GetWorldPosition();
663 Vector3 offset = worldPos - AbsolutePosition; 747 Vector3 offset = worldPos - AbsolutePosition;
664 Quaternion worldRot; 748 Quaternion worldRot;
@@ -717,6 +801,8 @@ namespace OpenSim.Region.Framework.Scenes
717 backBottomRight.Y = orig.Y + (part.Scale.Y / 2); 801 backBottomRight.Y = orig.Y + (part.Scale.Y / 2);
718 backBottomRight.Z = orig.Z - (part.Scale.Z / 2); 802 backBottomRight.Z = orig.Z - (part.Scale.Z / 2);
719 803
804
805
720 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z); 806 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
721 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z); 807 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
722 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z); 808 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
@@ -888,6 +974,7 @@ namespace OpenSim.Region.Framework.Scenes
888 minZ = backBottomLeft.Z; 974 minZ = backBottomLeft.Z;
889 } 975 }
890 } 976 }
977 lockPartsForRead(false);
891 978
892 Vector3 boundingBox = new Vector3(maxX - minX, maxY - minY, maxZ - minZ); 979 Vector3 boundingBox = new Vector3(maxX - minX, maxY - minY, maxZ - minZ);
893 980
@@ -916,17 +1003,20 @@ namespace OpenSim.Region.Framework.Scenes
916 Dictionary<UUID,string> states = new Dictionary<UUID,string>(); 1003 Dictionary<UUID,string> states = new Dictionary<UUID,string>();
917 1004
918 // Capture script state while holding the lock 1005 // Capture script state while holding the lock
919 lock (m_parts) 1006 lockPartsForRead(true);
920 { 1007 {
921 foreach (SceneObjectPart part in m_parts.Values) 1008 foreach (SceneObjectPart part in m_parts.Values)
922 { 1009 {
1010
923 Dictionary<UUID,string> pstates = part.Inventory.GetScriptStates(); 1011 Dictionary<UUID,string> pstates = part.Inventory.GetScriptStates();
924 foreach (UUID itemid in pstates.Keys) 1012 foreach (UUID itemid in pstates.Keys)
925 { 1013 {
926 states.Add(itemid, pstates[itemid]); 1014 states.Add(itemid, pstates[itemid]);
927 } 1015 }
1016
928 } 1017 }
929 } 1018 }
1019 lockPartsForRead(false);
930 1020
931 if (states.Count > 0) 1021 if (states.Count > 0)
932 { 1022 {
@@ -1094,13 +1184,16 @@ namespace OpenSim.Region.Framework.Scenes
1094 1184
1095 public override void UpdateMovement() 1185 public override void UpdateMovement()
1096 { 1186 {
1097 lock (m_parts) 1187 lockPartsForRead(true);
1098 { 1188 {
1099 foreach (SceneObjectPart part in m_parts.Values) 1189 foreach (SceneObjectPart part in m_parts.Values)
1100 { 1190 {
1191
1101 part.UpdateMovement(); 1192 part.UpdateMovement();
1193
1102 } 1194 }
1103 } 1195 }
1196 lockPartsForRead(false);
1104 } 1197 }
1105 1198
1106 public ushort GetTimeDilation() 1199 public ushort GetTimeDilation()
@@ -1144,7 +1237,7 @@ namespace OpenSim.Region.Framework.Scenes
1144 /// <param name="part"></param> 1237 /// <param name="part"></param>
1145 public void AddPart(SceneObjectPart part) 1238 public void AddPart(SceneObjectPart part)
1146 { 1239 {
1147 lock (m_parts) 1240 lockPartsForWrite(true);
1148 { 1241 {
1149 part.SetParent(this); 1242 part.SetParent(this);
1150 m_parts.Add(part.UUID, part); 1243 m_parts.Add(part.UUID, part);
@@ -1154,6 +1247,7 @@ namespace OpenSim.Region.Framework.Scenes
1154 if (part.LinkNum == 2 && RootPart != null) 1247 if (part.LinkNum == 2 && RootPart != null)
1155 RootPart.LinkNum = 1; 1248 RootPart.LinkNum = 1;
1156 } 1249 }
1250 lockPartsForWrite(false);
1157 } 1251 }
1158 1252
1159 /// <summary> 1253 /// <summary>
@@ -1161,28 +1255,33 @@ namespace OpenSim.Region.Framework.Scenes
1161 /// </summary> 1255 /// </summary>
1162 private void UpdateParentIDs() 1256 private void UpdateParentIDs()
1163 { 1257 {
1164 lock (m_parts) 1258 lockPartsForRead(true);
1165 { 1259 {
1166 foreach (SceneObjectPart part in m_parts.Values) 1260 foreach (SceneObjectPart part in m_parts.Values)
1167 { 1261 {
1262
1168 if (part.UUID != m_rootPart.UUID) 1263 if (part.UUID != m_rootPart.UUID)
1169 { 1264 {
1170 part.ParentID = m_rootPart.LocalId; 1265 part.ParentID = m_rootPart.LocalId;
1171 } 1266 }
1267
1172 } 1268 }
1173 } 1269 }
1270 lockPartsForRead(false);
1174 } 1271 }
1175 1272
1176 public void RegenerateFullIDs() 1273 public void RegenerateFullIDs()
1177 { 1274 {
1178 lock (m_parts) 1275 lockPartsForRead(true);
1179 { 1276 {
1180 foreach (SceneObjectPart part in m_parts.Values) 1277 foreach (SceneObjectPart part in m_parts.Values)
1181 { 1278 {
1279
1182 part.UUID = UUID.Random(); 1280 part.UUID = UUID.Random();
1183 1281
1184 } 1282 }
1185 } 1283 }
1284 lockPartsForRead(false);
1186 } 1285 }
1187 1286
1188 // helper provided for parts. 1287 // helper provided for parts.
@@ -1263,27 +1362,33 @@ namespace OpenSim.Region.Framework.Scenes
1263 1362
1264 DetachFromBackup(); 1363 DetachFromBackup();
1265 1364
1266 lock (m_parts) 1365 lockPartsForRead(true);
1366 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1367 lockPartsForRead(false);
1368
1369 foreach (SceneObjectPart part in values)
1267 { 1370 {
1268 foreach (SceneObjectPart part in m_parts.Values)
1269 {
1270// part.Inventory.RemoveScriptInstances(); 1371// part.Inventory.RemoveScriptInstances();
1271 Scene.ForEachScenePresence(delegate(ScenePresence avatar) 1372
1373 List<ScenePresence> avatars = Scene.GetScenePresences();
1374 for (int i = 0; i < avatars.Count; i++)
1375 {
1376 if (avatars[i].ParentID == LocalId)
1272 { 1377 {
1273 if (avatar.ParentID == LocalId) 1378 avatars[i].StandUp();
1274 { 1379 }
1275 avatar.StandUp();
1276 }
1277 1380
1278 if (!silent) 1381 if (!silent)
1279 { 1382 {
1280 part.UpdateFlag = 0; 1383 part.UpdateFlag = 0;
1281 if (part == m_rootPart) 1384 if (part == m_rootPart)
1282 avatar.ControllingClient.SendKillObject(m_regionHandle, part.LocalId); 1385 avatars[i].ControllingClient.SendKillObject(m_regionHandle, part.LocalId);
1283 } 1386 }
1284 });
1285 } 1387 }
1388
1286 } 1389 }
1390
1391
1287 } 1392 }
1288 1393
1289 public void AddScriptLPS(int count) 1394 public void AddScriptLPS(int count)
@@ -1308,17 +1413,20 @@ namespace OpenSim.Region.Framework.Scenes
1308 1413
1309 scriptEvents aggregateScriptEvents=0; 1414 scriptEvents aggregateScriptEvents=0;
1310 1415
1311 lock (m_parts) 1416 lockPartsForRead(true);
1312 { 1417 {
1313 foreach (SceneObjectPart part in m_parts.Values) 1418 foreach (SceneObjectPart part in m_parts.Values)
1314 { 1419 {
1420
1315 if (part == null) 1421 if (part == null)
1316 continue; 1422 continue;
1317 if (part != RootPart) 1423 if (part != RootPart)
1318 part.ObjectFlags = objectflagupdate; 1424 part.ObjectFlags = objectflagupdate;
1319 aggregateScriptEvents |= part.AggregateScriptEvents; 1425 aggregateScriptEvents |= part.AggregateScriptEvents;
1426
1320 } 1427 }
1321 } 1428 }
1429 lockPartsForRead(false);
1322 1430
1323 m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0); 1431 m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0);
1324 m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0); 1432 m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0);
@@ -1360,42 +1468,52 @@ namespace OpenSim.Region.Framework.Scenes
1360 /// <param name="m_physicalPrim"></param> 1468 /// <param name="m_physicalPrim"></param>
1361 public void ApplyPhysics(bool m_physicalPrim) 1469 public void ApplyPhysics(bool m_physicalPrim)
1362 { 1470 {
1363 lock (m_parts) 1471 lockPartsForRead(true);
1472
1473 if (m_parts.Count > 1)
1364 { 1474 {
1365 if (m_parts.Count > 1) 1475 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1476 lockPartsForRead(false);
1477 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1478 foreach (SceneObjectPart part in values)
1366 { 1479 {
1367 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim); 1480
1368 foreach (SceneObjectPart part in m_parts.Values) 1481 if (part.LocalId != m_rootPart.LocalId)
1369 { 1482 {
1370 if (part.LocalId != m_rootPart.LocalId) 1483 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim);
1371 {
1372 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim);
1373 }
1374 } 1484 }
1375 1485
1376 // Hack to get the physics scene geometries in the right spot
1377 ResetChildPrimPhysicsPositions();
1378 }
1379 else
1380 {
1381 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1382 } 1486 }
1487 // Hack to get the physics scene geometries in the right spot
1488 ResetChildPrimPhysicsPositions();
1489 }
1490 else
1491 {
1492 lockPartsForRead(false);
1493 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1383 } 1494 }
1384 } 1495 }
1385 1496
1386 public void SetOwnerId(UUID userId) 1497 public void SetOwnerId(UUID userId)
1387 { 1498 {
1388 ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); 1499 ForEachPart(delegate(SceneObjectPart part)
1500 {
1501
1502 part.OwnerID = userId;
1503
1504 });
1389 } 1505 }
1390 1506
1391 public void ForEachPart(Action<SceneObjectPart> whatToDo) 1507 public void ForEachPart(Action<SceneObjectPart> whatToDo)
1392 { 1508 {
1393 lock (m_parts) 1509 lockPartsForRead(true);
1510 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1511 lockPartsForRead(false);
1512 foreach (SceneObjectPart part in values)
1394 { 1513 {
1395 foreach (SceneObjectPart part in m_parts.Values) 1514
1396 { 1515 whatToDo(part);
1397 whatToDo(part); 1516
1398 }
1399 } 1517 }
1400 } 1518 }
1401 1519
@@ -1493,10 +1611,11 @@ namespace OpenSim.Region.Framework.Scenes
1493 RootPart.SendFullUpdate( 1611 RootPart.SendFullUpdate(
1494 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID)); 1612 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID));
1495 1613
1496 lock (m_parts) 1614 lockPartsForRead(true);
1497 { 1615 {
1498 foreach (SceneObjectPart part in m_parts.Values) 1616 foreach (SceneObjectPart part in m_parts.Values)
1499 { 1617 {
1618
1500 if (part != RootPart) 1619 if (part != RootPart)
1501 part.SendFullUpdate( 1620 part.SendFullUpdate(
1502 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID)); 1621 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID));
@@ -1570,10 +1689,11 @@ namespace OpenSim.Region.Framework.Scenes
1570 1689
1571 List<SceneObjectPart> partList; 1690 List<SceneObjectPart> partList;
1572 1691
1573 lock (m_parts) 1692 lockPartsForRead(true);
1574 { 1693
1575 partList = new List<SceneObjectPart>(m_parts.Values); 1694 partList = new List<SceneObjectPart>(m_parts.Values);
1576 } 1695
1696 lockPartsForRead(false);
1577 1697
1578 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) 1698 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1579 { 1699 {
@@ -1796,13 +1916,40 @@ namespace OpenSim.Region.Framework.Scenes
1796 } 1916 }
1797 } 1917 }
1798 1918
1919 public void rotLookAt(Quaternion target, float strength, float damping)
1920 {
1921 SceneObjectPart rootpart = m_rootPart;
1922 if (rootpart != null)
1923 {
1924 if (IsAttachment)
1925 {
1926 /*
1927 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
1928 if (avatar != null)
1929 {
1930 Rotate the Av?
1931 } */
1932 }
1933 else
1934 {
1935 if (rootpart.PhysActor != null)
1936 { // APID must be implemented in your physics system for this to function.
1937 rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W);
1938 rootpart.PhysActor.APIDStrength = strength;
1939 rootpart.PhysActor.APIDDamping = damping;
1940 rootpart.PhysActor.APIDActive = true;
1941 }
1942 }
1943 }
1944 }
1945
1799 public void stopLookAt() 1946 public void stopLookAt()
1800 { 1947 {
1801 SceneObjectPart rootpart = m_rootPart; 1948 SceneObjectPart rootpart = m_rootPart;
1802 if (rootpart != null) 1949 if (rootpart != null)
1803 { 1950 {
1804 if (rootpart.PhysActor != null) 1951 if (rootpart.PhysActor != null)
1805 { 1952 { // APID must be implemented in your physics system for this to function.
1806 rootpart.PhysActor.APIDActive = false; 1953 rootpart.PhysActor.APIDActive = false;
1807 } 1954 }
1808 } 1955 }
@@ -1870,10 +2017,11 @@ namespace OpenSim.Region.Framework.Scenes
1870 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 2017 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
1871 newPart.SetParent(this); 2018 newPart.SetParent(this);
1872 2019
1873 lock (m_parts) 2020 lockPartsForWrite(true);
1874 { 2021 {
1875 m_parts.Add(newPart.UUID, newPart); 2022 m_parts.Add(newPart.UUID, newPart);
1876 } 2023 }
2024 lockPartsForWrite(false);
1877 2025
1878 SetPartAsNonRoot(newPart); 2026 SetPartAsNonRoot(newPart);
1879 2027
@@ -1936,7 +2084,7 @@ namespace OpenSim.Region.Framework.Scenes
1936 //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0) 2084 //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
1937 // return; 2085 // return;
1938 2086
1939 lock (m_parts) 2087 lockPartsForRead(true);
1940 { 2088 {
1941 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0); 2089 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0);
1942 2090
@@ -1956,9 +2104,12 @@ namespace OpenSim.Region.Framework.Scenes
1956 { 2104 {
1957 if (!IsSelected) 2105 if (!IsSelected)
1958 part.UpdateLookAt(); 2106 part.UpdateLookAt();
2107
1959 part.SendScheduledUpdates(); 2108 part.SendScheduledUpdates();
2109
1960 } 2110 }
1961 } 2111 }
2112 lockPartsForRead(false);
1962 } 2113 }
1963 2114
1964 public void ScheduleFullUpdateToAvatar(ScenePresence presence) 2115 public void ScheduleFullUpdateToAvatar(ScenePresence presence)
@@ -1967,27 +2118,29 @@ namespace OpenSim.Region.Framework.Scenes
1967 2118
1968 RootPart.AddFullUpdateToAvatar(presence); 2119 RootPart.AddFullUpdateToAvatar(presence);
1969 2120
1970 lock (m_parts) 2121 lockPartsForRead(true);
1971 { 2122 {
1972 foreach (SceneObjectPart part in m_parts.Values) 2123 foreach (SceneObjectPart part in m_parts.Values)
1973 { 2124 {
2125
1974 if (part != RootPart) 2126 if (part != RootPart)
1975 part.AddFullUpdateToAvatar(presence); 2127 part.AddFullUpdateToAvatar(presence);
2128
1976 } 2129 }
1977 } 2130 }
2131 lockPartsForRead(false);
1978 } 2132 }
1979 2133
1980 public void ScheduleTerseUpdateToAvatar(ScenePresence presence) 2134 public void ScheduleTerseUpdateToAvatar(ScenePresence presence)
1981 { 2135 {
1982// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1} just to avatar {2}", Name, UUID, presence.Name); 2136 lockPartsForRead(true);
1983 2137
1984 lock (m_parts) 2138 foreach (SceneObjectPart part in m_parts.Values)
1985 { 2139 {
1986 foreach (SceneObjectPart part in m_parts.Values) 2140 part.AddTerseUpdateToAvatar(presence);
1987 {
1988 part.AddTerseUpdateToAvatar(presence);
1989 }
1990 } 2141 }
2142
2143 lockPartsForRead(false);
1991 } 2144 }
1992 2145
1993 /// <summary> 2146 /// <summary>
@@ -2000,14 +2153,17 @@ namespace OpenSim.Region.Framework.Scenes
2000 checkAtTargets(); 2153 checkAtTargets();
2001 RootPart.ScheduleFullUpdate(); 2154 RootPart.ScheduleFullUpdate();
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 if (part != RootPart) 2161 if (part != RootPart)
2008 part.ScheduleFullUpdate(); 2162 part.ScheduleFullUpdate();
2163
2009 } 2164 }
2010 } 2165 }
2166 lockPartsForRead(false);
2011 } 2167 }
2012 2168
2013 /// <summary> 2169 /// <summary>
@@ -2015,15 +2171,14 @@ namespace OpenSim.Region.Framework.Scenes
2015 /// </summary> 2171 /// </summary>
2016 public void ScheduleGroupForTerseUpdate() 2172 public void ScheduleGroupForTerseUpdate()
2017 { 2173 {
2018// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1}", Name, UUID); 2174 lockPartsForRead(true);
2019 2175
2020 lock (m_parts) 2176 foreach (SceneObjectPart part in m_parts.Values)
2021 { 2177 {
2022 foreach (SceneObjectPart part in m_parts.Values) 2178 part.ScheduleTerseUpdate();
2023 {
2024 part.ScheduleTerseUpdate();
2025 }
2026 } 2179 }
2180
2181 lockPartsForRead(false);
2027 } 2182 }
2028 2183
2029 /// <summary> 2184 /// <summary>
@@ -2038,14 +2193,17 @@ namespace OpenSim.Region.Framework.Scenes
2038 2193
2039 RootPart.SendFullUpdateToAllClients(); 2194 RootPart.SendFullUpdateToAllClients();
2040 2195
2041 lock (m_parts) 2196 lockPartsForRead(true);
2042 { 2197 {
2043 foreach (SceneObjectPart part in m_parts.Values) 2198 foreach (SceneObjectPart part in m_parts.Values)
2044 { 2199 {
2200
2045 if (part != RootPart) 2201 if (part != RootPart)
2046 part.SendFullUpdateToAllClients(); 2202 part.SendFullUpdateToAllClients();
2203
2047 } 2204 }
2048 } 2205 }
2206 lockPartsForRead(false);
2049 } 2207 }
2050 2208
2051 /// <summary> 2209 /// <summary>
@@ -2077,14 +2235,15 @@ namespace OpenSim.Region.Framework.Scenes
2077 { 2235 {
2078 if (IsDeleted) 2236 if (IsDeleted)
2079 return; 2237 return;
2080 2238
2081 lock (m_parts) 2239 lockPartsForRead(true);
2082 { 2240 {
2083 foreach (SceneObjectPart part in m_parts.Values) 2241 foreach (SceneObjectPart part in m_parts.Values)
2084 { 2242 {
2085 part.SendTerseUpdateToAllClients(); 2243 part.SendTerseUpdateToAllClients();
2086 } 2244 }
2087 } 2245 }
2246 lockPartsForRead(false);
2088 } 2247 }
2089 2248
2090 #endregion 2249 #endregion
@@ -2098,16 +2257,18 @@ namespace OpenSim.Region.Framework.Scenes
2098 /// <returns>null if no child part with that linknum or child part</returns> 2257 /// <returns>null if no child part with that linknum or child part</returns>
2099 public SceneObjectPart GetLinkNumPart(int linknum) 2258 public SceneObjectPart GetLinkNumPart(int linknum)
2100 { 2259 {
2101 lock (m_parts) 2260 lockPartsForRead(true);
2102 { 2261 {
2103 foreach (SceneObjectPart part in m_parts.Values) 2262 foreach (SceneObjectPart part in m_parts.Values)
2104 { 2263 {
2105 if (part.LinkNum == linknum) 2264 if (part.LinkNum == linknum)
2106 { 2265 {
2266 lockPartsForRead(false);
2107 return part; 2267 return part;
2108 } 2268 }
2109 } 2269 }
2110 } 2270 }
2271 lockPartsForRead(false);
2111 2272
2112 return null; 2273 return null;
2113 } 2274 }
@@ -2135,17 +2296,19 @@ namespace OpenSim.Region.Framework.Scenes
2135 public SceneObjectPart GetChildPart(uint localID) 2296 public SceneObjectPart GetChildPart(uint localID)
2136 { 2297 {
2137 //m_log.DebugFormat("Entered looking for {0}", localID); 2298 //m_log.DebugFormat("Entered looking for {0}", localID);
2138 lock (m_parts) 2299 lockPartsForRead(true);
2139 { 2300 {
2140 foreach (SceneObjectPart part in m_parts.Values) 2301 foreach (SceneObjectPart part in m_parts.Values)
2141 { 2302 {
2142 //m_log.DebugFormat("Found {0}", part.LocalId); 2303 //m_log.DebugFormat("Found {0}", part.LocalId);
2143 if (part.LocalId == localID) 2304 if (part.LocalId == localID)
2144 { 2305 {
2306 lockPartsForRead(false);
2145 return part; 2307 return part;
2146 } 2308 }
2147 } 2309 }
2148 } 2310 }
2311 lockPartsForRead(false);
2149 2312
2150 return null; 2313 return null;
2151 } 2314 }
@@ -2175,17 +2338,19 @@ namespace OpenSim.Region.Framework.Scenes
2175 public bool HasChildPrim(uint localID) 2338 public bool HasChildPrim(uint localID)
2176 { 2339 {
2177 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID); 2340 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID);
2178 lock (m_parts) 2341 lockPartsForRead(true);
2179 { 2342 {
2180 foreach (SceneObjectPart part in m_parts.Values) 2343 foreach (SceneObjectPart part in m_parts.Values)
2181 { 2344 {
2182 //m_log.DebugFormat("Found {0}", part.LocalId); 2345 //m_log.DebugFormat("Found {0}", part.LocalId);
2183 if (part.LocalId == localID) 2346 if (part.LocalId == localID)
2184 { 2347 {
2348 lockPartsForRead(false);
2185 return true; 2349 return true;
2186 } 2350 }
2187 } 2351 }
2188 } 2352 }
2353 lockPartsForRead(false);
2189 2354
2190 return false; 2355 return false;
2191 } 2356 }
@@ -2235,53 +2400,57 @@ namespace OpenSim.Region.Framework.Scenes
2235 if (m_rootPart.LinkNum == 0) 2400 if (m_rootPart.LinkNum == 0)
2236 m_rootPart.LinkNum = 1; 2401 m_rootPart.LinkNum = 1;
2237 2402
2238 lock (m_parts) 2403 lockPartsForWrite(true);
2239 { 2404
2240 m_parts.Add(linkPart.UUID, linkPart); 2405 m_parts.Add(linkPart.UUID, linkPart);
2406
2407 lockPartsForWrite(false);
2241 2408
2242 // Insert in terms of link numbers, the new links 2409 // Insert in terms of link numbers, the new links
2243 // before the current ones (with the exception of 2410 // before the current ones (with the exception of
2244 // the root prim. Shuffle the old ones up 2411 // the root prim. Shuffle the old ones up
2245 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts) 2412 lockPartsForRead(true);
2413 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts)
2414 {
2415 if (kvp.Value.LinkNum != 1)
2246 { 2416 {
2247 if (kvp.Value.LinkNum != 1) 2417 // Don't update root prim link number
2248 { 2418 kvp.Value.LinkNum += objectGroup.PrimCount;
2249 // Don't update root prim link number
2250 kvp.Value.LinkNum += objectGroup.PrimCount;
2251 }
2252 } 2419 }
2420 }
2421 lockPartsForRead(false);
2253 2422
2254 linkPart.LinkNum = 2; 2423 linkPart.LinkNum = 2;
2255 2424
2256 linkPart.SetParent(this); 2425 linkPart.SetParent(this);
2257 linkPart.AddFlag(PrimFlags.CreateSelected); 2426 linkPart.AddFlag(PrimFlags.CreateSelected);
2258 2427
2259 //if (linkPart.PhysActor != null) 2428 //if (linkPart.PhysActor != null)
2260 //{ 2429 //{
2261 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); 2430 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor);
2262 2431
2263 //linkPart.PhysActor = null; 2432 //linkPart.PhysActor = null;
2264 //} 2433 //}
2265 2434
2266 //TODO: rest of parts 2435 //TODO: rest of parts
2267 int linkNum = 3; 2436 int linkNum = 3;
2268 foreach (SceneObjectPart part in objectGroup.Children.Values) 2437 foreach (SceneObjectPart part in objectGroup.Children.Values)
2438 {
2439 if (part.UUID != objectGroup.m_rootPart.UUID)
2269 { 2440 {
2270 if (part.UUID != objectGroup.m_rootPart.UUID) 2441 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2271 {
2272 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2273 }
2274 part.ClearUndoState();
2275 } 2442 }
2443 part.ClearUndoState();
2276 } 2444 }
2277 2445
2278 m_scene.UnlinkSceneObject(objectGroup.UUID, true); 2446 m_scene.UnlinkSceneObject(objectGroup.UUID, true);
2279 objectGroup.m_isDeleted = true; 2447 objectGroup.m_isDeleted = true;
2448
2449 objectGroup.lockPartsForWrite(true);
2280 2450
2281 lock (objectGroup.m_parts) 2451 objectGroup.m_parts.Clear();
2282 { 2452
2283 objectGroup.m_parts.Clear(); 2453 objectGroup.lockPartsForWrite(false);
2284 }
2285 2454
2286 // Can't do this yet since backup still makes use of the root part without any synchronization 2455 // Can't do this yet since backup still makes use of the root part without any synchronization
2287// objectGroup.m_rootPart = null; 2456// objectGroup.m_rootPart = null;
@@ -2351,11 +2520,12 @@ namespace OpenSim.Region.Framework.Scenes
2351 Quaternion worldRot = linkPart.GetWorldRotation(); 2520 Quaternion worldRot = linkPart.GetWorldRotation();
2352 2521
2353 // Remove the part from this object 2522 // Remove the part from this object
2354 lock (m_parts) 2523 lockPartsForWrite(true);
2355 { 2524 {
2356 m_parts.Remove(linkPart.UUID); 2525 m_parts.Remove(linkPart.UUID);
2357 } 2526 }
2358 2527 lockPartsForWrite(false);
2528 lockPartsForRead(true);
2359 if (m_parts.Count == 1 && RootPart != null) //Single prim is left 2529 if (m_parts.Count == 1 && RootPart != null) //Single prim is left
2360 RootPart.LinkNum = 0; 2530 RootPart.LinkNum = 0;
2361 else 2531 else
@@ -2366,6 +2536,7 @@ namespace OpenSim.Region.Framework.Scenes
2366 p.LinkNum--; 2536 p.LinkNum--;
2367 } 2537 }
2368 } 2538 }
2539 lockPartsForRead(false);
2369 2540
2370 linkPart.ParentID = 0; 2541 linkPart.ParentID = 0;
2371 linkPart.LinkNum = 0; 2542 linkPart.LinkNum = 0;
@@ -2687,9 +2858,12 @@ namespace OpenSim.Region.Framework.Scenes
2687 2858
2688 if (selectionPart != null) 2859 if (selectionPart != null)
2689 { 2860 {
2690 lock (m_parts) 2861 lockPartsForRead(true);
2862 List<SceneObjectPart> parts = new List<SceneObjectPart>(m_parts.Values);
2863 lockPartsForRead(false);
2864 foreach (SceneObjectPart part in parts)
2691 { 2865 {
2692 foreach (SceneObjectPart part in m_parts.Values) 2866 if (part.Scale.X > 10.0 || part.Scale.Y > 10.0 || part.Scale.Z > 10.0)
2693 { 2867 {
2694 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax || 2868 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax ||
2695 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax || 2869 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax ||
@@ -2699,12 +2873,13 @@ namespace OpenSim.Region.Framework.Scenes
2699 break; 2873 break;
2700 } 2874 }
2701 } 2875 }
2876 }
2702 2877
2703 foreach (SceneObjectPart part in m_parts.Values) 2878 foreach (SceneObjectPart part in parts)
2704 { 2879 {
2705 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect); 2880 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
2706 }
2707 } 2881 }
2882
2708 } 2883 }
2709 } 2884 }
2710 2885
@@ -2790,11 +2965,9 @@ namespace OpenSim.Region.Framework.Scenes
2790 scale.Y = m_scene.m_maxNonphys; 2965 scale.Y = m_scene.m_maxNonphys;
2791 if (scale.Z > m_scene.m_maxNonphys) 2966 if (scale.Z > m_scene.m_maxNonphys)
2792 scale.Z = m_scene.m_maxNonphys; 2967 scale.Z = m_scene.m_maxNonphys;
2793
2794 SceneObjectPart part = GetChildPart(localID); 2968 SceneObjectPart part = GetChildPart(localID);
2795 if (part != null) 2969 if (part != null)
2796 { 2970 {
2797 part.Resize(scale);
2798 if (part.PhysActor != null) 2971 if (part.PhysActor != null)
2799 { 2972 {
2800 if (part.PhysActor.IsPhysical) 2973 if (part.PhysActor.IsPhysical)
@@ -2809,7 +2982,7 @@ namespace OpenSim.Region.Framework.Scenes
2809 part.PhysActor.Size = scale; 2982 part.PhysActor.Size = scale;
2810 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); 2983 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor);
2811 } 2984 }
2812 //if (part.UUID != m_rootPart.UUID) 2985 part.Resize(scale);
2813 2986
2814 HasGroupChanged = true; 2987 HasGroupChanged = true;
2815 ScheduleGroupForFullUpdate(); 2988 ScheduleGroupForFullUpdate();
@@ -2851,73 +3024,71 @@ namespace OpenSim.Region.Framework.Scenes
2851 float y = (scale.Y / part.Scale.Y); 3024 float y = (scale.Y / part.Scale.Y);
2852 float z = (scale.Z / part.Scale.Z); 3025 float z = (scale.Z / part.Scale.Z);
2853 3026
2854 lock (m_parts) 3027 lockPartsForRead(true);
3028 if (x > 1.0f || y > 1.0f || z > 1.0f)
2855 { 3029 {
2856 if (x > 1.0f || y > 1.0f || z > 1.0f) 3030 foreach (SceneObjectPart obPart in m_parts.Values)
2857 { 3031 {
2858 foreach (SceneObjectPart obPart in m_parts.Values) 3032 if (obPart.UUID != m_rootPart.UUID)
2859 { 3033 {
2860 if (obPart.UUID != m_rootPart.UUID) 3034 Vector3 oldSize = new Vector3(obPart.Scale);
2861 { 3035 obPart.IgnoreUndoUpdate = true;
2862 obPart.IgnoreUndoUpdate = true;
2863 Vector3 oldSize = new Vector3(obPart.Scale);
2864 3036
2865 float f = 1.0f; 3037 float f = 1.0f;
2866 float a = 1.0f; 3038 float a = 1.0f;
2867 3039
2868 if (part.PhysActor != null && part.PhysActor.IsPhysical) 3040 if (part.PhysActor != null && part.PhysActor.IsPhysical)
3041 {
3042 if (oldSize.X*x > m_scene.m_maxPhys)
2869 { 3043 {
2870 if (oldSize.X*x > m_scene.m_maxPhys) 3044 f = m_scene.m_maxPhys / oldSize.X;
2871 { 3045 a = f / x;
2872 f = m_scene.m_maxPhys / oldSize.X; 3046 x *= a;
2873 a = f / x; 3047 y *= a;
2874 x *= a; 3048 z *= a;
2875 y *= a;
2876 z *= a;
2877 }
2878 if (oldSize.Y*y > m_scene.m_maxPhys)
2879 {
2880 f = m_scene.m_maxPhys / oldSize.Y;
2881 a = f / y;
2882 x *= a;
2883 y *= a;
2884 z *= a;
2885 }
2886 if (oldSize.Z*z > m_scene.m_maxPhys)
2887 {
2888 f = m_scene.m_maxPhys / oldSize.Z;
2889 a = f / z;
2890 x *= a;
2891 y *= a;
2892 z *= a;
2893 }
2894 } 3049 }
2895 else 3050 if (oldSize.Y*y > m_scene.m_maxPhys)
3051 {
3052 f = m_scene.m_maxPhys / oldSize.Y;
3053 a = f / y;
3054 x *= a;
3055 y *= a;
3056 z *= a;
3057 }
3058 if (oldSize.Z*z > m_scene.m_maxPhys)
3059 {
3060 f = m_scene.m_maxPhys / oldSize.Z;
3061 a = f / z;
3062 x *= a;
3063 y *= a;
3064 z *= a;
3065 }
3066 }
3067 else
3068 {
3069 if (oldSize.X*x > m_scene.m_maxNonphys)
3070 {
3071 f = m_scene.m_maxNonphys / oldSize.X;
3072 a = f / x;
3073 x *= a;
3074 y *= a;
3075 z *= a;
3076 }
3077 if (oldSize.Y*y > m_scene.m_maxNonphys)
2896 { 3078 {
2897 if (oldSize.X*x > m_scene.m_maxNonphys) 3079 f = m_scene.m_maxNonphys / oldSize.Y;
2898 { 3080 a = f / y;
2899 f = m_scene.m_maxNonphys / oldSize.X; 3081 x *= a;
2900 a = f / x; 3082 y *= a;
2901 x *= a; 3083 z *= a;
2902 y *= a; 3084 }
2903 z *= a; 3085 if (oldSize.Z*z > m_scene.m_maxNonphys)
2904 } 3086 {
2905 if (oldSize.Y*y > m_scene.m_maxNonphys) 3087 f = m_scene.m_maxNonphys / oldSize.Z;
2906 { 3088 a = f / z;
2907 f = m_scene.m_maxNonphys / oldSize.Y; 3089 x *= a;
2908 a = f / y; 3090 y *= a;
2909 x *= a; 3091 z *= a;
2910 y *= a;
2911 z *= a;
2912 }
2913 if (oldSize.Z*z > m_scene.m_maxNonphys)
2914 {
2915 f = m_scene.m_maxNonphys / oldSize.Z;
2916 a = f / z;
2917 x *= a;
2918 y *= a;
2919 z *= a;
2920 }
2921 } 3092 }
2922 obPart.IgnoreUndoUpdate = false; 3093 obPart.IgnoreUndoUpdate = false;
2923 obPart.StoreUndoState(); 3094 obPart.StoreUndoState();
@@ -2925,6 +3096,7 @@ namespace OpenSim.Region.Framework.Scenes
2925 } 3096 }
2926 } 3097 }
2927 } 3098 }
3099 lockPartsForRead(false);
2928 3100
2929 Vector3 prevScale = part.Scale; 3101 Vector3 prevScale = part.Scale;
2930 prevScale.X *= x; 3102 prevScale.X *= x;
@@ -2932,7 +3104,7 @@ namespace OpenSim.Region.Framework.Scenes
2932 prevScale.Z *= z; 3104 prevScale.Z *= z;
2933 part.Resize(prevScale); 3105 part.Resize(prevScale);
2934 3106
2935 lock (m_parts) 3107 lockPartsForRead(true);
2936 { 3108 {
2937 foreach (SceneObjectPart obPart in m_parts.Values) 3109 foreach (SceneObjectPart obPart in m_parts.Values)
2938 { 3110 {
@@ -2954,6 +3126,7 @@ namespace OpenSim.Region.Framework.Scenes
2954 obPart.StoreUndoState(); 3126 obPart.StoreUndoState();
2955 } 3127 }
2956 } 3128 }
3129 lockPartsForRead(false);
2957 3130
2958 if (part.PhysActor != null) 3131 if (part.PhysActor != null)
2959 { 3132 {
@@ -3056,7 +3229,7 @@ namespace OpenSim.Region.Framework.Scenes
3056 axDiff *= Quaternion.Inverse(partRotation); 3229 axDiff *= Quaternion.Inverse(partRotation);
3057 diff = axDiff; 3230 diff = axDiff;
3058 3231
3059 lock (m_parts) 3232 lockPartsForRead(true);
3060 { 3233 {
3061 foreach (SceneObjectPart obPart in m_parts.Values) 3234 foreach (SceneObjectPart obPart in m_parts.Values)
3062 { 3235 {
@@ -3066,6 +3239,7 @@ namespace OpenSim.Region.Framework.Scenes
3066 } 3239 }
3067 } 3240 }
3068 } 3241 }
3242 lockPartsForRead(false);
3069 3243
3070 AbsolutePosition = newPos; 3244 AbsolutePosition = newPos;
3071 3245
@@ -3199,25 +3373,25 @@ namespace OpenSim.Region.Framework.Scenes
3199 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); 3373 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
3200 } 3374 }
3201 3375
3202 lock (m_parts) 3376 lockPartsForRead(true);
3377
3378 foreach (SceneObjectPart prim in m_parts.Values)
3203 { 3379 {
3204 foreach (SceneObjectPart prim in m_parts.Values) 3380 if (prim.UUID != m_rootPart.UUID)
3205 { 3381 {
3206 if (prim.UUID != m_rootPart.UUID) 3382 prim.IgnoreUndoUpdate = true;
3207 { 3383 Vector3 axPos = prim.OffsetPosition;
3208 prim.IgnoreUndoUpdate = true; 3384 axPos *= oldParentRot;
3209 Vector3 axPos = prim.OffsetPosition; 3385 axPos *= Quaternion.Inverse(axRot);
3210 axPos *= oldParentRot; 3386 prim.OffsetPosition = axPos;
3211 axPos *= Quaternion.Inverse(axRot); 3387 Quaternion primsRot = prim.RotationOffset;
3212 prim.OffsetPosition = axPos; 3388 Quaternion newRot = primsRot * oldParentRot;
3213 Quaternion primsRot = prim.RotationOffset; 3389 newRot *= Quaternion.Inverse(axRot);
3214 Quaternion newRot = primsRot * oldParentRot; 3390 prim.RotationOffset = newRot;
3215 newRot *= Quaternion.Inverse(axRot); 3391 prim.ScheduleTerseUpdate();
3216 prim.RotationOffset = newRot;
3217 prim.ScheduleTerseUpdate();
3218 }
3219 } 3392 }
3220 } 3393 }
3394
3221 foreach (SceneObjectPart childpart in Children.Values) 3395 foreach (SceneObjectPart childpart in Children.Values)
3222 { 3396 {
3223 if (childpart != m_rootPart) 3397 if (childpart != m_rootPart)
@@ -3226,6 +3400,9 @@ namespace OpenSim.Region.Framework.Scenes
3226 childpart.StoreUndoState(); 3400 childpart.StoreUndoState();
3227 } 3401 }
3228 } 3402 }
3403
3404 lockPartsForRead(false);
3405
3229 m_rootPart.ScheduleTerseUpdate(); 3406 m_rootPart.ScheduleTerseUpdate();
3230 } 3407 }
3231 3408
@@ -3347,7 +3524,7 @@ namespace OpenSim.Region.Framework.Scenes
3347 if (atTargets.Count > 0) 3524 if (atTargets.Count > 0)
3348 { 3525 {
3349 uint[] localids = new uint[0]; 3526 uint[] localids = new uint[0];
3350 lock (m_parts) 3527 lockPartsForRead(true);
3351 { 3528 {
3352 localids = new uint[m_parts.Count]; 3529 localids = new uint[m_parts.Count];
3353 int cntr = 0; 3530 int cntr = 0;
@@ -3357,6 +3534,7 @@ namespace OpenSim.Region.Framework.Scenes
3357 cntr++; 3534 cntr++;
3358 } 3535 }
3359 } 3536 }
3537 lockPartsForRead(false);
3360 3538
3361 for (int ctr = 0; ctr < localids.Length; ctr++) 3539 for (int ctr = 0; ctr < localids.Length; ctr++)
3362 { 3540 {
@@ -3375,7 +3553,7 @@ namespace OpenSim.Region.Framework.Scenes
3375 { 3553 {
3376 //trigger not_at_target 3554 //trigger not_at_target
3377 uint[] localids = new uint[0]; 3555 uint[] localids = new uint[0];
3378 lock (m_parts) 3556 lockPartsForRead(true);
3379 { 3557 {
3380 localids = new uint[m_parts.Count]; 3558 localids = new uint[m_parts.Count];
3381 int cntr = 0; 3559 int cntr = 0;
@@ -3385,7 +3563,8 @@ namespace OpenSim.Region.Framework.Scenes
3385 cntr++; 3563 cntr++;
3386 } 3564 }
3387 } 3565 }
3388 3566 lockPartsForRead(false);
3567
3389 for (int ctr = 0; ctr < localids.Length; ctr++) 3568 for (int ctr = 0; ctr < localids.Length; ctr++)
3390 { 3569 {
3391 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]); 3570 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]);
@@ -3477,19 +3656,20 @@ namespace OpenSim.Region.Framework.Scenes
3477 public float GetMass() 3656 public float GetMass()
3478 { 3657 {
3479 float retmass = 0f; 3658 float retmass = 0f;
3480 lock (m_parts) 3659 lockPartsForRead(true);
3481 { 3660 {
3482 foreach (SceneObjectPart part in m_parts.Values) 3661 foreach (SceneObjectPart part in m_parts.Values)
3483 { 3662 {
3484 retmass += part.GetMass(); 3663 retmass += part.GetMass();
3485 } 3664 }
3486 } 3665 }
3666 lockPartsForRead(false);
3487 return retmass; 3667 return retmass;
3488 } 3668 }
3489 3669
3490 public void CheckSculptAndLoad() 3670 public void CheckSculptAndLoad()
3491 { 3671 {
3492 lock (m_parts) 3672 lockPartsForRead(true);
3493 { 3673 {
3494 if (!IsDeleted) 3674 if (!IsDeleted)
3495 { 3675 {
@@ -3514,6 +3694,7 @@ namespace OpenSim.Region.Framework.Scenes
3514 } 3694 }
3515 } 3695 }
3516 } 3696 }
3697 lockPartsForRead(false);
3517 } 3698 }
3518 3699
3519 protected void AssetReceived(string id, Object sender, AssetBase asset) 3700 protected void AssetReceived(string id, Object sender, AssetBase asset)
@@ -3534,7 +3715,7 @@ namespace OpenSim.Region.Framework.Scenes
3534 /// <param name="client"></param> 3715 /// <param name="client"></param>
3535 public void SetGroup(UUID GroupID, IClientAPI client) 3716 public void SetGroup(UUID GroupID, IClientAPI client)
3536 { 3717 {
3537 lock (m_parts) 3718 lockPartsForRead(true);
3538 { 3719 {
3539 foreach (SceneObjectPart part in m_parts.Values) 3720 foreach (SceneObjectPart part in m_parts.Values)
3540 { 3721 {
@@ -3544,6 +3725,7 @@ namespace OpenSim.Region.Framework.Scenes
3544 3725
3545 HasGroupChanged = true; 3726 HasGroupChanged = true;
3546 } 3727 }
3728 lockPartsForRead(false);
3547 3729
3548 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled 3730 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled
3549 // for the same object with very different properties. The caller must schedule the update. 3731 // for the same object with very different properties. The caller must schedule the update.
@@ -3565,11 +3747,12 @@ namespace OpenSim.Region.Framework.Scenes
3565 3747
3566 public void SetAttachmentPoint(byte point) 3748 public void SetAttachmentPoint(byte point)
3567 { 3749 {
3568 lock (m_parts) 3750 lockPartsForRead(true);
3569 { 3751 {
3570 foreach (SceneObjectPart part in m_parts.Values) 3752 foreach (SceneObjectPart part in m_parts.Values)
3571 part.SetAttachmentPoint(point); 3753 part.SetAttachmentPoint(point);
3572 } 3754 }
3755 lockPartsForRead(false);
3573 } 3756 }
3574 3757
3575 #region ISceneObject 3758 #region ISceneObject