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.cs662
1 files changed, 445 insertions, 217 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 8aefd50..1c6f2d1 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. 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,10 +1657,11 @@ 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));
@@ -1570,10 +1735,11 @@ namespace OpenSim.Region.Framework.Scenes
1570 1735
1571 List<SceneObjectPart> partList; 1736 List<SceneObjectPart> partList;
1572 1737
1573 lock (m_parts) 1738 lockPartsForRead(true);
1574 { 1739
1575 partList = new List<SceneObjectPart>(m_parts.Values); 1740 partList = new List<SceneObjectPart>(m_parts.Values);
1576 } 1741
1742 lockPartsForRead(false);
1577 1743
1578 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) 1744 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1579 { 1745 {
@@ -1796,13 +1962,40 @@ namespace OpenSim.Region.Framework.Scenes
1796 } 1962 }
1797 } 1963 }
1798 1964
1965 public void rotLookAt(Quaternion target, float strength, float damping)
1966 {
1967 SceneObjectPart rootpart = m_rootPart;
1968 if (rootpart != null)
1969 {
1970 if (IsAttachment)
1971 {
1972 /*
1973 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
1974 if (avatar != null)
1975 {
1976 Rotate the Av?
1977 } */
1978 }
1979 else
1980 {
1981 if (rootpart.PhysActor != null)
1982 { // APID must be implemented in your physics system for this to function.
1983 rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W);
1984 rootpart.PhysActor.APIDStrength = strength;
1985 rootpart.PhysActor.APIDDamping = damping;
1986 rootpart.PhysActor.APIDActive = true;
1987 }
1988 }
1989 }
1990 }
1991
1799 public void stopLookAt() 1992 public void stopLookAt()
1800 { 1993 {
1801 SceneObjectPart rootpart = m_rootPart; 1994 SceneObjectPart rootpart = m_rootPart;
1802 if (rootpart != null) 1995 if (rootpart != null)
1803 { 1996 {
1804 if (rootpart.PhysActor != null) 1997 if (rootpart.PhysActor != null)
1805 { 1998 { // APID must be implemented in your physics system for this to function.
1806 rootpart.PhysActor.APIDActive = false; 1999 rootpart.PhysActor.APIDActive = false;
1807 } 2000 }
1808 } 2001 }
@@ -1870,10 +2063,11 @@ namespace OpenSim.Region.Framework.Scenes
1870 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 2063 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
1871 newPart.SetParent(this); 2064 newPart.SetParent(this);
1872 2065
1873 lock (m_parts) 2066 lockPartsForWrite(true);
1874 { 2067 {
1875 m_parts.Add(newPart.UUID, newPart); 2068 m_parts.Add(newPart.UUID, newPart);
1876 } 2069 }
2070 lockPartsForWrite(false);
1877 2071
1878 SetPartAsNonRoot(newPart); 2072 SetPartAsNonRoot(newPart);
1879 2073
@@ -1936,7 +2130,7 @@ namespace OpenSim.Region.Framework.Scenes
1936 //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0) 2130 //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
1937 // return; 2131 // return;
1938 2132
1939 lock (m_parts) 2133 lockPartsForRead(true);
1940 { 2134 {
1941 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0); 2135 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0);
1942 2136
@@ -1956,9 +2150,12 @@ namespace OpenSim.Region.Framework.Scenes
1956 { 2150 {
1957 if (!IsSelected) 2151 if (!IsSelected)
1958 part.UpdateLookAt(); 2152 part.UpdateLookAt();
2153
1959 part.SendScheduledUpdates(); 2154 part.SendScheduledUpdates();
2155
1960 } 2156 }
1961 } 2157 }
2158 lockPartsForRead(false);
1962 } 2159 }
1963 2160
1964 public void ScheduleFullUpdateToAvatar(ScenePresence presence) 2161 public void ScheduleFullUpdateToAvatar(ScenePresence presence)
@@ -1967,27 +2164,29 @@ namespace OpenSim.Region.Framework.Scenes
1967 2164
1968 RootPart.AddFullUpdateToAvatar(presence); 2165 RootPart.AddFullUpdateToAvatar(presence);
1969 2166
1970 lock (m_parts) 2167 lockPartsForRead(true);
1971 { 2168 {
1972 foreach (SceneObjectPart part in m_parts.Values) 2169 foreach (SceneObjectPart part in m_parts.Values)
1973 { 2170 {
2171
1974 if (part != RootPart) 2172 if (part != RootPart)
1975 part.AddFullUpdateToAvatar(presence); 2173 part.AddFullUpdateToAvatar(presence);
2174
1976 } 2175 }
1977 } 2176 }
2177 lockPartsForRead(false);
1978 } 2178 }
1979 2179
1980 public void ScheduleTerseUpdateToAvatar(ScenePresence presence) 2180 public void ScheduleTerseUpdateToAvatar(ScenePresence presence)
1981 { 2181 {
1982// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1} just to avatar {2}", Name, UUID, presence.Name); 2182 lockPartsForRead(true);
1983 2183
1984 lock (m_parts) 2184 foreach (SceneObjectPart part in m_parts.Values)
1985 { 2185 {
1986 foreach (SceneObjectPart part in m_parts.Values) 2186 part.AddTerseUpdateToAvatar(presence);
1987 {
1988 part.AddTerseUpdateToAvatar(presence);
1989 }
1990 } 2187 }
2188
2189 lockPartsForRead(false);
1991 } 2190 }
1992 2191
1993 /// <summary> 2192 /// <summary>
@@ -2000,14 +2199,17 @@ namespace OpenSim.Region.Framework.Scenes
2000 checkAtTargets(); 2199 checkAtTargets();
2001 RootPart.ScheduleFullUpdate(); 2200 RootPart.ScheduleFullUpdate();
2002 2201
2003 lock (m_parts) 2202 lockPartsForRead(true);
2004 { 2203 {
2005 foreach (SceneObjectPart part in m_parts.Values) 2204 foreach (SceneObjectPart part in m_parts.Values)
2006 { 2205 {
2206
2007 if (part != RootPart) 2207 if (part != RootPart)
2008 part.ScheduleFullUpdate(); 2208 part.ScheduleFullUpdate();
2209
2009 } 2210 }
2010 } 2211 }
2212 lockPartsForRead(false);
2011 } 2213 }
2012 2214
2013 /// <summary> 2215 /// <summary>
@@ -2015,37 +2217,38 @@ namespace OpenSim.Region.Framework.Scenes
2015 /// </summary> 2217 /// </summary>
2016 public void ScheduleGroupForTerseUpdate() 2218 public void ScheduleGroupForTerseUpdate()
2017 { 2219 {
2018// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1}", Name, UUID); 2220 lockPartsForRead(true);
2019 2221 foreach (SceneObjectPart part in m_parts.Values)
2020 lock (m_parts)
2021 { 2222 {
2022 foreach (SceneObjectPart part in m_parts.Values) 2223 part.ScheduleTerseUpdate();
2023 {
2024 part.ScheduleTerseUpdate();
2025 }
2026 } 2224 }
2225
2226 lockPartsForRead(false);
2027 } 2227 }
2028 2228
2029 /// <summary> 2229 /// <summary>
2030 /// Immediately send a full update for this scene object. 2230 /// Immediately send a full update for this scene object.
2031 /// </summary> 2231 /// </summary>
2032 public void SendGroupFullUpdate() 2232 public void SendGroupFullUpdate()
2033 { 2233 {
2034 if (IsDeleted) 2234 if (IsDeleted)
2035 return; 2235 return;
2036 2236
2037// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); 2237// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID);
2038 2238
2039 RootPart.SendFullUpdateToAllClients(); 2239 RootPart.SendFullUpdateToAllClients();
2040 2240
2041 lock (m_parts) 2241 lockPartsForRead(true);
2042 { 2242 {
2043 foreach (SceneObjectPart part in m_parts.Values) 2243 foreach (SceneObjectPart part in m_parts.Values)
2044 { 2244 {
2245
2045 if (part != RootPart) 2246 if (part != RootPart)
2046 part.SendFullUpdateToAllClients(); 2247 part.SendFullUpdateToAllClients();
2248
2047 } 2249 }
2048 } 2250 }
2251 lockPartsForRead(false);
2049 } 2252 }
2050 2253
2051 /// <summary> 2254 /// <summary>
@@ -2077,14 +2280,15 @@ namespace OpenSim.Region.Framework.Scenes
2077 { 2280 {
2078 if (IsDeleted) 2281 if (IsDeleted)
2079 return; 2282 return;
2080 2283
2081 lock (m_parts) 2284 lockPartsForRead(true);
2082 { 2285 {
2083 foreach (SceneObjectPart part in m_parts.Values) 2286 foreach (SceneObjectPart part in m_parts.Values)
2084 { 2287 {
2085 part.SendTerseUpdateToAllClients(); 2288 part.SendTerseUpdateToAllClients();
2086 } 2289 }
2087 } 2290 }
2291 lockPartsForRead(false);
2088 } 2292 }
2089 2293
2090 #endregion 2294 #endregion
@@ -2098,16 +2302,18 @@ namespace OpenSim.Region.Framework.Scenes
2098 /// <returns>null if no child part with that linknum or child part</returns> 2302 /// <returns>null if no child part with that linknum or child part</returns>
2099 public SceneObjectPart GetLinkNumPart(int linknum) 2303 public SceneObjectPart GetLinkNumPart(int linknum)
2100 { 2304 {
2101 lock (m_parts) 2305 lockPartsForRead(true);
2102 { 2306 {
2103 foreach (SceneObjectPart part in m_parts.Values) 2307 foreach (SceneObjectPart part in m_parts.Values)
2104 { 2308 {
2105 if (part.LinkNum == linknum) 2309 if (part.LinkNum == linknum)
2106 { 2310 {
2311 lockPartsForRead(false);
2107 return part; 2312 return part;
2108 } 2313 }
2109 } 2314 }
2110 } 2315 }
2316 lockPartsForRead(false);
2111 2317
2112 return null; 2318 return null;
2113 } 2319 }
@@ -2135,17 +2341,19 @@ namespace OpenSim.Region.Framework.Scenes
2135 public SceneObjectPart GetChildPart(uint localID) 2341 public SceneObjectPart GetChildPart(uint localID)
2136 { 2342 {
2137 //m_log.DebugFormat("Entered looking for {0}", localID); 2343 //m_log.DebugFormat("Entered looking for {0}", localID);
2138 lock (m_parts) 2344 lockPartsForRead(true);
2139 { 2345 {
2140 foreach (SceneObjectPart part in m_parts.Values) 2346 foreach (SceneObjectPart part in m_parts.Values)
2141 { 2347 {
2142 //m_log.DebugFormat("Found {0}", part.LocalId); 2348 //m_log.DebugFormat("Found {0}", part.LocalId);
2143 if (part.LocalId == localID) 2349 if (part.LocalId == localID)
2144 { 2350 {
2351 lockPartsForRead(false);
2145 return part; 2352 return part;
2146 } 2353 }
2147 } 2354 }
2148 } 2355 }
2356 lockPartsForRead(false);
2149 2357
2150 return null; 2358 return null;
2151 } 2359 }
@@ -2175,17 +2383,19 @@ namespace OpenSim.Region.Framework.Scenes
2175 public bool HasChildPrim(uint localID) 2383 public bool HasChildPrim(uint localID)
2176 { 2384 {
2177 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID); 2385 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID);
2178 lock (m_parts) 2386 lockPartsForRead(true);
2179 { 2387 {
2180 foreach (SceneObjectPart part in m_parts.Values) 2388 foreach (SceneObjectPart part in m_parts.Values)
2181 { 2389 {
2182 //m_log.DebugFormat("Found {0}", part.LocalId); 2390 //m_log.DebugFormat("Found {0}", part.LocalId);
2183 if (part.LocalId == localID) 2391 if (part.LocalId == localID)
2184 { 2392 {
2393 lockPartsForRead(false);
2185 return true; 2394 return true;
2186 } 2395 }
2187 } 2396 }
2188 } 2397 }
2398 lockPartsForRead(false);
2189 2399
2190 return false; 2400 return false;
2191 } 2401 }
@@ -2235,53 +2445,57 @@ namespace OpenSim.Region.Framework.Scenes
2235 if (m_rootPart.LinkNum == 0) 2445 if (m_rootPart.LinkNum == 0)
2236 m_rootPart.LinkNum = 1; 2446 m_rootPart.LinkNum = 1;
2237 2447
2238 lock (m_parts) 2448 lockPartsForWrite(true);
2239 { 2449
2240 m_parts.Add(linkPart.UUID, linkPart); 2450 m_parts.Add(linkPart.UUID, linkPart);
2241 2451
2242 // Insert in terms of link numbers, the new links 2452 lockPartsForWrite(false);
2243 // before the current ones (with the exception of 2453
2244 // the root prim. Shuffle the old ones up 2454 // Insert in terms of link numbers, the new links
2245 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts) 2455 // before the current ones (with the exception of
2456 // the root prim. Shuffle the old ones up
2457 lockPartsForRead(true);
2458 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts)
2459 {
2460 if (kvp.Value.LinkNum != 1)
2246 { 2461 {
2247 if (kvp.Value.LinkNum != 1) 2462 // Don't update root prim link number
2248 { 2463 kvp.Value.LinkNum += objectGroup.PrimCount;
2249 // Don't update root prim link number
2250 kvp.Value.LinkNum += objectGroup.PrimCount;
2251 }
2252 } 2464 }
2465 }
2466 lockPartsForRead(false);
2253 2467
2254 linkPart.LinkNum = 2; 2468 linkPart.LinkNum = 2;
2255 2469
2256 linkPart.SetParent(this); 2470 linkPart.SetParent(this);
2257 linkPart.AddFlag(PrimFlags.CreateSelected); 2471 linkPart.AddFlag(PrimFlags.CreateSelected);
2258 2472
2259 //if (linkPart.PhysActor != null) 2473 //if (linkPart.PhysActor != null)
2260 //{ 2474 //{
2261 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); 2475 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor);
2262 2476
2263 //linkPart.PhysActor = null; 2477 //linkPart.PhysActor = null;
2264 //} 2478 //}
2265 2479
2266 //TODO: rest of parts 2480 //TODO: rest of parts
2267 int linkNum = 3; 2481 int linkNum = 3;
2268 foreach (SceneObjectPart part in objectGroup.Children.Values) 2482 foreach (SceneObjectPart part in objectGroup.Children.Values)
2483 {
2484 if (part.UUID != objectGroup.m_rootPart.UUID)
2269 { 2485 {
2270 if (part.UUID != objectGroup.m_rootPart.UUID) 2486 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2271 {
2272 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2273 }
2274 part.ClearUndoState();
2275 } 2487 }
2488 part.ClearUndoState();
2276 } 2489 }
2277 2490
2278 m_scene.UnlinkSceneObject(objectGroup.UUID, true); 2491 m_scene.UnlinkSceneObject(objectGroup.UUID, true);
2279 objectGroup.m_isDeleted = true; 2492 objectGroup.m_isDeleted = true;
2493
2494 objectGroup.lockPartsForWrite(true);
2280 2495
2281 lock (objectGroup.m_parts) 2496 objectGroup.m_parts.Clear();
2282 { 2497
2283 objectGroup.m_parts.Clear(); 2498 objectGroup.lockPartsForWrite(false);
2284 }
2285 2499
2286 // Can't do this yet since backup still makes use of the root part without any synchronization 2500 // Can't do this yet since backup still makes use of the root part without any synchronization
2287// objectGroup.m_rootPart = null; 2501// objectGroup.m_rootPart = null;
@@ -2351,11 +2565,12 @@ namespace OpenSim.Region.Framework.Scenes
2351 Quaternion worldRot = linkPart.GetWorldRotation(); 2565 Quaternion worldRot = linkPart.GetWorldRotation();
2352 2566
2353 // Remove the part from this object 2567 // Remove the part from this object
2354 lock (m_parts) 2568 lockPartsForWrite(true);
2355 { 2569 {
2356 m_parts.Remove(linkPart.UUID); 2570 m_parts.Remove(linkPart.UUID);
2357 } 2571 }
2358 2572 lockPartsForWrite(false);
2573 lockPartsForRead(true);
2359 if (m_parts.Count == 1 && RootPart != null) //Single prim is left 2574 if (m_parts.Count == 1 && RootPart != null) //Single prim is left
2360 RootPart.LinkNum = 0; 2575 RootPart.LinkNum = 0;
2361 else 2576 else
@@ -2366,6 +2581,7 @@ namespace OpenSim.Region.Framework.Scenes
2366 p.LinkNum--; 2581 p.LinkNum--;
2367 } 2582 }
2368 } 2583 }
2584 lockPartsForRead(false);
2369 2585
2370 linkPart.ParentID = 0; 2586 linkPart.ParentID = 0;
2371 linkPart.LinkNum = 0; 2587 linkPart.LinkNum = 0;
@@ -2687,9 +2903,12 @@ namespace OpenSim.Region.Framework.Scenes
2687 2903
2688 if (selectionPart != null) 2904 if (selectionPart != null)
2689 { 2905 {
2690 lock (m_parts) 2906 lockPartsForRead(true);
2907 List<SceneObjectPart> parts = new List<SceneObjectPart>(m_parts.Values);
2908 lockPartsForRead(false);
2909 foreach (SceneObjectPart part in parts)
2691 { 2910 {
2692 foreach (SceneObjectPart part in m_parts.Values) 2911 if (part.Scale.X > 10.0 || part.Scale.Y > 10.0 || part.Scale.Z > 10.0)
2693 { 2912 {
2694 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax || 2913 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax ||
2695 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax || 2914 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax ||
@@ -2699,12 +2918,13 @@ namespace OpenSim.Region.Framework.Scenes
2699 break; 2918 break;
2700 } 2919 }
2701 } 2920 }
2921 }
2702 2922
2703 foreach (SceneObjectPart part in m_parts.Values) 2923 foreach (SceneObjectPart part in parts)
2704 { 2924 {
2705 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect); 2925 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
2706 }
2707 } 2926 }
2927
2708 } 2928 }
2709 } 2929 }
2710 2930
@@ -2790,11 +3010,9 @@ namespace OpenSim.Region.Framework.Scenes
2790 scale.Y = m_scene.m_maxNonphys; 3010 scale.Y = m_scene.m_maxNonphys;
2791 if (scale.Z > m_scene.m_maxNonphys) 3011 if (scale.Z > m_scene.m_maxNonphys)
2792 scale.Z = m_scene.m_maxNonphys; 3012 scale.Z = m_scene.m_maxNonphys;
2793
2794 SceneObjectPart part = GetChildPart(localID); 3013 SceneObjectPart part = GetChildPart(localID);
2795 if (part != null) 3014 if (part != null)
2796 { 3015 {
2797 part.Resize(scale);
2798 if (part.PhysActor != null) 3016 if (part.PhysActor != null)
2799 { 3017 {
2800 if (part.PhysActor.IsPhysical) 3018 if (part.PhysActor.IsPhysical)
@@ -2809,7 +3027,7 @@ namespace OpenSim.Region.Framework.Scenes
2809 part.PhysActor.Size = scale; 3027 part.PhysActor.Size = scale;
2810 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); 3028 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor);
2811 } 3029 }
2812 //if (part.UUID != m_rootPart.UUID) 3030 part.Resize(scale);
2813 3031
2814 HasGroupChanged = true; 3032 HasGroupChanged = true;
2815 ScheduleGroupForFullUpdate(); 3033 ScheduleGroupForFullUpdate();
@@ -2851,73 +3069,71 @@ namespace OpenSim.Region.Framework.Scenes
2851 float y = (scale.Y / part.Scale.Y); 3069 float y = (scale.Y / part.Scale.Y);
2852 float z = (scale.Z / part.Scale.Z); 3070 float z = (scale.Z / part.Scale.Z);
2853 3071
2854 lock (m_parts) 3072 lockPartsForRead(true);
3073 if (x > 1.0f || y > 1.0f || z > 1.0f)
2855 { 3074 {
2856 if (x > 1.0f || y > 1.0f || z > 1.0f) 3075 foreach (SceneObjectPart obPart in m_parts.Values)
2857 { 3076 {
2858 foreach (SceneObjectPart obPart in m_parts.Values) 3077 if (obPart.UUID != m_rootPart.UUID)
2859 { 3078 {
2860 if (obPart.UUID != m_rootPart.UUID) 3079 Vector3 oldSize = new Vector3(obPart.Scale);
2861 { 3080 obPart.IgnoreUndoUpdate = true;
2862 obPart.IgnoreUndoUpdate = true;
2863 Vector3 oldSize = new Vector3(obPart.Scale);
2864 3081
2865 float f = 1.0f; 3082 float f = 1.0f;
2866 float a = 1.0f; 3083 float a = 1.0f;
2867 3084
2868 if (part.PhysActor != null && part.PhysActor.IsPhysical) 3085 if (part.PhysActor != null && part.PhysActor.IsPhysical)
3086 {
3087 if (oldSize.X*x > m_scene.m_maxPhys)
2869 { 3088 {
2870 if (oldSize.X*x > m_scene.m_maxPhys) 3089 f = m_scene.m_maxPhys / oldSize.X;
2871 { 3090 a = f / x;
2872 f = m_scene.m_maxPhys / oldSize.X; 3091 x *= a;
2873 a = f / x; 3092 y *= a;
2874 x *= a; 3093 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 } 3094 }
2895 else 3095 if (oldSize.Y*y > m_scene.m_maxPhys)
3096 {
3097 f = m_scene.m_maxPhys / oldSize.Y;
3098 a = f / y;
3099 x *= a;
3100 y *= a;
3101 z *= a;
3102 }
3103 if (oldSize.Z*z > m_scene.m_maxPhys)
3104 {
3105 f = m_scene.m_maxPhys / oldSize.Z;
3106 a = f / z;
3107 x *= a;
3108 y *= a;
3109 z *= a;
3110 }
3111 }
3112 else
3113 {
3114 if (oldSize.X*x > m_scene.m_maxNonphys)
2896 { 3115 {
2897 if (oldSize.X*x > m_scene.m_maxNonphys) 3116 f = m_scene.m_maxNonphys / oldSize.X;
2898 { 3117 a = f / x;
2899 f = m_scene.m_maxNonphys / oldSize.X; 3118 x *= a;
2900 a = f / x; 3119 y *= a;
2901 x *= a; 3120 z *= a;
2902 y *= a; 3121 }
2903 z *= a; 3122 if (oldSize.Y*y > m_scene.m_maxNonphys)
2904 } 3123 {
2905 if (oldSize.Y*y > m_scene.m_maxNonphys) 3124 f = m_scene.m_maxNonphys / oldSize.Y;
2906 { 3125 a = f / y;
2907 f = m_scene.m_maxNonphys / oldSize.Y; 3126 x *= a;
2908 a = f / y; 3127 y *= a;
2909 x *= a; 3128 z *= a;
2910 y *= a; 3129 }
2911 z *= a; 3130 if (oldSize.Z*z > m_scene.m_maxNonphys)
2912 } 3131 {
2913 if (oldSize.Z*z > m_scene.m_maxNonphys) 3132 f = m_scene.m_maxNonphys / oldSize.Z;
2914 { 3133 a = f / z;
2915 f = m_scene.m_maxNonphys / oldSize.Z; 3134 x *= a;
2916 a = f / z; 3135 y *= a;
2917 x *= a; 3136 z *= a;
2918 y *= a;
2919 z *= a;
2920 }
2921 } 3137 }
2922 obPart.IgnoreUndoUpdate = false; 3138 obPart.IgnoreUndoUpdate = false;
2923 obPart.StoreUndoState(); 3139 obPart.StoreUndoState();
@@ -2925,6 +3141,7 @@ namespace OpenSim.Region.Framework.Scenes
2925 } 3141 }
2926 } 3142 }
2927 } 3143 }
3144 lockPartsForRead(false);
2928 3145
2929 Vector3 prevScale = part.Scale; 3146 Vector3 prevScale = part.Scale;
2930 prevScale.X *= x; 3147 prevScale.X *= x;
@@ -2932,7 +3149,7 @@ namespace OpenSim.Region.Framework.Scenes
2932 prevScale.Z *= z; 3149 prevScale.Z *= z;
2933 part.Resize(prevScale); 3150 part.Resize(prevScale);
2934 3151
2935 lock (m_parts) 3152 lockPartsForRead(true);
2936 { 3153 {
2937 foreach (SceneObjectPart obPart in m_parts.Values) 3154 foreach (SceneObjectPart obPart in m_parts.Values)
2938 { 3155 {
@@ -2954,6 +3171,7 @@ namespace OpenSim.Region.Framework.Scenes
2954 obPart.StoreUndoState(); 3171 obPart.StoreUndoState();
2955 } 3172 }
2956 } 3173 }
3174 lockPartsForRead(false);
2957 3175
2958 if (part.PhysActor != null) 3176 if (part.PhysActor != null)
2959 { 3177 {
@@ -3056,7 +3274,7 @@ namespace OpenSim.Region.Framework.Scenes
3056 axDiff *= Quaternion.Inverse(partRotation); 3274 axDiff *= Quaternion.Inverse(partRotation);
3057 diff = axDiff; 3275 diff = axDiff;
3058 3276
3059 lock (m_parts) 3277 lockPartsForRead(true);
3060 { 3278 {
3061 foreach (SceneObjectPart obPart in m_parts.Values) 3279 foreach (SceneObjectPart obPart in m_parts.Values)
3062 { 3280 {
@@ -3066,6 +3284,7 @@ namespace OpenSim.Region.Framework.Scenes
3066 } 3284 }
3067 } 3285 }
3068 } 3286 }
3287 lockPartsForRead(false);
3069 3288
3070 AbsolutePosition = newPos; 3289 AbsolutePosition = newPos;
3071 3290
@@ -3199,25 +3418,25 @@ namespace OpenSim.Region.Framework.Scenes
3199 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); 3418 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
3200 } 3419 }
3201 3420
3202 lock (m_parts) 3421 lockPartsForRead(true);
3422
3423 foreach (SceneObjectPart prim in m_parts.Values)
3203 { 3424 {
3204 foreach (SceneObjectPart prim in m_parts.Values) 3425 if (prim.UUID != m_rootPart.UUID)
3205 { 3426 {
3206 if (prim.UUID != m_rootPart.UUID) 3427 prim.IgnoreUndoUpdate = true;
3207 { 3428 Vector3 axPos = prim.OffsetPosition;
3208 prim.IgnoreUndoUpdate = true; 3429 axPos *= oldParentRot;
3209 Vector3 axPos = prim.OffsetPosition; 3430 axPos *= Quaternion.Inverse(axRot);
3210 axPos *= oldParentRot; 3431 prim.OffsetPosition = axPos;
3211 axPos *= Quaternion.Inverse(axRot); 3432 Quaternion primsRot = prim.RotationOffset;
3212 prim.OffsetPosition = axPos; 3433 Quaternion newRot = primsRot * oldParentRot;
3213 Quaternion primsRot = prim.RotationOffset; 3434 newRot *= Quaternion.Inverse(axRot);
3214 Quaternion newRot = primsRot * oldParentRot; 3435 prim.RotationOffset = newRot;
3215 newRot *= Quaternion.Inverse(axRot); 3436 prim.ScheduleTerseUpdate();
3216 prim.RotationOffset = newRot;
3217 prim.ScheduleTerseUpdate();
3218 }
3219 } 3437 }
3220 } 3438 }
3439
3221 foreach (SceneObjectPart childpart in Children.Values) 3440 foreach (SceneObjectPart childpart in Children.Values)
3222 { 3441 {
3223 if (childpart != m_rootPart) 3442 if (childpart != m_rootPart)
@@ -3226,6 +3445,9 @@ namespace OpenSim.Region.Framework.Scenes
3226 childpart.StoreUndoState(); 3445 childpart.StoreUndoState();
3227 } 3446 }
3228 } 3447 }
3448
3449 lockPartsForRead(false);
3450
3229 m_rootPart.ScheduleTerseUpdate(); 3451 m_rootPart.ScheduleTerseUpdate();
3230 } 3452 }
3231 3453
@@ -3347,7 +3569,7 @@ namespace OpenSim.Region.Framework.Scenes
3347 if (atTargets.Count > 0) 3569 if (atTargets.Count > 0)
3348 { 3570 {
3349 uint[] localids = new uint[0]; 3571 uint[] localids = new uint[0];
3350 lock (m_parts) 3572 lockPartsForRead(true);
3351 { 3573 {
3352 localids = new uint[m_parts.Count]; 3574 localids = new uint[m_parts.Count];
3353 int cntr = 0; 3575 int cntr = 0;
@@ -3357,6 +3579,7 @@ namespace OpenSim.Region.Framework.Scenes
3357 cntr++; 3579 cntr++;
3358 } 3580 }
3359 } 3581 }
3582 lockPartsForRead(false);
3360 3583
3361 for (int ctr = 0; ctr < localids.Length; ctr++) 3584 for (int ctr = 0; ctr < localids.Length; ctr++)
3362 { 3585 {
@@ -3375,7 +3598,7 @@ namespace OpenSim.Region.Framework.Scenes
3375 { 3598 {
3376 //trigger not_at_target 3599 //trigger not_at_target
3377 uint[] localids = new uint[0]; 3600 uint[] localids = new uint[0];
3378 lock (m_parts) 3601 lockPartsForRead(true);
3379 { 3602 {
3380 localids = new uint[m_parts.Count]; 3603 localids = new uint[m_parts.Count];
3381 int cntr = 0; 3604 int cntr = 0;
@@ -3385,7 +3608,8 @@ namespace OpenSim.Region.Framework.Scenes
3385 cntr++; 3608 cntr++;
3386 } 3609 }
3387 } 3610 }
3388 3611 lockPartsForRead(false);
3612
3389 for (int ctr = 0; ctr < localids.Length; ctr++) 3613 for (int ctr = 0; ctr < localids.Length; ctr++)
3390 { 3614 {
3391 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]); 3615 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]);
@@ -3477,19 +3701,20 @@ namespace OpenSim.Region.Framework.Scenes
3477 public float GetMass() 3701 public float GetMass()
3478 { 3702 {
3479 float retmass = 0f; 3703 float retmass = 0f;
3480 lock (m_parts) 3704 lockPartsForRead(true);
3481 { 3705 {
3482 foreach (SceneObjectPart part in m_parts.Values) 3706 foreach (SceneObjectPart part in m_parts.Values)
3483 { 3707 {
3484 retmass += part.GetMass(); 3708 retmass += part.GetMass();
3485 } 3709 }
3486 } 3710 }
3711 lockPartsForRead(false);
3487 return retmass; 3712 return retmass;
3488 } 3713 }
3489 3714
3490 public void CheckSculptAndLoad() 3715 public void CheckSculptAndLoad()
3491 { 3716 {
3492 lock (m_parts) 3717 lockPartsForRead(true);
3493 { 3718 {
3494 if (!IsDeleted) 3719 if (!IsDeleted)
3495 { 3720 {
@@ -3514,6 +3739,7 @@ namespace OpenSim.Region.Framework.Scenes
3514 } 3739 }
3515 } 3740 }
3516 } 3741 }
3742 lockPartsForRead(false);
3517 } 3743 }
3518 3744
3519 protected void AssetReceived(string id, Object sender, AssetBase asset) 3745 protected void AssetReceived(string id, Object sender, AssetBase asset)
@@ -3534,7 +3760,7 @@ namespace OpenSim.Region.Framework.Scenes
3534 /// <param name="client"></param> 3760 /// <param name="client"></param>
3535 public void SetGroup(UUID GroupID, IClientAPI client) 3761 public void SetGroup(UUID GroupID, IClientAPI client)
3536 { 3762 {
3537 lock (m_parts) 3763 lockPartsForRead(true);
3538 { 3764 {
3539 foreach (SceneObjectPart part in m_parts.Values) 3765 foreach (SceneObjectPart part in m_parts.Values)
3540 { 3766 {
@@ -3544,6 +3770,7 @@ namespace OpenSim.Region.Framework.Scenes
3544 3770
3545 HasGroupChanged = true; 3771 HasGroupChanged = true;
3546 } 3772 }
3773 lockPartsForRead(false);
3547 3774
3548 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled 3775 // 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. 3776 // for the same object with very different properties. The caller must schedule the update.
@@ -3565,11 +3792,12 @@ namespace OpenSim.Region.Framework.Scenes
3565 3792
3566 public void SetAttachmentPoint(byte point) 3793 public void SetAttachmentPoint(byte point)
3567 { 3794 {
3568 lock (m_parts) 3795 lockPartsForRead(true);
3569 { 3796 {
3570 foreach (SceneObjectPart part in m_parts.Values) 3797 foreach (SceneObjectPart part in m_parts.Values)
3571 part.SetAttachmentPoint(point); 3798 part.SetAttachmentPoint(point);
3572 } 3799 }
3800 lockPartsForRead(false);
3573 } 3801 }
3574 3802
3575 #region ISceneObject 3803 #region ISceneObject