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, 391 insertions, 210 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 88deedf..d083119 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,29 +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 1372
1272 ScenePresence[] avatars = Scene.GetScenePresences(); 1373 ScenePresence[] avatars = Scene.GetScenePresences();
1273 for (int i = 0; i < avatars.Length; i++) 1374 for (int i = 0; i < avatars.Length; i++)
1375 {
1376 if (avatars[i].ParentID == LocalId)
1274 { 1377 {
1275 if (avatars[i].ParentID == LocalId) 1378 avatars[i].StandUp();
1276 { 1379 }
1277 avatars[i].StandUp();
1278 }
1279 1380
1280 if (!silent) 1381 if (!silent)
1281 { 1382 {
1282 part.UpdateFlag = 0; 1383 part.UpdateFlag = 0;
1283 if (part == m_rootPart) 1384 if (part == m_rootPart)
1284 avatars[i].ControllingClient.SendKillObject(m_regionHandle, part.LocalId); 1385 avatars[i].ControllingClient.SendKillObject(m_regionHandle, part.LocalId);
1285 }
1286 } 1386 }
1287 } 1387 }
1388
1288 } 1389 }
1390
1391
1289 } 1392 }
1290 1393
1291 public void AddScriptLPS(int count) 1394 public void AddScriptLPS(int count)
@@ -1310,17 +1413,20 @@ namespace OpenSim.Region.Framework.Scenes
1310 1413
1311 scriptEvents aggregateScriptEvents=0; 1414 scriptEvents aggregateScriptEvents=0;
1312 1415
1313 lock (m_parts) 1416 lockPartsForRead(true);
1314 { 1417 {
1315 foreach (SceneObjectPart part in m_parts.Values) 1418 foreach (SceneObjectPart part in m_parts.Values)
1316 { 1419 {
1420
1317 if (part == null) 1421 if (part == null)
1318 continue; 1422 continue;
1319 if (part != RootPart) 1423 if (part != RootPart)
1320 part.ObjectFlags = objectflagupdate; 1424 part.ObjectFlags = objectflagupdate;
1321 aggregateScriptEvents |= part.AggregateScriptEvents; 1425 aggregateScriptEvents |= part.AggregateScriptEvents;
1426
1322 } 1427 }
1323 } 1428 }
1429 lockPartsForRead(false);
1324 1430
1325 m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0); 1431 m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0);
1326 m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0); 1432 m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0);
@@ -1362,42 +1468,52 @@ namespace OpenSim.Region.Framework.Scenes
1362 /// <param name="m_physicalPrim"></param> 1468 /// <param name="m_physicalPrim"></param>
1363 public void ApplyPhysics(bool m_physicalPrim) 1469 public void ApplyPhysics(bool m_physicalPrim)
1364 { 1470 {
1365 lock (m_parts) 1471 lockPartsForRead(true);
1472
1473 if (m_parts.Count > 1)
1366 { 1474 {
1367 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)
1368 { 1479 {
1369 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim); 1480
1370 foreach (SceneObjectPart part in m_parts.Values) 1481 if (part.LocalId != m_rootPart.LocalId)
1371 { 1482 {
1372 if (part.LocalId != m_rootPart.LocalId) 1483 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim);
1373 {
1374 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim);
1375 }
1376 } 1484 }
1377 1485
1378 // Hack to get the physics scene geometries in the right spot
1379 ResetChildPrimPhysicsPositions();
1380 }
1381 else
1382 {
1383 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1384 } 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);
1385 } 1494 }
1386 } 1495 }
1387 1496
1388 public void SetOwnerId(UUID userId) 1497 public void SetOwnerId(UUID userId)
1389 { 1498 {
1390 ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); 1499 ForEachPart(delegate(SceneObjectPart part)
1500 {
1501
1502 part.OwnerID = userId;
1503
1504 });
1391 } 1505 }
1392 1506
1393 public void ForEachPart(Action<SceneObjectPart> whatToDo) 1507 public void ForEachPart(Action<SceneObjectPart> whatToDo)
1394 { 1508 {
1395 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)
1396 { 1513 {
1397 foreach (SceneObjectPart part in m_parts.Values) 1514
1398 { 1515 whatToDo(part);
1399 whatToDo(part); 1516
1400 }
1401 } 1517 }
1402 } 1518 }
1403 1519
@@ -1495,10 +1611,11 @@ namespace OpenSim.Region.Framework.Scenes
1495 RootPart.SendFullUpdate( 1611 RootPart.SendFullUpdate(
1496 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID)); 1612 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID));
1497 1613
1498 lock (m_parts) 1614 lockPartsForRead(true);
1499 { 1615 {
1500 foreach (SceneObjectPart part in m_parts.Values) 1616 foreach (SceneObjectPart part in m_parts.Values)
1501 { 1617 {
1618
1502 if (part != RootPart) 1619 if (part != RootPart)
1503 part.SendFullUpdate( 1620 part.SendFullUpdate(
1504 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID)); 1621 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID));
@@ -1572,10 +1689,11 @@ namespace OpenSim.Region.Framework.Scenes
1572 1689
1573 List<SceneObjectPart> partList; 1690 List<SceneObjectPart> partList;
1574 1691
1575 lock (m_parts) 1692 lockPartsForRead(true);
1576 { 1693
1577 partList = new List<SceneObjectPart>(m_parts.Values); 1694 partList = new List<SceneObjectPart>(m_parts.Values);
1578 } 1695
1696 lockPartsForRead(false);
1579 1697
1580 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) 1698 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1581 { 1699 {
@@ -1798,13 +1916,40 @@ namespace OpenSim.Region.Framework.Scenes
1798 } 1916 }
1799 } 1917 }
1800 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
1801 public void stopLookAt() 1946 public void stopLookAt()
1802 { 1947 {
1803 SceneObjectPart rootpart = m_rootPart; 1948 SceneObjectPart rootpart = m_rootPart;
1804 if (rootpart != null) 1949 if (rootpart != null)
1805 { 1950 {
1806 if (rootpart.PhysActor != null) 1951 if (rootpart.PhysActor != null)
1807 { 1952 { // APID must be implemented in your physics system for this to function.
1808 rootpart.PhysActor.APIDActive = false; 1953 rootpart.PhysActor.APIDActive = false;
1809 } 1954 }
1810 } 1955 }
@@ -1872,10 +2017,11 @@ namespace OpenSim.Region.Framework.Scenes
1872 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);
1873 newPart.SetParent(this); 2018 newPart.SetParent(this);
1874 2019
1875 lock (m_parts) 2020 lockPartsForWrite(true);
1876 { 2021 {
1877 m_parts.Add(newPart.UUID, newPart); 2022 m_parts.Add(newPart.UUID, newPart);
1878 } 2023 }
2024 lockPartsForWrite(false);
1879 2025
1880 SetPartAsNonRoot(newPart); 2026 SetPartAsNonRoot(newPart);
1881 2027
@@ -1938,7 +2084,7 @@ namespace OpenSim.Region.Framework.Scenes
1938 //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0) 2084 //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
1939 // return; 2085 // return;
1940 2086
1941 lock (m_parts) 2087 lockPartsForRead(true);
1942 { 2088 {
1943 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0); 2089 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0);
1944 2090
@@ -1958,9 +2104,12 @@ namespace OpenSim.Region.Framework.Scenes
1958 { 2104 {
1959 if (!IsSelected) 2105 if (!IsSelected)
1960 part.UpdateLookAt(); 2106 part.UpdateLookAt();
2107
1961 part.SendScheduledUpdates(); 2108 part.SendScheduledUpdates();
2109
1962 } 2110 }
1963 } 2111 }
2112 lockPartsForRead(false);
1964 } 2113 }
1965 2114
1966 public void ScheduleFullUpdateToAvatar(ScenePresence presence) 2115 public void ScheduleFullUpdateToAvatar(ScenePresence presence)
@@ -1969,27 +2118,29 @@ namespace OpenSim.Region.Framework.Scenes
1969 2118
1970 RootPart.AddFullUpdateToAvatar(presence); 2119 RootPart.AddFullUpdateToAvatar(presence);
1971 2120
1972 lock (m_parts) 2121 lockPartsForRead(true);
1973 { 2122 {
1974 foreach (SceneObjectPart part in m_parts.Values) 2123 foreach (SceneObjectPart part in m_parts.Values)
1975 { 2124 {
2125
1976 if (part != RootPart) 2126 if (part != RootPart)
1977 part.AddFullUpdateToAvatar(presence); 2127 part.AddFullUpdateToAvatar(presence);
2128
1978 } 2129 }
1979 } 2130 }
2131 lockPartsForRead(false);
1980 } 2132 }
1981 2133
1982 public void ScheduleTerseUpdateToAvatar(ScenePresence presence) 2134 public void ScheduleTerseUpdateToAvatar(ScenePresence presence)
1983 { 2135 {
1984// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1} just to avatar {2}", Name, UUID, presence.Name); 2136 lockPartsForRead(true);
1985 2137
1986 lock (m_parts) 2138 foreach (SceneObjectPart part in m_parts.Values)
1987 { 2139 {
1988 foreach (SceneObjectPart part in m_parts.Values) 2140 part.AddTerseUpdateToAvatar(presence);
1989 {
1990 part.AddTerseUpdateToAvatar(presence);
1991 }
1992 } 2141 }
2142
2143 lockPartsForRead(false);
1993 } 2144 }
1994 2145
1995 /// <summary> 2146 /// <summary>
@@ -2002,14 +2153,17 @@ namespace OpenSim.Region.Framework.Scenes
2002 checkAtTargets(); 2153 checkAtTargets();
2003 RootPart.ScheduleFullUpdate(); 2154 RootPart.ScheduleFullUpdate();
2004 2155
2005 lock (m_parts) 2156 lockPartsForRead(true);
2006 { 2157 {
2007 foreach (SceneObjectPart part in m_parts.Values) 2158 foreach (SceneObjectPart part in m_parts.Values)
2008 { 2159 {
2160
2009 if (part != RootPart) 2161 if (part != RootPart)
2010 part.ScheduleFullUpdate(); 2162 part.ScheduleFullUpdate();
2163
2011 } 2164 }
2012 } 2165 }
2166 lockPartsForRead(false);
2013 } 2167 }
2014 2168
2015 /// <summary> 2169 /// <summary>
@@ -2017,15 +2171,14 @@ namespace OpenSim.Region.Framework.Scenes
2017 /// </summary> 2171 /// </summary>
2018 public void ScheduleGroupForTerseUpdate() 2172 public void ScheduleGroupForTerseUpdate()
2019 { 2173 {
2020// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1}", Name, UUID); 2174 lockPartsForRead(true);
2021 2175
2022 lock (m_parts) 2176 foreach (SceneObjectPart part in m_parts.Values)
2023 { 2177 {
2024 foreach (SceneObjectPart part in m_parts.Values) 2178 part.ScheduleTerseUpdate();
2025 {
2026 part.ScheduleTerseUpdate();
2027 }
2028 } 2179 }
2180
2181 lockPartsForRead(false);
2029 } 2182 }
2030 2183
2031 /// <summary> 2184 /// <summary>
@@ -2040,14 +2193,17 @@ namespace OpenSim.Region.Framework.Scenes
2040 2193
2041 RootPart.SendFullUpdateToAllClients(); 2194 RootPart.SendFullUpdateToAllClients();
2042 2195
2043 lock (m_parts) 2196 lockPartsForRead(true);
2044 { 2197 {
2045 foreach (SceneObjectPart part in m_parts.Values) 2198 foreach (SceneObjectPart part in m_parts.Values)
2046 { 2199 {
2200
2047 if (part != RootPart) 2201 if (part != RootPart)
2048 part.SendFullUpdateToAllClients(); 2202 part.SendFullUpdateToAllClients();
2203
2049 } 2204 }
2050 } 2205 }
2206 lockPartsForRead(false);
2051 } 2207 }
2052 2208
2053 /// <summary> 2209 /// <summary>
@@ -2079,14 +2235,15 @@ namespace OpenSim.Region.Framework.Scenes
2079 { 2235 {
2080 if (IsDeleted) 2236 if (IsDeleted)
2081 return; 2237 return;
2082 2238
2083 lock (m_parts) 2239 lockPartsForRead(true);
2084 { 2240 {
2085 foreach (SceneObjectPart part in m_parts.Values) 2241 foreach (SceneObjectPart part in m_parts.Values)
2086 { 2242 {
2087 part.SendTerseUpdateToAllClients(); 2243 part.SendTerseUpdateToAllClients();
2088 } 2244 }
2089 } 2245 }
2246 lockPartsForRead(false);
2090 } 2247 }
2091 2248
2092 #endregion 2249 #endregion
@@ -2100,16 +2257,18 @@ namespace OpenSim.Region.Framework.Scenes
2100 /// <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>
2101 public SceneObjectPart GetLinkNumPart(int linknum) 2258 public SceneObjectPart GetLinkNumPart(int linknum)
2102 { 2259 {
2103 lock (m_parts) 2260 lockPartsForRead(true);
2104 { 2261 {
2105 foreach (SceneObjectPart part in m_parts.Values) 2262 foreach (SceneObjectPart part in m_parts.Values)
2106 { 2263 {
2107 if (part.LinkNum == linknum) 2264 if (part.LinkNum == linknum)
2108 { 2265 {
2266 lockPartsForRead(false);
2109 return part; 2267 return part;
2110 } 2268 }
2111 } 2269 }
2112 } 2270 }
2271 lockPartsForRead(false);
2113 2272
2114 return null; 2273 return null;
2115 } 2274 }
@@ -2137,17 +2296,19 @@ namespace OpenSim.Region.Framework.Scenes
2137 public SceneObjectPart GetChildPart(uint localID) 2296 public SceneObjectPart GetChildPart(uint localID)
2138 { 2297 {
2139 //m_log.DebugFormat("Entered looking for {0}", localID); 2298 //m_log.DebugFormat("Entered looking for {0}", localID);
2140 lock (m_parts) 2299 lockPartsForRead(true);
2141 { 2300 {
2142 foreach (SceneObjectPart part in m_parts.Values) 2301 foreach (SceneObjectPart part in m_parts.Values)
2143 { 2302 {
2144 //m_log.DebugFormat("Found {0}", part.LocalId); 2303 //m_log.DebugFormat("Found {0}", part.LocalId);
2145 if (part.LocalId == localID) 2304 if (part.LocalId == localID)
2146 { 2305 {
2306 lockPartsForRead(false);
2147 return part; 2307 return part;
2148 } 2308 }
2149 } 2309 }
2150 } 2310 }
2311 lockPartsForRead(false);
2151 2312
2152 return null; 2313 return null;
2153 } 2314 }
@@ -2177,17 +2338,19 @@ namespace OpenSim.Region.Framework.Scenes
2177 public bool HasChildPrim(uint localID) 2338 public bool HasChildPrim(uint localID)
2178 { 2339 {
2179 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID); 2340 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID);
2180 lock (m_parts) 2341 lockPartsForRead(true);
2181 { 2342 {
2182 foreach (SceneObjectPart part in m_parts.Values) 2343 foreach (SceneObjectPart part in m_parts.Values)
2183 { 2344 {
2184 //m_log.DebugFormat("Found {0}", part.LocalId); 2345 //m_log.DebugFormat("Found {0}", part.LocalId);
2185 if (part.LocalId == localID) 2346 if (part.LocalId == localID)
2186 { 2347 {
2348 lockPartsForRead(false);
2187 return true; 2349 return true;
2188 } 2350 }
2189 } 2351 }
2190 } 2352 }
2353 lockPartsForRead(false);
2191 2354
2192 return false; 2355 return false;
2193 } 2356 }
@@ -2237,53 +2400,57 @@ namespace OpenSim.Region.Framework.Scenes
2237 if (m_rootPart.LinkNum == 0) 2400 if (m_rootPart.LinkNum == 0)
2238 m_rootPart.LinkNum = 1; 2401 m_rootPart.LinkNum = 1;
2239 2402
2240 lock (m_parts) 2403 lockPartsForWrite(true);
2241 { 2404
2242 m_parts.Add(linkPart.UUID, linkPart); 2405 m_parts.Add(linkPart.UUID, linkPart);
2406
2407 lockPartsForWrite(false);
2243 2408
2244 // Insert in terms of link numbers, the new links 2409 // Insert in terms of link numbers, the new links
2245 // before the current ones (with the exception of 2410 // before the current ones (with the exception of
2246 // the root prim. Shuffle the old ones up 2411 // the root prim. Shuffle the old ones up
2247 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)
2248 { 2416 {
2249 if (kvp.Value.LinkNum != 1) 2417 // Don't update root prim link number
2250 { 2418 kvp.Value.LinkNum += objectGroup.PrimCount;
2251 // Don't update root prim link number
2252 kvp.Value.LinkNum += objectGroup.PrimCount;
2253 }
2254 } 2419 }
2420 }
2421 lockPartsForRead(false);
2255 2422
2256 linkPart.LinkNum = 2; 2423 linkPart.LinkNum = 2;
2257 2424
2258 linkPart.SetParent(this); 2425 linkPart.SetParent(this);
2259 linkPart.AddFlag(PrimFlags.CreateSelected); 2426 linkPart.AddFlag(PrimFlags.CreateSelected);
2260 2427
2261 //if (linkPart.PhysActor != null) 2428 //if (linkPart.PhysActor != null)
2262 //{ 2429 //{
2263 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); 2430 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor);
2264 2431
2265 //linkPart.PhysActor = null; 2432 //linkPart.PhysActor = null;
2266 //} 2433 //}
2267 2434
2268 //TODO: rest of parts 2435 //TODO: rest of parts
2269 int linkNum = 3; 2436 int linkNum = 3;
2270 foreach (SceneObjectPart part in objectGroup.Children.Values) 2437 foreach (SceneObjectPart part in objectGroup.Children.Values)
2438 {
2439 if (part.UUID != objectGroup.m_rootPart.UUID)
2271 { 2440 {
2272 if (part.UUID != objectGroup.m_rootPart.UUID) 2441 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2273 {
2274 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2275 }
2276 part.ClearUndoState();
2277 } 2442 }
2443 part.ClearUndoState();
2278 } 2444 }
2279 2445
2280 m_scene.UnlinkSceneObject(objectGroup.UUID, true); 2446 m_scene.UnlinkSceneObject(objectGroup.UUID, true);
2281 objectGroup.m_isDeleted = true; 2447 objectGroup.m_isDeleted = true;
2448
2449 objectGroup.lockPartsForWrite(true);
2282 2450
2283 lock (objectGroup.m_parts) 2451 objectGroup.m_parts.Clear();
2284 { 2452
2285 objectGroup.m_parts.Clear(); 2453 objectGroup.lockPartsForWrite(false);
2286 }
2287 2454
2288 // 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
2289// objectGroup.m_rootPart = null; 2456// objectGroup.m_rootPart = null;
@@ -2353,11 +2520,12 @@ namespace OpenSim.Region.Framework.Scenes
2353 Quaternion worldRot = linkPart.GetWorldRotation(); 2520 Quaternion worldRot = linkPart.GetWorldRotation();
2354 2521
2355 // Remove the part from this object 2522 // Remove the part from this object
2356 lock (m_parts) 2523 lockPartsForWrite(true);
2357 { 2524 {
2358 m_parts.Remove(linkPart.UUID); 2525 m_parts.Remove(linkPart.UUID);
2359 } 2526 }
2360 2527 lockPartsForWrite(false);
2528 lockPartsForRead(true);
2361 if (m_parts.Count == 1 && RootPart != null) //Single prim is left 2529 if (m_parts.Count == 1 && RootPart != null) //Single prim is left
2362 RootPart.LinkNum = 0; 2530 RootPart.LinkNum = 0;
2363 else 2531 else
@@ -2368,6 +2536,7 @@ namespace OpenSim.Region.Framework.Scenes
2368 p.LinkNum--; 2536 p.LinkNum--;
2369 } 2537 }
2370 } 2538 }
2539 lockPartsForRead(false);
2371 2540
2372 linkPart.ParentID = 0; 2541 linkPart.ParentID = 0;
2373 linkPart.LinkNum = 0; 2542 linkPart.LinkNum = 0;
@@ -2689,9 +2858,12 @@ namespace OpenSim.Region.Framework.Scenes
2689 2858
2690 if (selectionPart != null) 2859 if (selectionPart != null)
2691 { 2860 {
2692 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)
2693 { 2865 {
2694 foreach (SceneObjectPart part in m_parts.Values) 2866 if (part.Scale.X > 10.0 || part.Scale.Y > 10.0 || part.Scale.Z > 10.0)
2695 { 2867 {
2696 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax || 2868 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax ||
2697 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax || 2869 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax ||
@@ -2701,12 +2873,13 @@ namespace OpenSim.Region.Framework.Scenes
2701 break; 2873 break;
2702 } 2874 }
2703 } 2875 }
2876 }
2704 2877
2705 foreach (SceneObjectPart part in m_parts.Values) 2878 foreach (SceneObjectPart part in parts)
2706 { 2879 {
2707 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect); 2880 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
2708 }
2709 } 2881 }
2882
2710 } 2883 }
2711 } 2884 }
2712 2885
@@ -2792,11 +2965,9 @@ namespace OpenSim.Region.Framework.Scenes
2792 scale.Y = m_scene.m_maxNonphys; 2965 scale.Y = m_scene.m_maxNonphys;
2793 if (scale.Z > m_scene.m_maxNonphys) 2966 if (scale.Z > m_scene.m_maxNonphys)
2794 scale.Z = m_scene.m_maxNonphys; 2967 scale.Z = m_scene.m_maxNonphys;
2795
2796 SceneObjectPart part = GetChildPart(localID); 2968 SceneObjectPart part = GetChildPart(localID);
2797 if (part != null) 2969 if (part != null)
2798 { 2970 {
2799 part.Resize(scale);
2800 if (part.PhysActor != null) 2971 if (part.PhysActor != null)
2801 { 2972 {
2802 if (part.PhysActor.IsPhysical) 2973 if (part.PhysActor.IsPhysical)
@@ -2811,7 +2982,7 @@ namespace OpenSim.Region.Framework.Scenes
2811 part.PhysActor.Size = scale; 2982 part.PhysActor.Size = scale;
2812 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); 2983 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor);
2813 } 2984 }
2814 //if (part.UUID != m_rootPart.UUID) 2985 part.Resize(scale);
2815 2986
2816 HasGroupChanged = true; 2987 HasGroupChanged = true;
2817 ScheduleGroupForFullUpdate(); 2988 ScheduleGroupForFullUpdate();
@@ -2853,73 +3024,71 @@ namespace OpenSim.Region.Framework.Scenes
2853 float y = (scale.Y / part.Scale.Y); 3024 float y = (scale.Y / part.Scale.Y);
2854 float z = (scale.Z / part.Scale.Z); 3025 float z = (scale.Z / part.Scale.Z);
2855 3026
2856 lock (m_parts) 3027 lockPartsForRead(true);
3028 if (x > 1.0f || y > 1.0f || z > 1.0f)
2857 { 3029 {
2858 if (x > 1.0f || y > 1.0f || z > 1.0f) 3030 foreach (SceneObjectPart obPart in m_parts.Values)
2859 { 3031 {
2860 foreach (SceneObjectPart obPart in m_parts.Values) 3032 if (obPart.UUID != m_rootPart.UUID)
2861 { 3033 {
2862 if (obPart.UUID != m_rootPart.UUID) 3034 Vector3 oldSize = new Vector3(obPart.Scale);
2863 { 3035 obPart.IgnoreUndoUpdate = true;
2864 obPart.IgnoreUndoUpdate = true;
2865 Vector3 oldSize = new Vector3(obPart.Scale);
2866 3036
2867 float f = 1.0f; 3037 float f = 1.0f;
2868 float a = 1.0f; 3038 float a = 1.0f;
2869 3039
2870 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)
2871 { 3043 {
2872 if (oldSize.X*x > m_scene.m_maxPhys) 3044 f = m_scene.m_maxPhys / oldSize.X;
2873 { 3045 a = f / x;
2874 f = m_scene.m_maxPhys / oldSize.X; 3046 x *= a;
2875 a = f / x; 3047 y *= a;
2876 x *= a; 3048 z *= a;
2877 y *= a;
2878 z *= a;
2879 }
2880 if (oldSize.Y*y > m_scene.m_maxPhys)
2881 {
2882 f = m_scene.m_maxPhys / oldSize.Y;
2883 a = f / y;
2884 x *= a;
2885 y *= a;
2886 z *= a;
2887 }
2888 if (oldSize.Z*z > m_scene.m_maxPhys)
2889 {
2890 f = m_scene.m_maxPhys / oldSize.Z;
2891 a = f / z;
2892 x *= a;
2893 y *= a;
2894 z *= a;
2895 }
2896 } 3049 }
2897 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)
2898 { 3078 {
2899 if (oldSize.X*x > m_scene.m_maxNonphys) 3079 f = m_scene.m_maxNonphys / oldSize.Y;
2900 { 3080 a = f / y;
2901 f = m_scene.m_maxNonphys / oldSize.X; 3081 x *= a;
2902 a = f / x; 3082 y *= a;
2903 x *= a; 3083 z *= a;
2904 y *= a; 3084 }
2905 z *= a; 3085 if (oldSize.Z*z > m_scene.m_maxNonphys)
2906 } 3086 {
2907 if (oldSize.Y*y > m_scene.m_maxNonphys) 3087 f = m_scene.m_maxNonphys / oldSize.Z;
2908 { 3088 a = f / z;
2909 f = m_scene.m_maxNonphys / oldSize.Y; 3089 x *= a;
2910 a = f / y; 3090 y *= a;
2911 x *= a; 3091 z *= a;
2912 y *= a;
2913 z *= a;
2914 }
2915 if (oldSize.Z*z > m_scene.m_maxNonphys)
2916 {
2917 f = m_scene.m_maxNonphys / oldSize.Z;
2918 a = f / z;
2919 x *= a;
2920 y *= a;
2921 z *= a;
2922 }
2923 } 3092 }
2924 obPart.IgnoreUndoUpdate = false; 3093 obPart.IgnoreUndoUpdate = false;
2925 obPart.StoreUndoState(); 3094 obPart.StoreUndoState();
@@ -2927,6 +3096,7 @@ namespace OpenSim.Region.Framework.Scenes
2927 } 3096 }
2928 } 3097 }
2929 } 3098 }
3099 lockPartsForRead(false);
2930 3100
2931 Vector3 prevScale = part.Scale; 3101 Vector3 prevScale = part.Scale;
2932 prevScale.X *= x; 3102 prevScale.X *= x;
@@ -2934,7 +3104,7 @@ namespace OpenSim.Region.Framework.Scenes
2934 prevScale.Z *= z; 3104 prevScale.Z *= z;
2935 part.Resize(prevScale); 3105 part.Resize(prevScale);
2936 3106
2937 lock (m_parts) 3107 lockPartsForRead(true);
2938 { 3108 {
2939 foreach (SceneObjectPart obPart in m_parts.Values) 3109 foreach (SceneObjectPart obPart in m_parts.Values)
2940 { 3110 {
@@ -2956,6 +3126,7 @@ namespace OpenSim.Region.Framework.Scenes
2956 obPart.StoreUndoState(); 3126 obPart.StoreUndoState();
2957 } 3127 }
2958 } 3128 }
3129 lockPartsForRead(false);
2959 3130
2960 if (part.PhysActor != null) 3131 if (part.PhysActor != null)
2961 { 3132 {
@@ -3058,7 +3229,7 @@ namespace OpenSim.Region.Framework.Scenes
3058 axDiff *= Quaternion.Inverse(partRotation); 3229 axDiff *= Quaternion.Inverse(partRotation);
3059 diff = axDiff; 3230 diff = axDiff;
3060 3231
3061 lock (m_parts) 3232 lockPartsForRead(true);
3062 { 3233 {
3063 foreach (SceneObjectPart obPart in m_parts.Values) 3234 foreach (SceneObjectPart obPart in m_parts.Values)
3064 { 3235 {
@@ -3068,6 +3239,7 @@ namespace OpenSim.Region.Framework.Scenes
3068 } 3239 }
3069 } 3240 }
3070 } 3241 }
3242 lockPartsForRead(false);
3071 3243
3072 AbsolutePosition = newPos; 3244 AbsolutePosition = newPos;
3073 3245
@@ -3201,25 +3373,25 @@ namespace OpenSim.Region.Framework.Scenes
3201 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); 3373 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
3202 } 3374 }
3203 3375
3204 lock (m_parts) 3376 lockPartsForRead(true);
3377
3378 foreach (SceneObjectPart prim in m_parts.Values)
3205 { 3379 {
3206 foreach (SceneObjectPart prim in m_parts.Values) 3380 if (prim.UUID != m_rootPart.UUID)
3207 { 3381 {
3208 if (prim.UUID != m_rootPart.UUID) 3382 prim.IgnoreUndoUpdate = true;
3209 { 3383 Vector3 axPos = prim.OffsetPosition;
3210 prim.IgnoreUndoUpdate = true; 3384 axPos *= oldParentRot;
3211 Vector3 axPos = prim.OffsetPosition; 3385 axPos *= Quaternion.Inverse(axRot);
3212 axPos *= oldParentRot; 3386 prim.OffsetPosition = axPos;
3213 axPos *= Quaternion.Inverse(axRot); 3387 Quaternion primsRot = prim.RotationOffset;
3214 prim.OffsetPosition = axPos; 3388 Quaternion newRot = primsRot * oldParentRot;
3215 Quaternion primsRot = prim.RotationOffset; 3389 newRot *= Quaternion.Inverse(axRot);
3216 Quaternion newRot = primsRot * oldParentRot; 3390 prim.RotationOffset = newRot;
3217 newRot *= Quaternion.Inverse(axRot); 3391 prim.ScheduleTerseUpdate();
3218 prim.RotationOffset = newRot;
3219 prim.ScheduleTerseUpdate();
3220 }
3221 } 3392 }
3222 } 3393 }
3394
3223 foreach (SceneObjectPart childpart in Children.Values) 3395 foreach (SceneObjectPart childpart in Children.Values)
3224 { 3396 {
3225 if (childpart != m_rootPart) 3397 if (childpart != m_rootPart)
@@ -3228,6 +3400,9 @@ namespace OpenSim.Region.Framework.Scenes
3228 childpart.StoreUndoState(); 3400 childpart.StoreUndoState();
3229 } 3401 }
3230 } 3402 }
3403
3404 lockPartsForRead(false);
3405
3231 m_rootPart.ScheduleTerseUpdate(); 3406 m_rootPart.ScheduleTerseUpdate();
3232 } 3407 }
3233 3408
@@ -3349,7 +3524,7 @@ namespace OpenSim.Region.Framework.Scenes
3349 if (atTargets.Count > 0) 3524 if (atTargets.Count > 0)
3350 { 3525 {
3351 uint[] localids = new uint[0]; 3526 uint[] localids = new uint[0];
3352 lock (m_parts) 3527 lockPartsForRead(true);
3353 { 3528 {
3354 localids = new uint[m_parts.Count]; 3529 localids = new uint[m_parts.Count];
3355 int cntr = 0; 3530 int cntr = 0;
@@ -3359,6 +3534,7 @@ namespace OpenSim.Region.Framework.Scenes
3359 cntr++; 3534 cntr++;
3360 } 3535 }
3361 } 3536 }
3537 lockPartsForRead(false);
3362 3538
3363 for (int ctr = 0; ctr < localids.Length; ctr++) 3539 for (int ctr = 0; ctr < localids.Length; ctr++)
3364 { 3540 {
@@ -3377,7 +3553,7 @@ namespace OpenSim.Region.Framework.Scenes
3377 { 3553 {
3378 //trigger not_at_target 3554 //trigger not_at_target
3379 uint[] localids = new uint[0]; 3555 uint[] localids = new uint[0];
3380 lock (m_parts) 3556 lockPartsForRead(true);
3381 { 3557 {
3382 localids = new uint[m_parts.Count]; 3558 localids = new uint[m_parts.Count];
3383 int cntr = 0; 3559 int cntr = 0;
@@ -3387,7 +3563,8 @@ namespace OpenSim.Region.Framework.Scenes
3387 cntr++; 3563 cntr++;
3388 } 3564 }
3389 } 3565 }
3390 3566 lockPartsForRead(false);
3567
3391 for (int ctr = 0; ctr < localids.Length; ctr++) 3568 for (int ctr = 0; ctr < localids.Length; ctr++)
3392 { 3569 {
3393 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]); 3570 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]);
@@ -3479,19 +3656,20 @@ namespace OpenSim.Region.Framework.Scenes
3479 public float GetMass() 3656 public float GetMass()
3480 { 3657 {
3481 float retmass = 0f; 3658 float retmass = 0f;
3482 lock (m_parts) 3659 lockPartsForRead(true);
3483 { 3660 {
3484 foreach (SceneObjectPart part in m_parts.Values) 3661 foreach (SceneObjectPart part in m_parts.Values)
3485 { 3662 {
3486 retmass += part.GetMass(); 3663 retmass += part.GetMass();
3487 } 3664 }
3488 } 3665 }
3666 lockPartsForRead(false);
3489 return retmass; 3667 return retmass;
3490 } 3668 }
3491 3669
3492 public void CheckSculptAndLoad() 3670 public void CheckSculptAndLoad()
3493 { 3671 {
3494 lock (m_parts) 3672 lockPartsForRead(true);
3495 { 3673 {
3496 if (!IsDeleted) 3674 if (!IsDeleted)
3497 { 3675 {
@@ -3516,6 +3694,7 @@ namespace OpenSim.Region.Framework.Scenes
3516 } 3694 }
3517 } 3695 }
3518 } 3696 }
3697 lockPartsForRead(false);
3519 } 3698 }
3520 3699
3521 protected void AssetReceived(string id, Object sender, AssetBase asset) 3700 protected void AssetReceived(string id, Object sender, AssetBase asset)
@@ -3536,7 +3715,7 @@ namespace OpenSim.Region.Framework.Scenes
3536 /// <param name="client"></param> 3715 /// <param name="client"></param>
3537 public void SetGroup(UUID GroupID, IClientAPI client) 3716 public void SetGroup(UUID GroupID, IClientAPI client)
3538 { 3717 {
3539 lock (m_parts) 3718 lockPartsForRead(true);
3540 { 3719 {
3541 foreach (SceneObjectPart part in m_parts.Values) 3720 foreach (SceneObjectPart part in m_parts.Values)
3542 { 3721 {
@@ -3546,6 +3725,7 @@ namespace OpenSim.Region.Framework.Scenes
3546 3725
3547 HasGroupChanged = true; 3726 HasGroupChanged = true;
3548 } 3727 }
3728 lockPartsForRead(false);
3549 3729
3550 // 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
3551 // 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.
@@ -3567,11 +3747,12 @@ namespace OpenSim.Region.Framework.Scenes
3567 3747
3568 public void SetAttachmentPoint(byte point) 3748 public void SetAttachmentPoint(byte point)
3569 { 3749 {
3570 lock (m_parts) 3750 lockPartsForRead(true);
3571 { 3751 {
3572 foreach (SceneObjectPart part in m_parts.Values) 3752 foreach (SceneObjectPart part in m_parts.Values)
3573 part.SetAttachmentPoint(point); 3753 part.SetAttachmentPoint(point);
3574 } 3754 }
3755 lockPartsForRead(false);
3575 } 3756 }
3576 3757
3577 #region ISceneObject 3758 #region ISceneObject