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.cs671
1 files changed, 454 insertions, 217 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 8aefd50..35134d6 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -104,8 +104,78 @@ namespace OpenSim.Region.Framework.Scenes
104 /// since the group's last persistent backup 104 /// since the group's last persistent backup
105 /// </summary> 105 /// </summary>
106 private bool m_hasGroupChanged = false; 106 private bool m_hasGroupChanged = false;
107 private long timeFirstChanged; 107 private long timeFirstChanged = 0;
108 private long timeLastChanged; 108 private long timeLastChanged = 0;
109 private long m_maxPersistTime = 0;
110 private long m_minPersistTime = 0;
111 private Random m_rand;
112
113 private System.Threading.ReaderWriterLockSlim m_partsLock = new System.Threading.ReaderWriterLockSlim();
114
115 public void lockPartsForRead(bool locked)
116 {
117 if (locked)
118 {
119 if (m_partsLock.RecursiveReadCount > 0)
120 {
121 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.");
122 m_partsLock.ExitReadLock();
123 }
124 if (m_partsLock.RecursiveWriteCount > 0)
125 {
126 m_log.Error("[SceneObjectGroup.m_parts] Recursive read lock requested (write lock exists on this thread). This should not happen and means something needs to be fixed.");
127 m_partsLock.ExitWriteLock();
128 }
129
130 while (!m_partsLock.TryEnterReadLock(60000))
131 {
132 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.");
133 if (m_partsLock.IsWriteLockHeld)
134 {
135 m_partsLock = new System.Threading.ReaderWriterLockSlim();
136 }
137 }
138 }
139 else
140 {
141 if (m_partsLock.RecursiveReadCount > 0)
142 {
143 m_partsLock.ExitReadLock();
144 }
145 }
146 }
147 public void lockPartsForWrite(bool locked)
148 {
149 if (locked)
150 {
151 if (m_partsLock.RecursiveReadCount > 0)
152 {
153 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.");
154 m_partsLock.ExitReadLock();
155 }
156 if (m_partsLock.RecursiveWriteCount > 0)
157 {
158 m_log.Error("[SceneObjectGroup.m_parts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
159 m_partsLock.ExitWriteLock();
160 }
161
162 while (!m_partsLock.TryEnterWriteLock(60000))
163 {
164 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.");
165 if (m_partsLock.IsWriteLockHeld)
166 {
167 m_partsLock = new System.Threading.ReaderWriterLockSlim();
168 }
169 }
170 }
171 else
172 {
173 if (m_partsLock.RecursiveWriteCount > 0)
174 {
175 m_partsLock.ExitWriteLock();
176 }
177 }
178 }
109 179
110 public bool HasGroupChanged 180 public bool HasGroupChanged
111 { 181 {
@@ -116,6 +186,32 @@ namespace OpenSim.Region.Framework.Scenes
116 timeLastChanged = DateTime.Now.Ticks; 186 timeLastChanged = DateTime.Now.Ticks;
117 if (!m_hasGroupChanged) 187 if (!m_hasGroupChanged)
118 timeFirstChanged = DateTime.Now.Ticks; 188 timeFirstChanged = DateTime.Now.Ticks;
189 if (m_rootPart != null && m_rootPart.UUID != null && m_scene != null)
190 {
191 if (m_rand == null)
192 {
193 byte[] val = new byte[16];
194 m_rootPart.UUID.ToBytes(val, 0);
195 m_rand = new Random(BitConverter.ToInt32(val, 0));
196 }
197
198 if (m_scene.GetRootAgentCount() == 0)
199 {
200 //If the region is empty, this change has been made by an automated process
201 //and thus we delay the persist time by a random amount between 1.5 and 2.5.
202
203 float factor = 1.5f + (float)(m_rand.NextDouble());
204 m_maxPersistTime = (long)((float)m_scene.m_persistAfter * factor);
205 m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * factor);
206 }
207 else
208 {
209 //If the region is not empty, we want to obey the minimum and maximum persist times
210 //but add a random factor so we stagger the object persistance a little
211 m_maxPersistTime = (long)((float)m_scene.m_persistAfter * (1.0d - (m_rand.NextDouble() / 5.0d))); //Multiply by 1.0-1.5
212 m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * (1.0d + (m_rand.NextDouble() / 2.0d))); //Multiply by 0.8-1.0
213 }
214 }
119 } 215 }
120 m_hasGroupChanged = value; 216 m_hasGroupChanged = value;
121 } 217 }
@@ -131,8 +227,19 @@ namespace OpenSim.Region.Framework.Scenes
131 return false; 227 return false;
132 if (m_scene.ShuttingDown) 228 if (m_scene.ShuttingDown)
133 return true; 229 return true;
230
231 if (m_minPersistTime == 0 || m_maxPersistTime == 0)
232 {
233 m_maxPersistTime = m_scene.m_persistAfter;
234 m_minPersistTime = m_scene.m_dontPersistBefore;
235 }
236
134 long currentTime = DateTime.Now.Ticks; 237 long currentTime = DateTime.Now.Ticks;
135 if (currentTime - timeLastChanged > m_scene.m_dontPersistBefore || currentTime - timeFirstChanged > m_scene.m_persistAfter) 238
239 if (timeLastChanged == 0) timeLastChanged = currentTime;
240 if (timeFirstChanged == 0) timeFirstChanged = currentTime;
241
242 if (currentTime - timeLastChanged > m_minPersistTime || currentTime - timeFirstChanged > m_maxPersistTime)
136 return true; 243 return true;
137 return false; 244 return false;
138 } 245 }
@@ -258,13 +365,16 @@ namespace OpenSim.Region.Framework.Scenes
258 set 365 set
259 { 366 {
260 m_regionHandle = value; 367 m_regionHandle = value;
261 lock (m_parts) 368 lockPartsForRead(true);
262 { 369 {
263 foreach (SceneObjectPart part in m_parts.Values) 370 foreach (SceneObjectPart part in m_parts.Values)
264 { 371 {
372
265 part.RegionHandle = m_regionHandle; 373 part.RegionHandle = m_regionHandle;
374
266 } 375 }
267 } 376 }
377 lockPartsForRead(false);
268 } 378 }
269 } 379 }
270 380
@@ -298,6 +408,9 @@ namespace OpenSim.Region.Framework.Scenes
298 { 408 {
299 m_scene.CrossPrimGroupIntoNewRegion(val, this, true); 409 m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
300 } 410 }
411
412 lockPartsForRead(true);
413
301 if (RootPart.GetStatusSandbox()) 414 if (RootPart.GetStatusSandbox())
302 { 415 {
303 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) 416 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10)
@@ -305,17 +418,18 @@ namespace OpenSim.Region.Framework.Scenes
305 RootPart.ScriptSetPhysicsStatus(false); 418 RootPart.ScriptSetPhysicsStatus(false);
306 Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"), 419 Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"),
307 ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false); 420 ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false);
421 lockPartsForRead(false);
308 return; 422 return;
309 } 423 }
310 } 424 }
311 lock (m_parts) 425
426 foreach (SceneObjectPart part in m_parts.Values)
312 { 427 {
313 foreach (SceneObjectPart part in m_parts.Values) 428 part.GroupPosition = val;
314 {
315 part.GroupPosition = val;
316 }
317 } 429 }
318 430
431 lockPartsForRead(false);
432
319 //if (m_rootPart.PhysActor != null) 433 //if (m_rootPart.PhysActor != null)
320 //{ 434 //{
321 //m_rootPart.PhysActor.Position = 435 //m_rootPart.PhysActor.Position =
@@ -457,6 +571,7 @@ namespace OpenSim.Region.Framework.Scenes
457 /// </summary> 571 /// </summary>
458 public SceneObjectGroup() 572 public SceneObjectGroup()
459 { 573 {
574
460 } 575 }
461 576
462 /// <summary> 577 /// <summary>
@@ -473,7 +588,7 @@ namespace OpenSim.Region.Framework.Scenes
473 /// Constructor. This object is added to the scene later via AttachToScene() 588 /// Constructor. This object is added to the scene later via AttachToScene()
474 /// </summary> 589 /// </summary>
475 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) 590 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape)
476 { 591 {
477 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero)); 592 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero));
478 } 593 }
479 594
@@ -504,13 +619,16 @@ namespace OpenSim.Region.Framework.Scenes
504 619
505 public void SetFromItemID(UUID AssetId) 620 public void SetFromItemID(UUID AssetId)
506 { 621 {
507 lock (m_parts) 622 lockPartsForRead(true);
508 { 623 {
509 foreach (SceneObjectPart part in m_parts.Values) 624 foreach (SceneObjectPart part in m_parts.Values)
510 { 625 {
626
511 part.FromItemID = AssetId; 627 part.FromItemID = AssetId;
628
512 } 629 }
513 } 630 }
631 lockPartsForRead(false);
514 } 632 }
515 633
516 public UUID GetFromItemID() 634 public UUID GetFromItemID()
@@ -579,10 +697,11 @@ namespace OpenSim.Region.Framework.Scenes
579 Vector3 maxScale = Vector3.Zero; 697 Vector3 maxScale = Vector3.Zero;
580 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f); 698 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f);
581 699
582 lock (m_parts) 700 lockPartsForRead(true);
583 { 701 {
584 foreach (SceneObjectPart part in m_parts.Values) 702 foreach (SceneObjectPart part in m_parts.Values)
585 { 703 {
704
586 Vector3 partscale = part.Scale; 705 Vector3 partscale = part.Scale;
587 Vector3 partoffset = part.OffsetPosition; 706 Vector3 partoffset = part.OffsetPosition;
588 707
@@ -593,8 +712,11 @@ namespace OpenSim.Region.Framework.Scenes
593 maxScale.X = (partscale.X + partoffset.X > maxScale.X) ? partscale.X + partoffset.X : maxScale.X; 712 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; 713 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; 714 maxScale.Z = (partscale.Z + partoffset.Z > maxScale.Z) ? partscale.Z + partoffset.Z : maxScale.Z;
715
596 } 716 }
597 } 717 }
718 lockPartsForRead(false);
719
598 finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X; 720 finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X;
599 finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y; 721 finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y;
600 finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z; 722 finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z;
@@ -610,10 +732,11 @@ namespace OpenSim.Region.Framework.Scenes
610 732
611 EntityIntersection result = new EntityIntersection(); 733 EntityIntersection result = new EntityIntersection();
612 734
613 lock (m_parts) 735 lockPartsForRead(true);
614 { 736 {
615 foreach (SceneObjectPart part in m_parts.Values) 737 foreach (SceneObjectPart part in m_parts.Values)
616 { 738 {
739
617 // Temporary commented to stop compiler warning 740 // Temporary commented to stop compiler warning
618 //Vector3 partPosition = 741 //Vector3 partPosition =
619 // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z); 742 // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z);
@@ -641,8 +764,10 @@ namespace OpenSim.Region.Framework.Scenes
641 result.distance = inter.distance; 764 result.distance = inter.distance;
642 } 765 }
643 } 766 }
767
644 } 768 }
645 } 769 }
770 lockPartsForRead(false);
646 return result; 771 return result;
647 } 772 }
648 773
@@ -655,10 +780,11 @@ namespace OpenSim.Region.Framework.Scenes
655 public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight) 780 public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight)
656 { 781 {
657 float maxX = -256f, maxY = -256f, maxZ = -256f, minX = 256f, minY = 256f, minZ = 256f; 782 float maxX = -256f, maxY = -256f, maxZ = -256f, minX = 256f, minY = 256f, minZ = 256f;
658 lock (m_parts) 783 lockPartsForRead(true);
659 { 784 {
660 foreach (SceneObjectPart part in m_parts.Values) 785 foreach (SceneObjectPart part in m_parts.Values)
661 { 786 {
787
662 Vector3 worldPos = part.GetWorldPosition(); 788 Vector3 worldPos = part.GetWorldPosition();
663 Vector3 offset = worldPos - AbsolutePosition; 789 Vector3 offset = worldPos - AbsolutePosition;
664 Quaternion worldRot; 790 Quaternion worldRot;
@@ -717,6 +843,8 @@ namespace OpenSim.Region.Framework.Scenes
717 backBottomRight.Y = orig.Y + (part.Scale.Y / 2); 843 backBottomRight.Y = orig.Y + (part.Scale.Y / 2);
718 backBottomRight.Z = orig.Z - (part.Scale.Z / 2); 844 backBottomRight.Z = orig.Z - (part.Scale.Z / 2);
719 845
846
847
720 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z); 848 //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); 849 //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); 850 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
@@ -888,6 +1016,7 @@ namespace OpenSim.Region.Framework.Scenes
888 minZ = backBottomLeft.Z; 1016 minZ = backBottomLeft.Z;
889 } 1017 }
890 } 1018 }
1019 lockPartsForRead(false);
891 1020
892 Vector3 boundingBox = new Vector3(maxX - minX, maxY - minY, maxZ - minZ); 1021 Vector3 boundingBox = new Vector3(maxX - minX, maxY - minY, maxZ - minZ);
893 1022
@@ -912,21 +1041,29 @@ namespace OpenSim.Region.Framework.Scenes
912 1041
913 public void SaveScriptedState(XmlTextWriter writer) 1042 public void SaveScriptedState(XmlTextWriter writer)
914 { 1043 {
1044 SaveScriptedState(writer, false);
1045 }
1046
1047 public void SaveScriptedState(XmlTextWriter writer, bool oldIDs)
1048 {
915 XmlDocument doc = new XmlDocument(); 1049 XmlDocument doc = new XmlDocument();
916 Dictionary<UUID,string> states = new Dictionary<UUID,string>(); 1050 Dictionary<UUID,string> states = new Dictionary<UUID,string>();
917 1051
918 // Capture script state while holding the lock 1052 // Capture script state while holding the lock
919 lock (m_parts) 1053 lockPartsForRead(true);
920 { 1054 {
921 foreach (SceneObjectPart part in m_parts.Values) 1055 foreach (SceneObjectPart part in m_parts.Values)
922 { 1056 {
923 Dictionary<UUID,string> pstates = part.Inventory.GetScriptStates(); 1057
1058 Dictionary<UUID,string> pstates = part.Inventory.GetScriptStates(oldIDs);
924 foreach (UUID itemid in pstates.Keys) 1059 foreach (UUID itemid in pstates.Keys)
925 { 1060 {
926 states.Add(itemid, pstates[itemid]); 1061 states.Add(itemid, pstates[itemid]);
927 } 1062 }
1063
928 } 1064 }
929 } 1065 }
1066 lockPartsForRead(false);
930 1067
931 if (states.Count > 0) 1068 if (states.Count > 0)
932 { 1069 {
@@ -1094,13 +1231,16 @@ namespace OpenSim.Region.Framework.Scenes
1094 1231
1095 public override void UpdateMovement() 1232 public override void UpdateMovement()
1096 { 1233 {
1097 lock (m_parts) 1234 lockPartsForRead(true);
1098 { 1235 {
1099 foreach (SceneObjectPart part in m_parts.Values) 1236 foreach (SceneObjectPart part in m_parts.Values)
1100 { 1237 {
1238
1101 part.UpdateMovement(); 1239 part.UpdateMovement();
1240
1102 } 1241 }
1103 } 1242 }
1243 lockPartsForRead(false);
1104 } 1244 }
1105 1245
1106 public ushort GetTimeDilation() 1246 public ushort GetTimeDilation()
@@ -1144,7 +1284,7 @@ namespace OpenSim.Region.Framework.Scenes
1144 /// <param name="part"></param> 1284 /// <param name="part"></param>
1145 public void AddPart(SceneObjectPart part) 1285 public void AddPart(SceneObjectPart part)
1146 { 1286 {
1147 lock (m_parts) 1287 lockPartsForWrite(true);
1148 { 1288 {
1149 part.SetParent(this); 1289 part.SetParent(this);
1150 m_parts.Add(part.UUID, part); 1290 m_parts.Add(part.UUID, part);
@@ -1154,6 +1294,7 @@ namespace OpenSim.Region.Framework.Scenes
1154 if (part.LinkNum == 2 && RootPart != null) 1294 if (part.LinkNum == 2 && RootPart != null)
1155 RootPart.LinkNum = 1; 1295 RootPart.LinkNum = 1;
1156 } 1296 }
1297 lockPartsForWrite(false);
1157 } 1298 }
1158 1299
1159 /// <summary> 1300 /// <summary>
@@ -1161,28 +1302,33 @@ namespace OpenSim.Region.Framework.Scenes
1161 /// </summary> 1302 /// </summary>
1162 private void UpdateParentIDs() 1303 private void UpdateParentIDs()
1163 { 1304 {
1164 lock (m_parts) 1305 lockPartsForRead(true);
1165 { 1306 {
1166 foreach (SceneObjectPart part in m_parts.Values) 1307 foreach (SceneObjectPart part in m_parts.Values)
1167 { 1308 {
1309
1168 if (part.UUID != m_rootPart.UUID) 1310 if (part.UUID != m_rootPart.UUID)
1169 { 1311 {
1170 part.ParentID = m_rootPart.LocalId; 1312 part.ParentID = m_rootPart.LocalId;
1171 } 1313 }
1314
1172 } 1315 }
1173 } 1316 }
1317 lockPartsForRead(false);
1174 } 1318 }
1175 1319
1176 public void RegenerateFullIDs() 1320 public void RegenerateFullIDs()
1177 { 1321 {
1178 lock (m_parts) 1322 lockPartsForRead(true);
1179 { 1323 {
1180 foreach (SceneObjectPart part in m_parts.Values) 1324 foreach (SceneObjectPart part in m_parts.Values)
1181 { 1325 {
1326
1182 part.UUID = UUID.Random(); 1327 part.UUID = UUID.Random();
1183 1328
1184 } 1329 }
1185 } 1330 }
1331 lockPartsForRead(false);
1186 } 1332 }
1187 1333
1188 // helper provided for parts. 1334 // helper provided for parts.
@@ -1263,27 +1409,32 @@ namespace OpenSim.Region.Framework.Scenes
1263 1409
1264 DetachFromBackup(); 1410 DetachFromBackup();
1265 1411
1266 lock (m_parts) 1412 lockPartsForRead(true);
1413 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1414 lockPartsForRead(false);
1415
1416 foreach (SceneObjectPart part in values)
1267 { 1417 {
1268 foreach (SceneObjectPart part in m_parts.Values)
1269 {
1270// part.Inventory.RemoveScriptInstances(); 1418// part.Inventory.RemoveScriptInstances();
1271 Scene.ForEachScenePresence(delegate(ScenePresence avatar) 1419
1420 Scene.ForEachScenePresence(delegate (ScenePresence sp)
1421 {
1422 if (sp.ParentID == LocalId)
1272 { 1423 {
1273 if (avatar.ParentID == LocalId) 1424 sp.StandUp();
1274 { 1425 }
1275 avatar.StandUp();
1276 }
1277 1426
1278 if (!silent) 1427 if (!silent)
1279 { 1428 {
1280 part.UpdateFlag = 0; 1429 part.UpdateFlag = 0;
1281 if (part == m_rootPart) 1430 if (part == m_rootPart)
1282 avatar.ControllingClient.SendKillObject(m_regionHandle, part.LocalId); 1431 sp.ControllingClient.SendKillObject(m_regionHandle, part.LocalId);
1283 } 1432 }
1284 }); 1433 });
1285 } 1434
1286 } 1435 }
1436
1437
1287 } 1438 }
1288 1439
1289 public void AddScriptLPS(int count) 1440 public void AddScriptLPS(int count)
@@ -1308,17 +1459,20 @@ namespace OpenSim.Region.Framework.Scenes
1308 1459
1309 scriptEvents aggregateScriptEvents=0; 1460 scriptEvents aggregateScriptEvents=0;
1310 1461
1311 lock (m_parts) 1462 lockPartsForRead(true);
1312 { 1463 {
1313 foreach (SceneObjectPart part in m_parts.Values) 1464 foreach (SceneObjectPart part in m_parts.Values)
1314 { 1465 {
1466
1315 if (part == null) 1467 if (part == null)
1316 continue; 1468 continue;
1317 if (part != RootPart) 1469 if (part != RootPart)
1318 part.ObjectFlags = objectflagupdate; 1470 part.ObjectFlags = objectflagupdate;
1319 aggregateScriptEvents |= part.AggregateScriptEvents; 1471 aggregateScriptEvents |= part.AggregateScriptEvents;
1472
1320 } 1473 }
1321 } 1474 }
1475 lockPartsForRead(false);
1322 1476
1323 m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0); 1477 m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0);
1324 m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0); 1478 m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0);
@@ -1360,42 +1514,52 @@ namespace OpenSim.Region.Framework.Scenes
1360 /// <param name="m_physicalPrim"></param> 1514 /// <param name="m_physicalPrim"></param>
1361 public void ApplyPhysics(bool m_physicalPrim) 1515 public void ApplyPhysics(bool m_physicalPrim)
1362 { 1516 {
1363 lock (m_parts) 1517 lockPartsForRead(true);
1518
1519 if (m_parts.Count > 1)
1364 { 1520 {
1365 if (m_parts.Count > 1) 1521 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1522 lockPartsForRead(false);
1523 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1524 foreach (SceneObjectPart part in values)
1366 { 1525 {
1367 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim); 1526
1368 foreach (SceneObjectPart part in m_parts.Values) 1527 if (part.LocalId != m_rootPart.LocalId)
1369 { 1528 {
1370 if (part.LocalId != m_rootPart.LocalId) 1529 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim);
1371 {
1372 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim);
1373 }
1374 } 1530 }
1375 1531
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 } 1532 }
1533 // Hack to get the physics scene geometries in the right spot
1534 ResetChildPrimPhysicsPositions();
1535 }
1536 else
1537 {
1538 lockPartsForRead(false);
1539 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1383 } 1540 }
1384 } 1541 }
1385 1542
1386 public void SetOwnerId(UUID userId) 1543 public void SetOwnerId(UUID userId)
1387 { 1544 {
1388 ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); 1545 ForEachPart(delegate(SceneObjectPart part)
1546 {
1547
1548 part.OwnerID = userId;
1549
1550 });
1389 } 1551 }
1390 1552
1391 public void ForEachPart(Action<SceneObjectPart> whatToDo) 1553 public void ForEachPart(Action<SceneObjectPart> whatToDo)
1392 { 1554 {
1393 lock (m_parts) 1555 lockPartsForRead(true);
1556 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1557 lockPartsForRead(false);
1558 foreach (SceneObjectPart part in values)
1394 { 1559 {
1395 foreach (SceneObjectPart part in m_parts.Values) 1560
1396 { 1561 whatToDo(part);
1397 whatToDo(part); 1562
1398 }
1399 } 1563 }
1400 } 1564 }
1401 1565
@@ -1493,15 +1657,17 @@ namespace OpenSim.Region.Framework.Scenes
1493 RootPart.SendFullUpdate( 1657 RootPart.SendFullUpdate(
1494 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID)); 1658 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID));
1495 1659
1496 lock (m_parts) 1660 lockPartsForRead(true);
1497 { 1661 {
1498 foreach (SceneObjectPart part in m_parts.Values) 1662 foreach (SceneObjectPart part in m_parts.Values)
1499 { 1663 {
1664
1500 if (part != RootPart) 1665 if (part != RootPart)
1501 part.SendFullUpdate( 1666 part.SendFullUpdate(
1502 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID)); 1667 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID));
1503 } 1668 }
1504 } 1669 }
1670 lockPartsForRead(false);
1505 } 1671 }
1506 1672
1507 #region Copying 1673 #region Copying
@@ -1570,10 +1736,11 @@ namespace OpenSim.Region.Framework.Scenes
1570 1736
1571 List<SceneObjectPart> partList; 1737 List<SceneObjectPart> partList;
1572 1738
1573 lock (m_parts) 1739 lockPartsForRead(true);
1574 { 1740
1575 partList = new List<SceneObjectPart>(m_parts.Values); 1741 partList = new List<SceneObjectPart>(m_parts.Values);
1576 } 1742
1743 lockPartsForRead(false);
1577 1744
1578 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) 1745 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1579 { 1746 {
@@ -1796,13 +1963,40 @@ namespace OpenSim.Region.Framework.Scenes
1796 } 1963 }
1797 } 1964 }
1798 1965
1966 public void rotLookAt(Quaternion target, float strength, float damping)
1967 {
1968 SceneObjectPart rootpart = m_rootPart;
1969 if (rootpart != null)
1970 {
1971 if (IsAttachment)
1972 {
1973 /*
1974 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
1975 if (avatar != null)
1976 {
1977 Rotate the Av?
1978 } */
1979 }
1980 else
1981 {
1982 if (rootpart.PhysActor != null)
1983 { // APID must be implemented in your physics system for this to function.
1984 rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W);
1985 rootpart.PhysActor.APIDStrength = strength;
1986 rootpart.PhysActor.APIDDamping = damping;
1987 rootpart.PhysActor.APIDActive = true;
1988 }
1989 }
1990 }
1991 }
1992
1799 public void stopLookAt() 1993 public void stopLookAt()
1800 { 1994 {
1801 SceneObjectPart rootpart = m_rootPart; 1995 SceneObjectPart rootpart = m_rootPart;
1802 if (rootpart != null) 1996 if (rootpart != null)
1803 { 1997 {
1804 if (rootpart.PhysActor != null) 1998 if (rootpart.PhysActor != null)
1805 { 1999 { // APID must be implemented in your physics system for this to function.
1806 rootpart.PhysActor.APIDActive = false; 2000 rootpart.PhysActor.APIDActive = false;
1807 } 2001 }
1808 } 2002 }
@@ -1870,10 +2064,11 @@ namespace OpenSim.Region.Framework.Scenes
1870 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 2064 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
1871 newPart.SetParent(this); 2065 newPart.SetParent(this);
1872 2066
1873 lock (m_parts) 2067 lockPartsForWrite(true);
1874 { 2068 {
1875 m_parts.Add(newPart.UUID, newPart); 2069 m_parts.Add(newPart.UUID, newPart);
1876 } 2070 }
2071 lockPartsForWrite(false);
1877 2072
1878 SetPartAsNonRoot(newPart); 2073 SetPartAsNonRoot(newPart);
1879 2074
@@ -1936,7 +2131,7 @@ namespace OpenSim.Region.Framework.Scenes
1936 //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0) 2131 //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
1937 // return; 2132 // return;
1938 2133
1939 lock (m_parts) 2134 lockPartsForRead(true);
1940 { 2135 {
1941 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0); 2136 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0);
1942 2137
@@ -1956,9 +2151,12 @@ namespace OpenSim.Region.Framework.Scenes
1956 { 2151 {
1957 if (!IsSelected) 2152 if (!IsSelected)
1958 part.UpdateLookAt(); 2153 part.UpdateLookAt();
2154
1959 part.SendScheduledUpdates(); 2155 part.SendScheduledUpdates();
2156
1960 } 2157 }
1961 } 2158 }
2159 lockPartsForRead(false);
1962 } 2160 }
1963 2161
1964 public void ScheduleFullUpdateToAvatar(ScenePresence presence) 2162 public void ScheduleFullUpdateToAvatar(ScenePresence presence)
@@ -1967,27 +2165,29 @@ namespace OpenSim.Region.Framework.Scenes
1967 2165
1968 RootPart.AddFullUpdateToAvatar(presence); 2166 RootPart.AddFullUpdateToAvatar(presence);
1969 2167
1970 lock (m_parts) 2168 lockPartsForRead(true);
1971 { 2169 {
1972 foreach (SceneObjectPart part in m_parts.Values) 2170 foreach (SceneObjectPart part in m_parts.Values)
1973 { 2171 {
2172
1974 if (part != RootPart) 2173 if (part != RootPart)
1975 part.AddFullUpdateToAvatar(presence); 2174 part.AddFullUpdateToAvatar(presence);
2175
1976 } 2176 }
1977 } 2177 }
2178 lockPartsForRead(false);
1978 } 2179 }
1979 2180
1980 public void ScheduleTerseUpdateToAvatar(ScenePresence presence) 2181 public void ScheduleTerseUpdateToAvatar(ScenePresence presence)
1981 { 2182 {
1982// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1} just to avatar {2}", Name, UUID, presence.Name); 2183 lockPartsForRead(true);
1983 2184
1984 lock (m_parts) 2185 foreach (SceneObjectPart part in m_parts.Values)
1985 { 2186 {
1986 foreach (SceneObjectPart part in m_parts.Values) 2187 part.AddTerseUpdateToAvatar(presence);
1987 {
1988 part.AddTerseUpdateToAvatar(presence);
1989 }
1990 } 2188 }
2189
2190 lockPartsForRead(false);
1991 } 2191 }
1992 2192
1993 /// <summary> 2193 /// <summary>
@@ -2000,14 +2200,17 @@ namespace OpenSim.Region.Framework.Scenes
2000 checkAtTargets(); 2200 checkAtTargets();
2001 RootPart.ScheduleFullUpdate(); 2201 RootPart.ScheduleFullUpdate();
2002 2202
2003 lock (m_parts) 2203 lockPartsForRead(true);
2004 { 2204 {
2005 foreach (SceneObjectPart part in m_parts.Values) 2205 foreach (SceneObjectPart part in m_parts.Values)
2006 { 2206 {
2207
2007 if (part != RootPart) 2208 if (part != RootPart)
2008 part.ScheduleFullUpdate(); 2209 part.ScheduleFullUpdate();
2210
2009 } 2211 }
2010 } 2212 }
2213 lockPartsForRead(false);
2011 } 2214 }
2012 2215
2013 /// <summary> 2216 /// <summary>
@@ -2015,37 +2218,38 @@ namespace OpenSim.Region.Framework.Scenes
2015 /// </summary> 2218 /// </summary>
2016 public void ScheduleGroupForTerseUpdate() 2219 public void ScheduleGroupForTerseUpdate()
2017 { 2220 {
2018// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1}", Name, UUID); 2221 lockPartsForRead(true);
2019 2222 foreach (SceneObjectPart part in m_parts.Values)
2020 lock (m_parts)
2021 { 2223 {
2022 foreach (SceneObjectPart part in m_parts.Values) 2224 part.ScheduleTerseUpdate();
2023 {
2024 part.ScheduleTerseUpdate();
2025 }
2026 } 2225 }
2226
2227 lockPartsForRead(false);
2027 } 2228 }
2028 2229
2029 /// <summary> 2230 /// <summary>
2030 /// Immediately send a full update for this scene object. 2231 /// Immediately send a full update for this scene object.
2031 /// </summary> 2232 /// </summary>
2032 public void SendGroupFullUpdate() 2233 public void SendGroupFullUpdate()
2033 { 2234 {
2034 if (IsDeleted) 2235 if (IsDeleted)
2035 return; 2236 return;
2036 2237
2037// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); 2238// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID);
2038 2239
2039 RootPart.SendFullUpdateToAllClients(); 2240 RootPart.SendFullUpdateToAllClients();
2040 2241
2041 lock (m_parts) 2242 lockPartsForRead(true);
2042 { 2243 {
2043 foreach (SceneObjectPart part in m_parts.Values) 2244 foreach (SceneObjectPart part in m_parts.Values)
2044 { 2245 {
2246
2045 if (part != RootPart) 2247 if (part != RootPart)
2046 part.SendFullUpdateToAllClients(); 2248 part.SendFullUpdateToAllClients();
2249
2047 } 2250 }
2048 } 2251 }
2252 lockPartsForRead(false);
2049 } 2253 }
2050 2254
2051 /// <summary> 2255 /// <summary>
@@ -2077,14 +2281,15 @@ namespace OpenSim.Region.Framework.Scenes
2077 { 2281 {
2078 if (IsDeleted) 2282 if (IsDeleted)
2079 return; 2283 return;
2080 2284
2081 lock (m_parts) 2285 lockPartsForRead(true);
2082 { 2286 {
2083 foreach (SceneObjectPart part in m_parts.Values) 2287 foreach (SceneObjectPart part in m_parts.Values)
2084 { 2288 {
2085 part.SendTerseUpdateToAllClients(); 2289 part.SendTerseUpdateToAllClients();
2086 } 2290 }
2087 } 2291 }
2292 lockPartsForRead(false);
2088 } 2293 }
2089 2294
2090 #endregion 2295 #endregion
@@ -2098,16 +2303,18 @@ namespace OpenSim.Region.Framework.Scenes
2098 /// <returns>null if no child part with that linknum or child part</returns> 2303 /// <returns>null if no child part with that linknum or child part</returns>
2099 public SceneObjectPart GetLinkNumPart(int linknum) 2304 public SceneObjectPart GetLinkNumPart(int linknum)
2100 { 2305 {
2101 lock (m_parts) 2306 lockPartsForRead(true);
2102 { 2307 {
2103 foreach (SceneObjectPart part in m_parts.Values) 2308 foreach (SceneObjectPart part in m_parts.Values)
2104 { 2309 {
2105 if (part.LinkNum == linknum) 2310 if (part.LinkNum == linknum)
2106 { 2311 {
2312 lockPartsForRead(false);
2107 return part; 2313 return part;
2108 } 2314 }
2109 } 2315 }
2110 } 2316 }
2317 lockPartsForRead(false);
2111 2318
2112 return null; 2319 return null;
2113 } 2320 }
@@ -2135,17 +2342,19 @@ namespace OpenSim.Region.Framework.Scenes
2135 public SceneObjectPart GetChildPart(uint localID) 2342 public SceneObjectPart GetChildPart(uint localID)
2136 { 2343 {
2137 //m_log.DebugFormat("Entered looking for {0}", localID); 2344 //m_log.DebugFormat("Entered looking for {0}", localID);
2138 lock (m_parts) 2345 lockPartsForRead(true);
2139 { 2346 {
2140 foreach (SceneObjectPart part in m_parts.Values) 2347 foreach (SceneObjectPart part in m_parts.Values)
2141 { 2348 {
2142 //m_log.DebugFormat("Found {0}", part.LocalId); 2349 //m_log.DebugFormat("Found {0}", part.LocalId);
2143 if (part.LocalId == localID) 2350 if (part.LocalId == localID)
2144 { 2351 {
2352 lockPartsForRead(false);
2145 return part; 2353 return part;
2146 } 2354 }
2147 } 2355 }
2148 } 2356 }
2357 lockPartsForRead(false);
2149 2358
2150 return null; 2359 return null;
2151 } 2360 }
@@ -2175,17 +2384,19 @@ namespace OpenSim.Region.Framework.Scenes
2175 public bool HasChildPrim(uint localID) 2384 public bool HasChildPrim(uint localID)
2176 { 2385 {
2177 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID); 2386 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID);
2178 lock (m_parts) 2387 lockPartsForRead(true);
2179 { 2388 {
2180 foreach (SceneObjectPart part in m_parts.Values) 2389 foreach (SceneObjectPart part in m_parts.Values)
2181 { 2390 {
2182 //m_log.DebugFormat("Found {0}", part.LocalId); 2391 //m_log.DebugFormat("Found {0}", part.LocalId);
2183 if (part.LocalId == localID) 2392 if (part.LocalId == localID)
2184 { 2393 {
2394 lockPartsForRead(false);
2185 return true; 2395 return true;
2186 } 2396 }
2187 } 2397 }
2188 } 2398 }
2399 lockPartsForRead(false);
2189 2400
2190 return false; 2401 return false;
2191 } 2402 }
@@ -2235,53 +2446,57 @@ namespace OpenSim.Region.Framework.Scenes
2235 if (m_rootPart.LinkNum == 0) 2446 if (m_rootPart.LinkNum == 0)
2236 m_rootPart.LinkNum = 1; 2447 m_rootPart.LinkNum = 1;
2237 2448
2238 lock (m_parts) 2449 lockPartsForWrite(true);
2239 { 2450
2240 m_parts.Add(linkPart.UUID, linkPart); 2451 m_parts.Add(linkPart.UUID, linkPart);
2452
2453 lockPartsForWrite(false);
2241 2454
2242 // Insert in terms of link numbers, the new links 2455 // Insert in terms of link numbers, the new links
2243 // before the current ones (with the exception of 2456 // before the current ones (with the exception of
2244 // the root prim. Shuffle the old ones up 2457 // the root prim. Shuffle the old ones up
2245 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts) 2458 lockPartsForRead(true);
2459 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts)
2460 {
2461 if (kvp.Value.LinkNum != 1)
2246 { 2462 {
2247 if (kvp.Value.LinkNum != 1) 2463 // Don't update root prim link number
2248 { 2464 kvp.Value.LinkNum += objectGroup.PrimCount;
2249 // Don't update root prim link number
2250 kvp.Value.LinkNum += objectGroup.PrimCount;
2251 }
2252 } 2465 }
2466 }
2467 lockPartsForRead(false);
2253 2468
2254 linkPart.LinkNum = 2; 2469 linkPart.LinkNum = 2;
2255 2470
2256 linkPart.SetParent(this); 2471 linkPart.SetParent(this);
2257 linkPart.AddFlag(PrimFlags.CreateSelected); 2472 linkPart.AddFlag(PrimFlags.CreateSelected);
2258 2473
2259 //if (linkPart.PhysActor != null) 2474 //if (linkPart.PhysActor != null)
2260 //{ 2475 //{
2261 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); 2476 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor);
2262 2477
2263 //linkPart.PhysActor = null; 2478 //linkPart.PhysActor = null;
2264 //} 2479 //}
2265 2480
2266 //TODO: rest of parts 2481 //TODO: rest of parts
2267 int linkNum = 3; 2482 int linkNum = 3;
2268 foreach (SceneObjectPart part in objectGroup.Children.Values) 2483 foreach (SceneObjectPart part in objectGroup.Children.Values)
2484 {
2485 if (part.UUID != objectGroup.m_rootPart.UUID)
2269 { 2486 {
2270 if (part.UUID != objectGroup.m_rootPart.UUID) 2487 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2271 {
2272 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2273 }
2274 part.ClearUndoState();
2275 } 2488 }
2489 part.ClearUndoState();
2276 } 2490 }
2277 2491
2278 m_scene.UnlinkSceneObject(objectGroup.UUID, true); 2492 m_scene.UnlinkSceneObject(objectGroup.UUID, true);
2279 objectGroup.m_isDeleted = true; 2493 objectGroup.m_isDeleted = true;
2494
2495 objectGroup.lockPartsForWrite(true);
2280 2496
2281 lock (objectGroup.m_parts) 2497 objectGroup.m_parts.Clear();
2282 { 2498
2283 objectGroup.m_parts.Clear(); 2499 objectGroup.lockPartsForWrite(false);
2284 }
2285 2500
2286 // Can't do this yet since backup still makes use of the root part without any synchronization 2501 // Can't do this yet since backup still makes use of the root part without any synchronization
2287// objectGroup.m_rootPart = null; 2502// objectGroup.m_rootPart = null;
@@ -2351,11 +2566,12 @@ namespace OpenSim.Region.Framework.Scenes
2351 Quaternion worldRot = linkPart.GetWorldRotation(); 2566 Quaternion worldRot = linkPart.GetWorldRotation();
2352 2567
2353 // Remove the part from this object 2568 // Remove the part from this object
2354 lock (m_parts) 2569 lockPartsForWrite(true);
2355 { 2570 {
2356 m_parts.Remove(linkPart.UUID); 2571 m_parts.Remove(linkPart.UUID);
2357 } 2572 }
2358 2573 lockPartsForWrite(false);
2574 lockPartsForRead(true);
2359 if (m_parts.Count == 1 && RootPart != null) //Single prim is left 2575 if (m_parts.Count == 1 && RootPart != null) //Single prim is left
2360 RootPart.LinkNum = 0; 2576 RootPart.LinkNum = 0;
2361 else 2577 else
@@ -2366,6 +2582,7 @@ namespace OpenSim.Region.Framework.Scenes
2366 p.LinkNum--; 2582 p.LinkNum--;
2367 } 2583 }
2368 } 2584 }
2585 lockPartsForRead(false);
2369 2586
2370 linkPart.ParentID = 0; 2587 linkPart.ParentID = 0;
2371 linkPart.LinkNum = 0; 2588 linkPart.LinkNum = 0;
@@ -2687,9 +2904,12 @@ namespace OpenSim.Region.Framework.Scenes
2687 2904
2688 if (selectionPart != null) 2905 if (selectionPart != null)
2689 { 2906 {
2690 lock (m_parts) 2907 lockPartsForRead(true);
2908 List<SceneObjectPart> parts = new List<SceneObjectPart>(m_parts.Values);
2909 lockPartsForRead(false);
2910 foreach (SceneObjectPart part in parts)
2691 { 2911 {
2692 foreach (SceneObjectPart part in m_parts.Values) 2912 if (part.Scale.X > 10.0 || part.Scale.Y > 10.0 || part.Scale.Z > 10.0)
2693 { 2913 {
2694 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax || 2914 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax ||
2695 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax || 2915 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax ||
@@ -2699,12 +2919,13 @@ namespace OpenSim.Region.Framework.Scenes
2699 break; 2919 break;
2700 } 2920 }
2701 } 2921 }
2922 }
2702 2923
2703 foreach (SceneObjectPart part in m_parts.Values) 2924 foreach (SceneObjectPart part in parts)
2704 { 2925 {
2705 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect); 2926 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
2706 }
2707 } 2927 }
2928
2708 } 2929 }
2709 } 2930 }
2710 2931
@@ -2790,11 +3011,9 @@ namespace OpenSim.Region.Framework.Scenes
2790 scale.Y = m_scene.m_maxNonphys; 3011 scale.Y = m_scene.m_maxNonphys;
2791 if (scale.Z > m_scene.m_maxNonphys) 3012 if (scale.Z > m_scene.m_maxNonphys)
2792 scale.Z = m_scene.m_maxNonphys; 3013 scale.Z = m_scene.m_maxNonphys;
2793
2794 SceneObjectPart part = GetChildPart(localID); 3014 SceneObjectPart part = GetChildPart(localID);
2795 if (part != null) 3015 if (part != null)
2796 { 3016 {
2797 part.Resize(scale);
2798 if (part.PhysActor != null) 3017 if (part.PhysActor != null)
2799 { 3018 {
2800 if (part.PhysActor.IsPhysical) 3019 if (part.PhysActor.IsPhysical)
@@ -2809,7 +3028,7 @@ namespace OpenSim.Region.Framework.Scenes
2809 part.PhysActor.Size = scale; 3028 part.PhysActor.Size = scale;
2810 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); 3029 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor);
2811 } 3030 }
2812 //if (part.UUID != m_rootPart.UUID) 3031 part.Resize(scale);
2813 3032
2814 HasGroupChanged = true; 3033 HasGroupChanged = true;
2815 ScheduleGroupForFullUpdate(); 3034 ScheduleGroupForFullUpdate();
@@ -2851,73 +3070,71 @@ namespace OpenSim.Region.Framework.Scenes
2851 float y = (scale.Y / part.Scale.Y); 3070 float y = (scale.Y / part.Scale.Y);
2852 float z = (scale.Z / part.Scale.Z); 3071 float z = (scale.Z / part.Scale.Z);
2853 3072
2854 lock (m_parts) 3073 lockPartsForRead(true);
3074 if (x > 1.0f || y > 1.0f || z > 1.0f)
2855 { 3075 {
2856 if (x > 1.0f || y > 1.0f || z > 1.0f) 3076 foreach (SceneObjectPart obPart in m_parts.Values)
2857 { 3077 {
2858 foreach (SceneObjectPart obPart in m_parts.Values) 3078 if (obPart.UUID != m_rootPart.UUID)
2859 { 3079 {
2860 if (obPart.UUID != m_rootPart.UUID) 3080 Vector3 oldSize = new Vector3(obPart.Scale);
2861 { 3081 obPart.IgnoreUndoUpdate = true;
2862 obPart.IgnoreUndoUpdate = true;
2863 Vector3 oldSize = new Vector3(obPart.Scale);
2864 3082
2865 float f = 1.0f; 3083 float f = 1.0f;
2866 float a = 1.0f; 3084 float a = 1.0f;
2867 3085
2868 if (part.PhysActor != null && part.PhysActor.IsPhysical) 3086 if (part.PhysActor != null && part.PhysActor.IsPhysical)
3087 {
3088 if (oldSize.X*x > m_scene.m_maxPhys)
2869 { 3089 {
2870 if (oldSize.X*x > m_scene.m_maxPhys) 3090 f = m_scene.m_maxPhys / oldSize.X;
2871 { 3091 a = f / x;
2872 f = m_scene.m_maxPhys / oldSize.X; 3092 x *= a;
2873 a = f / x; 3093 y *= a;
2874 x *= a; 3094 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 } 3095 }
2895 else 3096 if (oldSize.Y*y > m_scene.m_maxPhys)
3097 {
3098 f = m_scene.m_maxPhys / oldSize.Y;
3099 a = f / y;
3100 x *= a;
3101 y *= a;
3102 z *= a;
3103 }
3104 if (oldSize.Z*z > m_scene.m_maxPhys)
3105 {
3106 f = m_scene.m_maxPhys / oldSize.Z;
3107 a = f / z;
3108 x *= a;
3109 y *= a;
3110 z *= a;
3111 }
3112 }
3113 else
3114 {
3115 if (oldSize.X*x > m_scene.m_maxNonphys)
3116 {
3117 f = m_scene.m_maxNonphys / oldSize.X;
3118 a = f / x;
3119 x *= a;
3120 y *= a;
3121 z *= a;
3122 }
3123 if (oldSize.Y*y > m_scene.m_maxNonphys)
3124 {
3125 f = m_scene.m_maxNonphys / oldSize.Y;
3126 a = f / y;
3127 x *= a;
3128 y *= a;
3129 z *= a;
3130 }
3131 if (oldSize.Z*z > m_scene.m_maxNonphys)
2896 { 3132 {
2897 if (oldSize.X*x > m_scene.m_maxNonphys) 3133 f = m_scene.m_maxNonphys / oldSize.Z;
2898 { 3134 a = f / z;
2899 f = m_scene.m_maxNonphys / oldSize.X; 3135 x *= a;
2900 a = f / x; 3136 y *= a;
2901 x *= a; 3137 z *= a;
2902 y *= a;
2903 z *= a;
2904 }
2905 if (oldSize.Y*y > m_scene.m_maxNonphys)
2906 {
2907 f = m_scene.m_maxNonphys / oldSize.Y;
2908 a = f / y;
2909 x *= 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 } 3138 }
2922 obPart.IgnoreUndoUpdate = false; 3139 obPart.IgnoreUndoUpdate = false;
2923 obPart.StoreUndoState(); 3140 obPart.StoreUndoState();
@@ -2925,6 +3142,7 @@ namespace OpenSim.Region.Framework.Scenes
2925 } 3142 }
2926 } 3143 }
2927 } 3144 }
3145 lockPartsForRead(false);
2928 3146
2929 Vector3 prevScale = part.Scale; 3147 Vector3 prevScale = part.Scale;
2930 prevScale.X *= x; 3148 prevScale.X *= x;
@@ -2932,7 +3150,7 @@ namespace OpenSim.Region.Framework.Scenes
2932 prevScale.Z *= z; 3150 prevScale.Z *= z;
2933 part.Resize(prevScale); 3151 part.Resize(prevScale);
2934 3152
2935 lock (m_parts) 3153 lockPartsForRead(true);
2936 { 3154 {
2937 foreach (SceneObjectPart obPart in m_parts.Values) 3155 foreach (SceneObjectPart obPart in m_parts.Values)
2938 { 3156 {
@@ -2954,6 +3172,7 @@ namespace OpenSim.Region.Framework.Scenes
2954 obPart.StoreUndoState(); 3172 obPart.StoreUndoState();
2955 } 3173 }
2956 } 3174 }
3175 lockPartsForRead(false);
2957 3176
2958 if (part.PhysActor != null) 3177 if (part.PhysActor != null)
2959 { 3178 {
@@ -3056,7 +3275,7 @@ namespace OpenSim.Region.Framework.Scenes
3056 axDiff *= Quaternion.Inverse(partRotation); 3275 axDiff *= Quaternion.Inverse(partRotation);
3057 diff = axDiff; 3276 diff = axDiff;
3058 3277
3059 lock (m_parts) 3278 lockPartsForRead(true);
3060 { 3279 {
3061 foreach (SceneObjectPart obPart in m_parts.Values) 3280 foreach (SceneObjectPart obPart in m_parts.Values)
3062 { 3281 {
@@ -3066,6 +3285,7 @@ namespace OpenSim.Region.Framework.Scenes
3066 } 3285 }
3067 } 3286 }
3068 } 3287 }
3288 lockPartsForRead(false);
3069 3289
3070 AbsolutePosition = newPos; 3290 AbsolutePosition = newPos;
3071 3291
@@ -3199,25 +3419,25 @@ namespace OpenSim.Region.Framework.Scenes
3199 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); 3419 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
3200 } 3420 }
3201 3421
3202 lock (m_parts) 3422 lockPartsForRead(true);
3423
3424 foreach (SceneObjectPart prim in m_parts.Values)
3203 { 3425 {
3204 foreach (SceneObjectPart prim in m_parts.Values) 3426 if (prim.UUID != m_rootPart.UUID)
3205 { 3427 {
3206 if (prim.UUID != m_rootPart.UUID) 3428 prim.IgnoreUndoUpdate = true;
3207 { 3429 Vector3 axPos = prim.OffsetPosition;
3208 prim.IgnoreUndoUpdate = true; 3430 axPos *= oldParentRot;
3209 Vector3 axPos = prim.OffsetPosition; 3431 axPos *= Quaternion.Inverse(axRot);
3210 axPos *= oldParentRot; 3432 prim.OffsetPosition = axPos;
3211 axPos *= Quaternion.Inverse(axRot); 3433 Quaternion primsRot = prim.RotationOffset;
3212 prim.OffsetPosition = axPos; 3434 Quaternion newRot = primsRot * oldParentRot;
3213 Quaternion primsRot = prim.RotationOffset; 3435 newRot *= Quaternion.Inverse(axRot);
3214 Quaternion newRot = primsRot * oldParentRot; 3436 prim.RotationOffset = newRot;
3215 newRot *= Quaternion.Inverse(axRot); 3437 prim.ScheduleTerseUpdate();
3216 prim.RotationOffset = newRot;
3217 prim.ScheduleTerseUpdate();
3218 }
3219 } 3438 }
3220 } 3439 }
3440
3221 foreach (SceneObjectPart childpart in Children.Values) 3441 foreach (SceneObjectPart childpart in Children.Values)
3222 { 3442 {
3223 if (childpart != m_rootPart) 3443 if (childpart != m_rootPart)
@@ -3226,6 +3446,9 @@ namespace OpenSim.Region.Framework.Scenes
3226 childpart.StoreUndoState(); 3446 childpart.StoreUndoState();
3227 } 3447 }
3228 } 3448 }
3449
3450 lockPartsForRead(false);
3451
3229 m_rootPart.ScheduleTerseUpdate(); 3452 m_rootPart.ScheduleTerseUpdate();
3230 } 3453 }
3231 3454
@@ -3347,7 +3570,7 @@ namespace OpenSim.Region.Framework.Scenes
3347 if (atTargets.Count > 0) 3570 if (atTargets.Count > 0)
3348 { 3571 {
3349 uint[] localids = new uint[0]; 3572 uint[] localids = new uint[0];
3350 lock (m_parts) 3573 lockPartsForRead(true);
3351 { 3574 {
3352 localids = new uint[m_parts.Count]; 3575 localids = new uint[m_parts.Count];
3353 int cntr = 0; 3576 int cntr = 0;
@@ -3357,6 +3580,7 @@ namespace OpenSim.Region.Framework.Scenes
3357 cntr++; 3580 cntr++;
3358 } 3581 }
3359 } 3582 }
3583 lockPartsForRead(false);
3360 3584
3361 for (int ctr = 0; ctr < localids.Length; ctr++) 3585 for (int ctr = 0; ctr < localids.Length; ctr++)
3362 { 3586 {
@@ -3375,7 +3599,7 @@ namespace OpenSim.Region.Framework.Scenes
3375 { 3599 {
3376 //trigger not_at_target 3600 //trigger not_at_target
3377 uint[] localids = new uint[0]; 3601 uint[] localids = new uint[0];
3378 lock (m_parts) 3602 lockPartsForRead(true);
3379 { 3603 {
3380 localids = new uint[m_parts.Count]; 3604 localids = new uint[m_parts.Count];
3381 int cntr = 0; 3605 int cntr = 0;
@@ -3385,7 +3609,8 @@ namespace OpenSim.Region.Framework.Scenes
3385 cntr++; 3609 cntr++;
3386 } 3610 }
3387 } 3611 }
3388 3612 lockPartsForRead(false);
3613
3389 for (int ctr = 0; ctr < localids.Length; ctr++) 3614 for (int ctr = 0; ctr < localids.Length; ctr++)
3390 { 3615 {
3391 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]); 3616 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]);
@@ -3477,19 +3702,20 @@ namespace OpenSim.Region.Framework.Scenes
3477 public float GetMass() 3702 public float GetMass()
3478 { 3703 {
3479 float retmass = 0f; 3704 float retmass = 0f;
3480 lock (m_parts) 3705 lockPartsForRead(true);
3481 { 3706 {
3482 foreach (SceneObjectPart part in m_parts.Values) 3707 foreach (SceneObjectPart part in m_parts.Values)
3483 { 3708 {
3484 retmass += part.GetMass(); 3709 retmass += part.GetMass();
3485 } 3710 }
3486 } 3711 }
3712 lockPartsForRead(false);
3487 return retmass; 3713 return retmass;
3488 } 3714 }
3489 3715
3490 public void CheckSculptAndLoad() 3716 public void CheckSculptAndLoad()
3491 { 3717 {
3492 lock (m_parts) 3718 lockPartsForRead(true);
3493 { 3719 {
3494 if (!IsDeleted) 3720 if (!IsDeleted)
3495 { 3721 {
@@ -3514,6 +3740,7 @@ namespace OpenSim.Region.Framework.Scenes
3514 } 3740 }
3515 } 3741 }
3516 } 3742 }
3743 lockPartsForRead(false);
3517 } 3744 }
3518 3745
3519 protected void AssetReceived(string id, Object sender, AssetBase asset) 3746 protected void AssetReceived(string id, Object sender, AssetBase asset)
@@ -3534,7 +3761,7 @@ namespace OpenSim.Region.Framework.Scenes
3534 /// <param name="client"></param> 3761 /// <param name="client"></param>
3535 public void SetGroup(UUID GroupID, IClientAPI client) 3762 public void SetGroup(UUID GroupID, IClientAPI client)
3536 { 3763 {
3537 lock (m_parts) 3764 lockPartsForRead(true);
3538 { 3765 {
3539 foreach (SceneObjectPart part in m_parts.Values) 3766 foreach (SceneObjectPart part in m_parts.Values)
3540 { 3767 {
@@ -3544,6 +3771,7 @@ namespace OpenSim.Region.Framework.Scenes
3544 3771
3545 HasGroupChanged = true; 3772 HasGroupChanged = true;
3546 } 3773 }
3774 lockPartsForRead(false);
3547 3775
3548 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled 3776 // 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. 3777 // for the same object with very different properties. The caller must schedule the update.
@@ -3565,11 +3793,12 @@ namespace OpenSim.Region.Framework.Scenes
3565 3793
3566 public void SetAttachmentPoint(byte point) 3794 public void SetAttachmentPoint(byte point)
3567 { 3795 {
3568 lock (m_parts) 3796 lockPartsForRead(true);
3569 { 3797 {
3570 foreach (SceneObjectPart part in m_parts.Values) 3798 foreach (SceneObjectPart part in m_parts.Values)
3571 part.SetAttachmentPoint(point); 3799 part.SetAttachmentPoint(point);
3572 } 3800 }
3801 lockPartsForRead(false);
3573 } 3802 }
3574 3803
3575 #region ISceneObject 3804 #region ISceneObject
@@ -3703,5 +3932,13 @@ namespace OpenSim.Region.Framework.Scenes
3703 3932
3704 return priority; 3933 return priority;
3705 } 3934 }
3935
3936 public void ResetOwnerChangeFlag()
3937 {
3938 ForEachPart(delegate(SceneObjectPart part)
3939 {
3940 part.ResetOwnerChangeFlag();
3941 });
3942 }
3706 } 3943 }
3707} 3944}