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.cs640
1 files changed, 434 insertions, 206 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index aa41354..54b27b2 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)
@@ -308,14 +421,14 @@ namespace OpenSim.Region.Framework.Scenes
308 return; 421 return;
309 } 422 }
310 } 423 }
311 lock (m_parts) 424
425 foreach (SceneObjectPart part in m_parts.Values)
312 { 426 {
313 foreach (SceneObjectPart part in m_parts.Values) 427 part.GroupPosition = val;
314 {
315 part.GroupPosition = val;
316 }
317 } 428 }
318 429
430 lockPartsForRead(false);
431
319 //if (m_rootPart.PhysActor != null) 432 //if (m_rootPart.PhysActor != null)
320 //{ 433 //{
321 //m_rootPart.PhysActor.Position = 434 //m_rootPart.PhysActor.Position =
@@ -457,6 +570,7 @@ namespace OpenSim.Region.Framework.Scenes
457 /// </summary> 570 /// </summary>
458 public SceneObjectGroup() 571 public SceneObjectGroup()
459 { 572 {
573
460 } 574 }
461 575
462 /// <summary> 576 /// <summary>
@@ -473,7 +587,7 @@ namespace OpenSim.Region.Framework.Scenes
473 /// Constructor. This object is added to the scene later via AttachToScene() 587 /// Constructor. This object is added to the scene later via AttachToScene()
474 /// </summary> 588 /// </summary>
475 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) 589 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape)
476 { 590 {
477 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero)); 591 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero));
478 } 592 }
479 593
@@ -504,13 +618,16 @@ namespace OpenSim.Region.Framework.Scenes
504 618
505 public void SetFromItemID(UUID AssetId) 619 public void SetFromItemID(UUID AssetId)
506 { 620 {
507 lock (m_parts) 621 lockPartsForRead(true);
508 { 622 {
509 foreach (SceneObjectPart part in m_parts.Values) 623 foreach (SceneObjectPart part in m_parts.Values)
510 { 624 {
625
511 part.FromItemID = AssetId; 626 part.FromItemID = AssetId;
627
512 } 628 }
513 } 629 }
630 lockPartsForRead(false);
514 } 631 }
515 632
516 public UUID GetFromItemID() 633 public UUID GetFromItemID()
@@ -579,10 +696,11 @@ namespace OpenSim.Region.Framework.Scenes
579 Vector3 maxScale = Vector3.Zero; 696 Vector3 maxScale = Vector3.Zero;
580 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f); 697 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f);
581 698
582 lock (m_parts) 699 lockPartsForRead(true);
583 { 700 {
584 foreach (SceneObjectPart part in m_parts.Values) 701 foreach (SceneObjectPart part in m_parts.Values)
585 { 702 {
703
586 Vector3 partscale = part.Scale; 704 Vector3 partscale = part.Scale;
587 Vector3 partoffset = part.OffsetPosition; 705 Vector3 partoffset = part.OffsetPosition;
588 706
@@ -593,8 +711,11 @@ namespace OpenSim.Region.Framework.Scenes
593 maxScale.X = (partscale.X + partoffset.X > maxScale.X) ? partscale.X + partoffset.X : maxScale.X; 711 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; 712 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; 713 maxScale.Z = (partscale.Z + partoffset.Z > maxScale.Z) ? partscale.Z + partoffset.Z : maxScale.Z;
714
596 } 715 }
597 } 716 }
717 lockPartsForRead(false);
718
598 finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X; 719 finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X;
599 finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y; 720 finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y;
600 finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z; 721 finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z;
@@ -610,10 +731,11 @@ namespace OpenSim.Region.Framework.Scenes
610 731
611 EntityIntersection result = new EntityIntersection(); 732 EntityIntersection result = new EntityIntersection();
612 733
613 lock (m_parts) 734 lockPartsForRead(true);
614 { 735 {
615 foreach (SceneObjectPart part in m_parts.Values) 736 foreach (SceneObjectPart part in m_parts.Values)
616 { 737 {
738
617 // Temporary commented to stop compiler warning 739 // Temporary commented to stop compiler warning
618 //Vector3 partPosition = 740 //Vector3 partPosition =
619 // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z); 741 // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z);
@@ -641,8 +763,10 @@ namespace OpenSim.Region.Framework.Scenes
641 result.distance = inter.distance; 763 result.distance = inter.distance;
642 } 764 }
643 } 765 }
766
644 } 767 }
645 } 768 }
769 lockPartsForRead(false);
646 return result; 770 return result;
647 } 771 }
648 772
@@ -655,10 +779,11 @@ namespace OpenSim.Region.Framework.Scenes
655 public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight) 779 public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight)
656 { 780 {
657 float maxX = -256f, maxY = -256f, maxZ = -256f, minX = 256f, minY = 256f, minZ = 256f; 781 float maxX = -256f, maxY = -256f, maxZ = -256f, minX = 256f, minY = 256f, minZ = 256f;
658 lock (m_parts) 782 lockPartsForRead(true);
659 { 783 {
660 foreach (SceneObjectPart part in m_parts.Values) 784 foreach (SceneObjectPart part in m_parts.Values)
661 { 785 {
786
662 Vector3 worldPos = part.GetWorldPosition(); 787 Vector3 worldPos = part.GetWorldPosition();
663 Vector3 offset = worldPos - AbsolutePosition; 788 Vector3 offset = worldPos - AbsolutePosition;
664 Quaternion worldRot; 789 Quaternion worldRot;
@@ -717,6 +842,8 @@ namespace OpenSim.Region.Framework.Scenes
717 backBottomRight.Y = orig.Y + (part.Scale.Y / 2); 842 backBottomRight.Y = orig.Y + (part.Scale.Y / 2);
718 backBottomRight.Z = orig.Z - (part.Scale.Z / 2); 843 backBottomRight.Z = orig.Z - (part.Scale.Z / 2);
719 844
845
846
720 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z); 847 //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); 848 //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); 849 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
@@ -888,6 +1015,7 @@ namespace OpenSim.Region.Framework.Scenes
888 minZ = backBottomLeft.Z; 1015 minZ = backBottomLeft.Z;
889 } 1016 }
890 } 1017 }
1018 lockPartsForRead(false);
891 1019
892 Vector3 boundingBox = new Vector3(maxX - minX, maxY - minY, maxZ - minZ); 1020 Vector3 boundingBox = new Vector3(maxX - minX, maxY - minY, maxZ - minZ);
893 1021
@@ -916,17 +1044,20 @@ namespace OpenSim.Region.Framework.Scenes
916 Dictionary<UUID,string> states = new Dictionary<UUID,string>(); 1044 Dictionary<UUID,string> states = new Dictionary<UUID,string>();
917 1045
918 // Capture script state while holding the lock 1046 // Capture script state while holding the lock
919 lock (m_parts) 1047 lockPartsForRead(true);
920 { 1048 {
921 foreach (SceneObjectPart part in m_parts.Values) 1049 foreach (SceneObjectPart part in m_parts.Values)
922 { 1050 {
1051
923 Dictionary<UUID,string> pstates = part.Inventory.GetScriptStates(); 1052 Dictionary<UUID,string> pstates = part.Inventory.GetScriptStates();
924 foreach (UUID itemid in pstates.Keys) 1053 foreach (UUID itemid in pstates.Keys)
925 { 1054 {
926 states.Add(itemid, pstates[itemid]); 1055 states.Add(itemid, pstates[itemid]);
927 } 1056 }
1057
928 } 1058 }
929 } 1059 }
1060 lockPartsForRead(false);
930 1061
931 if (states.Count > 0) 1062 if (states.Count > 0)
932 { 1063 {
@@ -1094,13 +1225,16 @@ namespace OpenSim.Region.Framework.Scenes
1094 1225
1095 public override void UpdateMovement() 1226 public override void UpdateMovement()
1096 { 1227 {
1097 lock (m_parts) 1228 lockPartsForRead(true);
1098 { 1229 {
1099 foreach (SceneObjectPart part in m_parts.Values) 1230 foreach (SceneObjectPart part in m_parts.Values)
1100 { 1231 {
1232
1101 part.UpdateMovement(); 1233 part.UpdateMovement();
1234
1102 } 1235 }
1103 } 1236 }
1237 lockPartsForRead(false);
1104 } 1238 }
1105 1239
1106 public ushort GetTimeDilation() 1240 public ushort GetTimeDilation()
@@ -1144,7 +1278,7 @@ namespace OpenSim.Region.Framework.Scenes
1144 /// <param name="part"></param> 1278 /// <param name="part"></param>
1145 public void AddPart(SceneObjectPart part) 1279 public void AddPart(SceneObjectPart part)
1146 { 1280 {
1147 lock (m_parts) 1281 lockPartsForWrite(true);
1148 { 1282 {
1149 part.SetParent(this); 1283 part.SetParent(this);
1150 m_parts.Add(part.UUID, part); 1284 m_parts.Add(part.UUID, part);
@@ -1154,6 +1288,7 @@ namespace OpenSim.Region.Framework.Scenes
1154 if (part.LinkNum == 2 && RootPart != null) 1288 if (part.LinkNum == 2 && RootPart != null)
1155 RootPart.LinkNum = 1; 1289 RootPart.LinkNum = 1;
1156 } 1290 }
1291 lockPartsForWrite(false);
1157 } 1292 }
1158 1293
1159 /// <summary> 1294 /// <summary>
@@ -1161,28 +1296,33 @@ namespace OpenSim.Region.Framework.Scenes
1161 /// </summary> 1296 /// </summary>
1162 private void UpdateParentIDs() 1297 private void UpdateParentIDs()
1163 { 1298 {
1164 lock (m_parts) 1299 lockPartsForRead(true);
1165 { 1300 {
1166 foreach (SceneObjectPart part in m_parts.Values) 1301 foreach (SceneObjectPart part in m_parts.Values)
1167 { 1302 {
1303
1168 if (part.UUID != m_rootPart.UUID) 1304 if (part.UUID != m_rootPart.UUID)
1169 { 1305 {
1170 part.ParentID = m_rootPart.LocalId; 1306 part.ParentID = m_rootPart.LocalId;
1171 } 1307 }
1308
1172 } 1309 }
1173 } 1310 }
1311 lockPartsForRead(false);
1174 } 1312 }
1175 1313
1176 public void RegenerateFullIDs() 1314 public void RegenerateFullIDs()
1177 { 1315 {
1178 lock (m_parts) 1316 lockPartsForRead(true);
1179 { 1317 {
1180 foreach (SceneObjectPart part in m_parts.Values) 1318 foreach (SceneObjectPart part in m_parts.Values)
1181 { 1319 {
1320
1182 part.UUID = UUID.Random(); 1321 part.UUID = UUID.Random();
1183 1322
1184 } 1323 }
1185 } 1324 }
1325 lockPartsForRead(false);
1186 } 1326 }
1187 1327
1188 // helper provided for parts. 1328 // helper provided for parts.
@@ -1263,29 +1403,33 @@ namespace OpenSim.Region.Framework.Scenes
1263 1403
1264 DetachFromBackup(); 1404 DetachFromBackup();
1265 1405
1266 lock (m_parts) 1406 lockPartsForRead(true);
1407 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1408 lockPartsForRead(false);
1409
1410 foreach (SceneObjectPart part in values)
1267 { 1411 {
1268 foreach (SceneObjectPart part in m_parts.Values)
1269 {
1270// part.Inventory.RemoveScriptInstances(); 1412// part.Inventory.RemoveScriptInstances();
1271 1413
1272 ScenePresence[] avatars = Scene.GetScenePresences(); 1414 ScenePresence[] avatars = Scene.GetScenePresences();
1273 for (int i = 0; i < avatars.Length; i++) 1415 for (int i = 0; i < avatars.Length; i++)
1416 {
1417 if (avatars[i].ParentID == LocalId)
1274 { 1418 {
1275 if (avatars[i].ParentID == LocalId) 1419 avatars[i].StandUp();
1276 { 1420 }
1277 avatars[i].StandUp();
1278 }
1279 1421
1280 if (!silent) 1422 if (!silent)
1281 { 1423 {
1282 part.UpdateFlag = 0; 1424 part.UpdateFlag = 0;
1283 if (part == m_rootPart) 1425 if (part == m_rootPart)
1284 avatars[i].ControllingClient.SendKillObject(m_regionHandle, part.LocalId); 1426 avatars[i].ControllingClient.SendKillObject(m_regionHandle, part.LocalId);
1285 }
1286 } 1427 }
1287 } 1428 }
1429
1288 } 1430 }
1431
1432
1289 } 1433 }
1290 1434
1291 public void AddScriptLPS(int count) 1435 public void AddScriptLPS(int count)
@@ -1310,17 +1454,20 @@ namespace OpenSim.Region.Framework.Scenes
1310 1454
1311 scriptEvents aggregateScriptEvents=0; 1455 scriptEvents aggregateScriptEvents=0;
1312 1456
1313 lock (m_parts) 1457 lockPartsForRead(true);
1314 { 1458 {
1315 foreach (SceneObjectPart part in m_parts.Values) 1459 foreach (SceneObjectPart part in m_parts.Values)
1316 { 1460 {
1461
1317 if (part == null) 1462 if (part == null)
1318 continue; 1463 continue;
1319 if (part != RootPart) 1464 if (part != RootPart)
1320 part.ObjectFlags = objectflagupdate; 1465 part.ObjectFlags = objectflagupdate;
1321 aggregateScriptEvents |= part.AggregateScriptEvents; 1466 aggregateScriptEvents |= part.AggregateScriptEvents;
1467
1322 } 1468 }
1323 } 1469 }
1470 lockPartsForRead(false);
1324 1471
1325 m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0); 1472 m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0);
1326 m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0); 1473 m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0);
@@ -1362,42 +1509,52 @@ namespace OpenSim.Region.Framework.Scenes
1362 /// <param name="m_physicalPrim"></param> 1509 /// <param name="m_physicalPrim"></param>
1363 public void ApplyPhysics(bool m_physicalPrim) 1510 public void ApplyPhysics(bool m_physicalPrim)
1364 { 1511 {
1365 lock (m_parts) 1512 lockPartsForRead(true);
1513
1514 if (m_parts.Count > 1)
1366 { 1515 {
1367 if (m_parts.Count > 1) 1516 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1517 lockPartsForRead(false);
1518 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1519 foreach (SceneObjectPart part in values)
1368 { 1520 {
1369 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim); 1521
1370 foreach (SceneObjectPart part in m_parts.Values) 1522 if (part.LocalId != m_rootPart.LocalId)
1371 { 1523 {
1372 if (part.LocalId != m_rootPart.LocalId) 1524 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim);
1373 {
1374 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim);
1375 }
1376 } 1525 }
1377 1526
1378 // Hack to get the physics scene geometries in the right spot
1379 ResetChildPrimPhysicsPositions();
1380 }
1381 else
1382 {
1383 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1384 } 1527 }
1528 // Hack to get the physics scene geometries in the right spot
1529 ResetChildPrimPhysicsPositions();
1530 }
1531 else
1532 {
1533 lockPartsForRead(false);
1534 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1385 } 1535 }
1386 } 1536 }
1387 1537
1388 public void SetOwnerId(UUID userId) 1538 public void SetOwnerId(UUID userId)
1389 { 1539 {
1390 ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); 1540 ForEachPart(delegate(SceneObjectPart part)
1541 {
1542
1543 part.OwnerID = userId;
1544
1545 });
1391 } 1546 }
1392 1547
1393 public void ForEachPart(Action<SceneObjectPart> whatToDo) 1548 public void ForEachPart(Action<SceneObjectPart> whatToDo)
1394 { 1549 {
1395 lock (m_parts) 1550 lockPartsForRead(true);
1551 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1552 lockPartsForRead(false);
1553 foreach (SceneObjectPart part in values)
1396 { 1554 {
1397 foreach (SceneObjectPart part in m_parts.Values) 1555
1398 { 1556 whatToDo(part);
1399 whatToDo(part); 1557
1400 }
1401 } 1558 }
1402 } 1559 }
1403 1560
@@ -1500,14 +1657,17 @@ namespace OpenSim.Region.Framework.Scenes
1500 1657
1501 SendPartFullUpdate(remoteClient, RootPart, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID)); 1658 SendPartFullUpdate(remoteClient, RootPart, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID));
1502 1659
1503 lock (m_parts) 1660 lockPartsForRead(true);
1504 { 1661 {
1505 foreach (SceneObjectPart part in m_parts.Values) 1662 foreach (SceneObjectPart part in m_parts.Values)
1506 { 1663 {
1664
1507 if (part != RootPart) 1665 if (part != RootPart)
1508 SendPartFullUpdate(remoteClient, part, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID)); 1666 SendPartFullUpdate(remoteClient, part, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID));
1667
1509 } 1668 }
1510 } 1669 }
1670 lockPartsForRead(false);
1511 } 1671 }
1512 1672
1513 /// <summary> 1673 /// <summary>
@@ -1606,10 +1766,11 @@ namespace OpenSim.Region.Framework.Scenes
1606 1766
1607 List<SceneObjectPart> partList; 1767 List<SceneObjectPart> partList;
1608 1768
1609 lock (m_parts) 1769 lockPartsForRead(true);
1610 { 1770
1611 partList = new List<SceneObjectPart>(m_parts.Values); 1771 partList = new List<SceneObjectPart>(m_parts.Values);
1612 } 1772
1773 lockPartsForRead(false);
1613 1774
1614 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) 1775 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1615 { 1776 {
@@ -1832,13 +1993,40 @@ namespace OpenSim.Region.Framework.Scenes
1832 } 1993 }
1833 } 1994 }
1834 1995
1996 public void rotLookAt(Quaternion target, float strength, float damping)
1997 {
1998 SceneObjectPart rootpart = m_rootPart;
1999 if (rootpart != null)
2000 {
2001 if (IsAttachment)
2002 {
2003 /*
2004 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
2005 if (avatar != null)
2006 {
2007 Rotate the Av?
2008 } */
2009 }
2010 else
2011 {
2012 if (rootpart.PhysActor != null)
2013 { // APID must be implemented in your physics system for this to function.
2014 rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W);
2015 rootpart.PhysActor.APIDStrength = strength;
2016 rootpart.PhysActor.APIDDamping = damping;
2017 rootpart.PhysActor.APIDActive = true;
2018 }
2019 }
2020 }
2021 }
2022
1835 public void stopLookAt() 2023 public void stopLookAt()
1836 { 2024 {
1837 SceneObjectPart rootpart = m_rootPart; 2025 SceneObjectPart rootpart = m_rootPart;
1838 if (rootpart != null) 2026 if (rootpart != null)
1839 { 2027 {
1840 if (rootpart.PhysActor != null) 2028 if (rootpart.PhysActor != null)
1841 { 2029 { // APID must be implemented in your physics system for this to function.
1842 rootpart.PhysActor.APIDActive = false; 2030 rootpart.PhysActor.APIDActive = false;
1843 } 2031 }
1844 } 2032 }
@@ -1906,10 +2094,11 @@ namespace OpenSim.Region.Framework.Scenes
1906 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 2094 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
1907 newPart.SetParent(this); 2095 newPart.SetParent(this);
1908 2096
1909 lock (m_parts) 2097 lockPartsForWrite(true);
1910 { 2098 {
1911 m_parts.Add(newPart.UUID, newPart); 2099 m_parts.Add(newPart.UUID, newPart);
1912 } 2100 }
2101 lockPartsForWrite(false);
1913 2102
1914 SetPartAsNonRoot(newPart); 2103 SetPartAsNonRoot(newPart);
1915 2104
@@ -1972,7 +2161,7 @@ namespace OpenSim.Region.Framework.Scenes
1972 //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0) 2161 //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
1973 // return; 2162 // return;
1974 2163
1975 lock (m_parts) 2164 lockPartsForRead(true);
1976 { 2165 {
1977 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0); 2166 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0);
1978 2167
@@ -1992,9 +2181,12 @@ namespace OpenSim.Region.Framework.Scenes
1992 { 2181 {
1993 if (!IsSelected) 2182 if (!IsSelected)
1994 part.UpdateLookAt(); 2183 part.UpdateLookAt();
2184
1995 part.SendScheduledUpdates(); 2185 part.SendScheduledUpdates();
2186
1996 } 2187 }
1997 } 2188 }
2189 lockPartsForRead(false);
1998 } 2190 }
1999 2191
2000 public void ScheduleFullUpdateToAvatar(ScenePresence presence) 2192 public void ScheduleFullUpdateToAvatar(ScenePresence presence)
@@ -2004,27 +2196,31 @@ namespace OpenSim.Region.Framework.Scenes
2004 2196
2005 RootPart.AddFullUpdateToAvatar(presence); 2197 RootPart.AddFullUpdateToAvatar(presence);
2006 2198
2007 lock (m_parts) 2199 lockPartsForRead(true);
2008 { 2200 {
2009 foreach (SceneObjectPart part in m_parts.Values) 2201 foreach (SceneObjectPart part in m_parts.Values)
2010 { 2202 {
2203
2011 if (part != RootPart) 2204 if (part != RootPart)
2012 part.AddFullUpdateToAvatar(presence); 2205 part.AddFullUpdateToAvatar(presence);
2206
2013 } 2207 }
2014 } 2208 }
2209 lockPartsForRead(false);
2015 } 2210 }
2016 2211
2017 public void ScheduleTerseUpdateToAvatar(ScenePresence presence) 2212 public void ScheduleTerseUpdateToAvatar(ScenePresence presence)
2018 { 2213 {
2019// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1} just to avatar {2}", Name, UUID, presence.Name); 2214 lockPartsForRead(true);
2020
2021 lock (m_parts)
2022 { 2215 {
2023 foreach (SceneObjectPart part in m_parts.Values) 2216 foreach (SceneObjectPart part in m_parts.Values)
2024 { 2217 {
2218
2025 part.AddTerseUpdateToAvatar(presence); 2219 part.AddTerseUpdateToAvatar(presence);
2220
2026 } 2221 }
2027 } 2222 }
2223 lockPartsForRead(false);
2028 } 2224 }
2029 2225
2030 /// <summary> 2226 /// <summary>
@@ -2038,14 +2234,17 @@ namespace OpenSim.Region.Framework.Scenes
2038 checkAtTargets(); 2234 checkAtTargets();
2039 RootPart.ScheduleFullUpdate(); 2235 RootPart.ScheduleFullUpdate();
2040 2236
2041 lock (m_parts) 2237 lockPartsForRead(true);
2042 { 2238 {
2043 foreach (SceneObjectPart part in m_parts.Values) 2239 foreach (SceneObjectPart part in m_parts.Values)
2044 { 2240 {
2241
2045 if (part != RootPart) 2242 if (part != RootPart)
2046 part.ScheduleFullUpdate(); 2243 part.ScheduleFullUpdate();
2244
2047 } 2245 }
2048 } 2246 }
2247 lockPartsForRead(false);
2049 } 2248 }
2050 2249
2051 /// <summary> 2250 /// <summary>
@@ -2053,15 +2252,16 @@ namespace OpenSim.Region.Framework.Scenes
2053 /// </summary> 2252 /// </summary>
2054 public void ScheduleGroupForTerseUpdate() 2253 public void ScheduleGroupForTerseUpdate()
2055 { 2254 {
2056// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1}", Name, UUID); 2255 lockPartsForRead(true);
2057
2058 lock (m_parts)
2059 { 2256 {
2060 foreach (SceneObjectPart part in m_parts.Values) 2257 foreach (SceneObjectPart part in m_parts.Values)
2061 { 2258 {
2259
2062 part.ScheduleTerseUpdate(); 2260 part.ScheduleTerseUpdate();
2261
2063 } 2262 }
2064 } 2263 }
2264 lockPartsForRead(false);
2065 } 2265 }
2066 2266
2067 /// <summary> 2267 /// <summary>
@@ -2076,14 +2276,17 @@ namespace OpenSim.Region.Framework.Scenes
2076 2276
2077 RootPart.SendFullUpdateToAllClients(); 2277 RootPart.SendFullUpdateToAllClients();
2078 2278
2079 lock (m_parts) 2279 lockPartsForRead(true);
2080 { 2280 {
2081 foreach (SceneObjectPart part in m_parts.Values) 2281 foreach (SceneObjectPart part in m_parts.Values)
2082 { 2282 {
2283
2083 if (part != RootPart) 2284 if (part != RootPart)
2084 part.SendFullUpdateToAllClients(); 2285 part.SendFullUpdateToAllClients();
2286
2085 } 2287 }
2086 } 2288 }
2289 lockPartsForRead(false);
2087 } 2290 }
2088 2291
2089 /// <summary> 2292 /// <summary>
@@ -2115,14 +2318,15 @@ namespace OpenSim.Region.Framework.Scenes
2115 { 2318 {
2116 if (IsDeleted) 2319 if (IsDeleted)
2117 return; 2320 return;
2118 2321
2119 lock (m_parts) 2322 lockPartsForRead(true);
2120 { 2323 {
2121 foreach (SceneObjectPart part in m_parts.Values) 2324 foreach (SceneObjectPart part in m_parts.Values)
2122 { 2325 {
2123 part.SendTerseUpdateToAllClients(); 2326 part.SendTerseUpdateToAllClients();
2124 } 2327 }
2125 } 2328 }
2329 lockPartsForRead(false);
2126 } 2330 }
2127 2331
2128 #endregion 2332 #endregion
@@ -2136,16 +2340,18 @@ namespace OpenSim.Region.Framework.Scenes
2136 /// <returns>null if no child part with that linknum or child part</returns> 2340 /// <returns>null if no child part with that linknum or child part</returns>
2137 public SceneObjectPart GetLinkNumPart(int linknum) 2341 public SceneObjectPart GetLinkNumPart(int linknum)
2138 { 2342 {
2139 lock (m_parts) 2343 lockPartsForRead(true);
2140 { 2344 {
2141 foreach (SceneObjectPart part in m_parts.Values) 2345 foreach (SceneObjectPart part in m_parts.Values)
2142 { 2346 {
2143 if (part.LinkNum == linknum) 2347 if (part.LinkNum == linknum)
2144 { 2348 {
2349 lockPartsForRead(false);
2145 return part; 2350 return part;
2146 } 2351 }
2147 } 2352 }
2148 } 2353 }
2354 lockPartsForRead(false);
2149 2355
2150 return null; 2356 return null;
2151 } 2357 }
@@ -2173,17 +2379,19 @@ namespace OpenSim.Region.Framework.Scenes
2173 public SceneObjectPart GetChildPart(uint localID) 2379 public SceneObjectPart GetChildPart(uint localID)
2174 { 2380 {
2175 //m_log.DebugFormat("Entered looking for {0}", localID); 2381 //m_log.DebugFormat("Entered looking for {0}", localID);
2176 lock (m_parts) 2382 lockPartsForRead(true);
2177 { 2383 {
2178 foreach (SceneObjectPart part in m_parts.Values) 2384 foreach (SceneObjectPart part in m_parts.Values)
2179 { 2385 {
2180 //m_log.DebugFormat("Found {0}", part.LocalId); 2386 //m_log.DebugFormat("Found {0}", part.LocalId);
2181 if (part.LocalId == localID) 2387 if (part.LocalId == localID)
2182 { 2388 {
2389 lockPartsForRead(false);
2183 return part; 2390 return part;
2184 } 2391 }
2185 } 2392 }
2186 } 2393 }
2394 lockPartsForRead(false);
2187 2395
2188 return null; 2396 return null;
2189 } 2397 }
@@ -2213,17 +2421,19 @@ namespace OpenSim.Region.Framework.Scenes
2213 public bool HasChildPrim(uint localID) 2421 public bool HasChildPrim(uint localID)
2214 { 2422 {
2215 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID); 2423 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID);
2216 lock (m_parts) 2424 lockPartsForRead(true);
2217 { 2425 {
2218 foreach (SceneObjectPart part in m_parts.Values) 2426 foreach (SceneObjectPart part in m_parts.Values)
2219 { 2427 {
2220 //m_log.DebugFormat("Found {0}", part.LocalId); 2428 //m_log.DebugFormat("Found {0}", part.LocalId);
2221 if (part.LocalId == localID) 2429 if (part.LocalId == localID)
2222 { 2430 {
2431 lockPartsForRead(false);
2223 return true; 2432 return true;
2224 } 2433 }
2225 } 2434 }
2226 } 2435 }
2436 lockPartsForRead(false);
2227 2437
2228 return false; 2438 return false;
2229 } 2439 }
@@ -2273,53 +2483,57 @@ namespace OpenSim.Region.Framework.Scenes
2273 if (m_rootPart.LinkNum == 0) 2483 if (m_rootPart.LinkNum == 0)
2274 m_rootPart.LinkNum = 1; 2484 m_rootPart.LinkNum = 1;
2275 2485
2276 lock (m_parts) 2486 lockPartsForWrite(true);
2277 { 2487
2278 m_parts.Add(linkPart.UUID, linkPart); 2488 m_parts.Add(linkPart.UUID, linkPart);
2489
2490 lockPartsForWrite(false);
2279 2491
2280 // Insert in terms of link numbers, the new links 2492 // Insert in terms of link numbers, the new links
2281 // before the current ones (with the exception of 2493 // before the current ones (with the exception of
2282 // the root prim. Shuffle the old ones up 2494 // the root prim. Shuffle the old ones up
2283 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts) 2495 lockPartsForRead(true);
2496 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts)
2497 {
2498 if (kvp.Value.LinkNum != 1)
2284 { 2499 {
2285 if (kvp.Value.LinkNum != 1) 2500 // Don't update root prim link number
2286 { 2501 kvp.Value.LinkNum += objectGroup.PrimCount;
2287 // Don't update root prim link number
2288 kvp.Value.LinkNum += objectGroup.PrimCount;
2289 }
2290 } 2502 }
2503 }
2504 lockPartsForRead(false);
2291 2505
2292 linkPart.LinkNum = 2; 2506 linkPart.LinkNum = 2;
2293 2507
2294 linkPart.SetParent(this); 2508 linkPart.SetParent(this);
2295 linkPart.AddFlag(PrimFlags.CreateSelected); 2509 linkPart.AddFlag(PrimFlags.CreateSelected);
2296 2510
2297 //if (linkPart.PhysActor != null) 2511 //if (linkPart.PhysActor != null)
2298 //{ 2512 //{
2299 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); 2513 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor);
2300 2514
2301 //linkPart.PhysActor = null; 2515 //linkPart.PhysActor = null;
2302 //} 2516 //}
2303 2517
2304 //TODO: rest of parts 2518 //TODO: rest of parts
2305 int linkNum = 3; 2519 int linkNum = 3;
2306 foreach (SceneObjectPart part in objectGroup.Children.Values) 2520 foreach (SceneObjectPart part in objectGroup.Children.Values)
2521 {
2522 if (part.UUID != objectGroup.m_rootPart.UUID)
2307 { 2523 {
2308 if (part.UUID != objectGroup.m_rootPart.UUID) 2524 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2309 {
2310 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2311 }
2312 part.ClearUndoState();
2313 } 2525 }
2526 part.ClearUndoState();
2314 } 2527 }
2315 2528
2316 m_scene.UnlinkSceneObject(objectGroup.UUID, true); 2529 m_scene.UnlinkSceneObject(objectGroup.UUID, true);
2317 objectGroup.m_isDeleted = true; 2530 objectGroup.m_isDeleted = true;
2531
2532 objectGroup.lockPartsForWrite(true);
2318 2533
2319 lock (objectGroup.m_parts) 2534 objectGroup.m_parts.Clear();
2320 { 2535
2321 objectGroup.m_parts.Clear(); 2536 objectGroup.lockPartsForWrite(false);
2322 }
2323 2537
2324 // Can't do this yet since backup still makes use of the root part without any synchronization 2538 // Can't do this yet since backup still makes use of the root part without any synchronization
2325// objectGroup.m_rootPart = null; 2539// objectGroup.m_rootPart = null;
@@ -2389,11 +2603,12 @@ namespace OpenSim.Region.Framework.Scenes
2389 Quaternion worldRot = linkPart.GetWorldRotation(); 2603 Quaternion worldRot = linkPart.GetWorldRotation();
2390 2604
2391 // Remove the part from this object 2605 // Remove the part from this object
2392 lock (m_parts) 2606 lockPartsForWrite(true);
2393 { 2607 {
2394 m_parts.Remove(linkPart.UUID); 2608 m_parts.Remove(linkPart.UUID);
2395 } 2609 }
2396 2610 lockPartsForWrite(false);
2611 lockPartsForRead(true);
2397 if (m_parts.Count == 1 && RootPart != null) //Single prim is left 2612 if (m_parts.Count == 1 && RootPart != null) //Single prim is left
2398 RootPart.LinkNum = 0; 2613 RootPart.LinkNum = 0;
2399 else 2614 else
@@ -2404,6 +2619,7 @@ namespace OpenSim.Region.Framework.Scenes
2404 p.LinkNum--; 2619 p.LinkNum--;
2405 } 2620 }
2406 } 2621 }
2622 lockPartsForRead(false);
2407 2623
2408 linkPart.ParentID = 0; 2624 linkPart.ParentID = 0;
2409 linkPart.LinkNum = 0; 2625 linkPart.LinkNum = 0;
@@ -2725,9 +2941,12 @@ namespace OpenSim.Region.Framework.Scenes
2725 2941
2726 if (selectionPart != null) 2942 if (selectionPart != null)
2727 { 2943 {
2728 lock (m_parts) 2944 lockPartsForRead(true);
2945 List<SceneObjectPart> parts = new List<SceneObjectPart>(m_parts.Values);
2946 lockPartsForRead(false);
2947 foreach (SceneObjectPart part in parts)
2729 { 2948 {
2730 foreach (SceneObjectPart part in m_parts.Values) 2949 if (part.Scale.X > 10.0 || part.Scale.Y > 10.0 || part.Scale.Z > 10.0)
2731 { 2950 {
2732 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax || 2951 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax ||
2733 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax || 2952 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax ||
@@ -2737,12 +2956,13 @@ namespace OpenSim.Region.Framework.Scenes
2737 break; 2956 break;
2738 } 2957 }
2739 } 2958 }
2959 }
2740 2960
2741 foreach (SceneObjectPart part in m_parts.Values) 2961 foreach (SceneObjectPart part in parts)
2742 { 2962 {
2743 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect); 2963 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
2744 }
2745 } 2964 }
2965
2746 } 2966 }
2747 } 2967 }
2748 2968
@@ -2828,11 +3048,9 @@ namespace OpenSim.Region.Framework.Scenes
2828 scale.Y = m_scene.m_maxNonphys; 3048 scale.Y = m_scene.m_maxNonphys;
2829 if (scale.Z > m_scene.m_maxNonphys) 3049 if (scale.Z > m_scene.m_maxNonphys)
2830 scale.Z = m_scene.m_maxNonphys; 3050 scale.Z = m_scene.m_maxNonphys;
2831
2832 SceneObjectPart part = GetChildPart(localID); 3051 SceneObjectPart part = GetChildPart(localID);
2833 if (part != null) 3052 if (part != null)
2834 { 3053 {
2835 part.Resize(scale);
2836 if (part.PhysActor != null) 3054 if (part.PhysActor != null)
2837 { 3055 {
2838 if (part.PhysActor.IsPhysical) 3056 if (part.PhysActor.IsPhysical)
@@ -2847,7 +3065,7 @@ namespace OpenSim.Region.Framework.Scenes
2847 part.PhysActor.Size = scale; 3065 part.PhysActor.Size = scale;
2848 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); 3066 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor);
2849 } 3067 }
2850 //if (part.UUID != m_rootPart.UUID) 3068 part.Resize(scale);
2851 3069
2852 HasGroupChanged = true; 3070 HasGroupChanged = true;
2853 ScheduleGroupForFullUpdate(); 3071 ScheduleGroupForFullUpdate();
@@ -2889,73 +3107,71 @@ namespace OpenSim.Region.Framework.Scenes
2889 float y = (scale.Y / part.Scale.Y); 3107 float y = (scale.Y / part.Scale.Y);
2890 float z = (scale.Z / part.Scale.Z); 3108 float z = (scale.Z / part.Scale.Z);
2891 3109
2892 lock (m_parts) 3110 lockPartsForRead(true);
3111 if (x > 1.0f || y > 1.0f || z > 1.0f)
2893 { 3112 {
2894 if (x > 1.0f || y > 1.0f || z > 1.0f) 3113 foreach (SceneObjectPart obPart in m_parts.Values)
2895 { 3114 {
2896 foreach (SceneObjectPart obPart in m_parts.Values) 3115 if (obPart.UUID != m_rootPart.UUID)
2897 { 3116 {
2898 if (obPart.UUID != m_rootPart.UUID) 3117 obPart.IgnoreUndoUpdate = true;
2899 { 3118 Vector3 oldSize = new Vector3(obPart.Scale);
2900 obPart.IgnoreUndoUpdate = true;
2901 Vector3 oldSize = new Vector3(obPart.Scale);
2902 3119
2903 float f = 1.0f; 3120 float f = 1.0f;
2904 float a = 1.0f; 3121 float a = 1.0f;
2905 3122
2906 if (part.PhysActor != null && part.PhysActor.IsPhysical) 3123 if (part.PhysActor != null && part.PhysActor.IsPhysical)
3124 {
3125 if (oldSize.X*x > m_scene.m_maxPhys)
2907 { 3126 {
2908 if (oldSize.X*x > m_scene.m_maxPhys) 3127 f = m_scene.m_maxPhys / oldSize.X;
2909 { 3128 a = f / x;
2910 f = m_scene.m_maxPhys / oldSize.X; 3129 x *= a;
2911 a = f / x; 3130 y *= a;
2912 x *= a; 3131 z *= a;
2913 y *= a;
2914 z *= a;
2915 }
2916 if (oldSize.Y*y > m_scene.m_maxPhys)
2917 {
2918 f = m_scene.m_maxPhys / oldSize.Y;
2919 a = f / y;
2920 x *= a;
2921 y *= a;
2922 z *= a;
2923 }
2924 if (oldSize.Z*z > m_scene.m_maxPhys)
2925 {
2926 f = m_scene.m_maxPhys / oldSize.Z;
2927 a = f / z;
2928 x *= a;
2929 y *= a;
2930 z *= a;
2931 }
2932 } 3132 }
2933 else 3133 if (oldSize.Y*y > m_scene.m_maxPhys)
2934 { 3134 {
2935 if (oldSize.X*x > m_scene.m_maxNonphys) 3135 f = m_scene.m_maxPhys / oldSize.Y;
2936 { 3136 a = f / y;
2937 f = m_scene.m_maxNonphys / oldSize.X; 3137 x *= a;
2938 a = f / x; 3138 y *= a;
2939 x *= a; 3139 z *= a;
2940 y *= a; 3140 }
2941 z *= a; 3141 if (oldSize.Z*z > m_scene.m_maxPhys)
2942 } 3142 {
2943 if (oldSize.Y*y > m_scene.m_maxNonphys) 3143 f = m_scene.m_maxPhys / oldSize.Z;
2944 { 3144 a = f / z;
2945 f = m_scene.m_maxNonphys / oldSize.Y; 3145 x *= a;
2946 a = f / y; 3146 y *= a;
2947 x *= a; 3147 z *= a;
2948 y *= a; 3148 }
2949 z *= a; 3149 }
2950 } 3150 else
2951 if (oldSize.Z*z > m_scene.m_maxNonphys) 3151 {
2952 { 3152 if (oldSize.X*x > m_scene.m_maxNonphys)
2953 f = m_scene.m_maxNonphys / oldSize.Z; 3153 {
2954 a = f / z; 3154 f = m_scene.m_maxNonphys / oldSize.X;
2955 x *= a; 3155 a = f / x;
2956 y *= a; 3156 x *= a;
2957 z *= a; 3157 y *= a;
2958 } 3158 z *= a;
3159 }
3160 if (oldSize.Y*y > m_scene.m_maxNonphys)
3161 {
3162 f = m_scene.m_maxNonphys / oldSize.Y;
3163 a = f / y;
3164 x *= a;
3165 y *= a;
3166 z *= a;
3167 }
3168 if (oldSize.Z*z > m_scene.m_maxNonphys)
3169 {
3170 f = m_scene.m_maxNonphys / oldSize.Z;
3171 a = f / z;
3172 x *= a;
3173 y *= a;
3174 z *= a;
2959 } 3175 }
2960 obPart.IgnoreUndoUpdate = false; 3176 obPart.IgnoreUndoUpdate = false;
2961 obPart.StoreUndoState(); 3177 obPart.StoreUndoState();
@@ -2963,6 +3179,7 @@ namespace OpenSim.Region.Framework.Scenes
2963 } 3179 }
2964 } 3180 }
2965 } 3181 }
3182 lockPartsForRead(false);
2966 3183
2967 Vector3 prevScale = part.Scale; 3184 Vector3 prevScale = part.Scale;
2968 prevScale.X *= x; 3185 prevScale.X *= x;
@@ -2970,7 +3187,7 @@ namespace OpenSim.Region.Framework.Scenes
2970 prevScale.Z *= z; 3187 prevScale.Z *= z;
2971 part.Resize(prevScale); 3188 part.Resize(prevScale);
2972 3189
2973 lock (m_parts) 3190 lockPartsForRead(true);
2974 { 3191 {
2975 foreach (SceneObjectPart obPart in m_parts.Values) 3192 foreach (SceneObjectPart obPart in m_parts.Values)
2976 { 3193 {
@@ -2992,6 +3209,7 @@ namespace OpenSim.Region.Framework.Scenes
2992 obPart.StoreUndoState(); 3209 obPart.StoreUndoState();
2993 } 3210 }
2994 } 3211 }
3212 lockPartsForRead(false);
2995 3213
2996 if (part.PhysActor != null) 3214 if (part.PhysActor != null)
2997 { 3215 {
@@ -3094,7 +3312,7 @@ namespace OpenSim.Region.Framework.Scenes
3094 axDiff *= Quaternion.Inverse(partRotation); 3312 axDiff *= Quaternion.Inverse(partRotation);
3095 diff = axDiff; 3313 diff = axDiff;
3096 3314
3097 lock (m_parts) 3315 lockPartsForRead(true);
3098 { 3316 {
3099 foreach (SceneObjectPart obPart in m_parts.Values) 3317 foreach (SceneObjectPart obPart in m_parts.Values)
3100 { 3318 {
@@ -3104,6 +3322,7 @@ namespace OpenSim.Region.Framework.Scenes
3104 } 3322 }
3105 } 3323 }
3106 } 3324 }
3325 lockPartsForRead(false);
3107 3326
3108 AbsolutePosition = newPos; 3327 AbsolutePosition = newPos;
3109 3328
@@ -3237,25 +3456,25 @@ namespace OpenSim.Region.Framework.Scenes
3237 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); 3456 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
3238 } 3457 }
3239 3458
3240 lock (m_parts) 3459 lockPartsForRead(true);
3460
3461 foreach (SceneObjectPart prim in m_parts.Values)
3241 { 3462 {
3242 foreach (SceneObjectPart prim in m_parts.Values) 3463 if (prim.UUID != m_rootPart.UUID)
3243 { 3464 {
3244 if (prim.UUID != m_rootPart.UUID) 3465 prim.IgnoreUndoUpdate = true;
3245 { 3466 Vector3 axPos = prim.OffsetPosition;
3246 prim.IgnoreUndoUpdate = true; 3467 axPos *= oldParentRot;
3247 Vector3 axPos = prim.OffsetPosition; 3468 axPos *= Quaternion.Inverse(axRot);
3248 axPos *= oldParentRot; 3469 prim.OffsetPosition = axPos;
3249 axPos *= Quaternion.Inverse(axRot); 3470 Quaternion primsRot = prim.RotationOffset;
3250 prim.OffsetPosition = axPos; 3471 Quaternion newRot = primsRot * oldParentRot;
3251 Quaternion primsRot = prim.RotationOffset; 3472 newRot *= Quaternion.Inverse(axRot);
3252 Quaternion newRot = primsRot * oldParentRot; 3473 prim.RotationOffset = newRot;
3253 newRot *= Quaternion.Inverse(axRot); 3474 prim.ScheduleTerseUpdate();
3254 prim.RotationOffset = newRot;
3255 prim.ScheduleTerseUpdate();
3256 }
3257 } 3475 }
3258 } 3476 }
3477
3259 foreach (SceneObjectPart childpart in Children.Values) 3478 foreach (SceneObjectPart childpart in Children.Values)
3260 { 3479 {
3261 if (childpart != m_rootPart) 3480 if (childpart != m_rootPart)
@@ -3264,6 +3483,9 @@ namespace OpenSim.Region.Framework.Scenes
3264 childpart.StoreUndoState(); 3483 childpart.StoreUndoState();
3265 } 3484 }
3266 } 3485 }
3486
3487 lockPartsForRead(false);
3488
3267 m_rootPart.ScheduleTerseUpdate(); 3489 m_rootPart.ScheduleTerseUpdate();
3268 } 3490 }
3269 3491
@@ -3385,7 +3607,7 @@ namespace OpenSim.Region.Framework.Scenes
3385 if (atTargets.Count > 0) 3607 if (atTargets.Count > 0)
3386 { 3608 {
3387 uint[] localids = new uint[0]; 3609 uint[] localids = new uint[0];
3388 lock (m_parts) 3610 lockPartsForRead(true);
3389 { 3611 {
3390 localids = new uint[m_parts.Count]; 3612 localids = new uint[m_parts.Count];
3391 int cntr = 0; 3613 int cntr = 0;
@@ -3395,6 +3617,7 @@ namespace OpenSim.Region.Framework.Scenes
3395 cntr++; 3617 cntr++;
3396 } 3618 }
3397 } 3619 }
3620 lockPartsForRead(false);
3398 3621
3399 for (int ctr = 0; ctr < localids.Length; ctr++) 3622 for (int ctr = 0; ctr < localids.Length; ctr++)
3400 { 3623 {
@@ -3413,7 +3636,7 @@ namespace OpenSim.Region.Framework.Scenes
3413 { 3636 {
3414 //trigger not_at_target 3637 //trigger not_at_target
3415 uint[] localids = new uint[0]; 3638 uint[] localids = new uint[0];
3416 lock (m_parts) 3639 lockPartsForRead(true);
3417 { 3640 {
3418 localids = new uint[m_parts.Count]; 3641 localids = new uint[m_parts.Count];
3419 int cntr = 0; 3642 int cntr = 0;
@@ -3423,7 +3646,8 @@ namespace OpenSim.Region.Framework.Scenes
3423 cntr++; 3646 cntr++;
3424 } 3647 }
3425 } 3648 }
3426 3649 lockPartsForRead(false);
3650
3427 for (int ctr = 0; ctr < localids.Length; ctr++) 3651 for (int ctr = 0; ctr < localids.Length; ctr++)
3428 { 3652 {
3429 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]); 3653 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]);
@@ -3515,19 +3739,20 @@ namespace OpenSim.Region.Framework.Scenes
3515 public float GetMass() 3739 public float GetMass()
3516 { 3740 {
3517 float retmass = 0f; 3741 float retmass = 0f;
3518 lock (m_parts) 3742 lockPartsForRead(true);
3519 { 3743 {
3520 foreach (SceneObjectPart part in m_parts.Values) 3744 foreach (SceneObjectPart part in m_parts.Values)
3521 { 3745 {
3522 retmass += part.GetMass(); 3746 retmass += part.GetMass();
3523 } 3747 }
3524 } 3748 }
3749 lockPartsForRead(false);
3525 return retmass; 3750 return retmass;
3526 } 3751 }
3527 3752
3528 public void CheckSculptAndLoad() 3753 public void CheckSculptAndLoad()
3529 { 3754 {
3530 lock (m_parts) 3755 lockPartsForRead(true);
3531 { 3756 {
3532 if (!IsDeleted) 3757 if (!IsDeleted)
3533 { 3758 {
@@ -3552,6 +3777,7 @@ namespace OpenSim.Region.Framework.Scenes
3552 } 3777 }
3553 } 3778 }
3554 } 3779 }
3780 lockPartsForRead(false);
3555 } 3781 }
3556 3782
3557 protected void AssetReceived(string id, Object sender, AssetBase asset) 3783 protected void AssetReceived(string id, Object sender, AssetBase asset)
@@ -3572,7 +3798,7 @@ namespace OpenSim.Region.Framework.Scenes
3572 /// <param name="client"></param> 3798 /// <param name="client"></param>
3573 public void SetGroup(UUID GroupID, IClientAPI client) 3799 public void SetGroup(UUID GroupID, IClientAPI client)
3574 { 3800 {
3575 lock (m_parts) 3801 lockPartsForRead(true);
3576 { 3802 {
3577 foreach (SceneObjectPart part in m_parts.Values) 3803 foreach (SceneObjectPart part in m_parts.Values)
3578 { 3804 {
@@ -3582,6 +3808,7 @@ namespace OpenSim.Region.Framework.Scenes
3582 3808
3583 HasGroupChanged = true; 3809 HasGroupChanged = true;
3584 } 3810 }
3811 lockPartsForRead(false);
3585 3812
3586 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled 3813 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled
3587 // for the same object with very different properties. The caller must schedule the update. 3814 // for the same object with very different properties. The caller must schedule the update.
@@ -3603,11 +3830,12 @@ namespace OpenSim.Region.Framework.Scenes
3603 3830
3604 public void SetAttachmentPoint(byte point) 3831 public void SetAttachmentPoint(byte point)
3605 { 3832 {
3606 lock (m_parts) 3833 lockPartsForRead(true);
3607 { 3834 {
3608 foreach (SceneObjectPart part in m_parts.Values) 3835 foreach (SceneObjectPart part in m_parts.Values)
3609 part.SetAttachmentPoint(point); 3836 part.SetAttachmentPoint(point);
3610 } 3837 }
3838 lockPartsForRead(false);
3611 } 3839 }
3612 3840
3613 #region ISceneObject 3841 #region ISceneObject