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 602b811..edaf1a0 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
@@ -1496,14 +1653,17 @@ namespace OpenSim.Region.Framework.Scenes
1496 { 1653 {
1497 SendPartFullUpdate(remoteClient, RootPart, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID)); 1654 SendPartFullUpdate(remoteClient, RootPart, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID));
1498 1655
1499 lock (m_parts) 1656 lockPartsForRead(true);
1500 { 1657 {
1501 foreach (SceneObjectPart part in m_parts.Values) 1658 foreach (SceneObjectPart part in m_parts.Values)
1502 { 1659 {
1660
1503 if (part != RootPart) 1661 if (part != RootPart)
1504 SendPartFullUpdate(remoteClient, part, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID)); 1662 SendPartFullUpdate(remoteClient, part, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID));
1663
1505 } 1664 }
1506 } 1665 }
1666 lockPartsForRead(false);
1507 } 1667 }
1508 1668
1509 /// <summary> 1669 /// <summary>
@@ -1601,10 +1761,11 @@ namespace OpenSim.Region.Framework.Scenes
1601 1761
1602 List<SceneObjectPart> partList; 1762 List<SceneObjectPart> partList;
1603 1763
1604 lock (m_parts) 1764 lockPartsForRead(true);
1605 { 1765
1606 partList = new List<SceneObjectPart>(m_parts.Values); 1766 partList = new List<SceneObjectPart>(m_parts.Values);
1607 } 1767
1768 lockPartsForRead(false);
1608 1769
1609 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) 1770 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1610 { 1771 {
@@ -1827,13 +1988,40 @@ namespace OpenSim.Region.Framework.Scenes
1827 } 1988 }
1828 } 1989 }
1829 1990
1991 public void rotLookAt(Quaternion target, float strength, float damping)
1992 {
1993 SceneObjectPart rootpart = m_rootPart;
1994 if (rootpart != null)
1995 {
1996 if (IsAttachment)
1997 {
1998 /*
1999 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
2000 if (avatar != null)
2001 {
2002 Rotate the Av?
2003 } */
2004 }
2005 else
2006 {
2007 if (rootpart.PhysActor != null)
2008 { // APID must be implemented in your physics system for this to function.
2009 rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W);
2010 rootpart.PhysActor.APIDStrength = strength;
2011 rootpart.PhysActor.APIDDamping = damping;
2012 rootpart.PhysActor.APIDActive = true;
2013 }
2014 }
2015 }
2016 }
2017
1830 public void stopLookAt() 2018 public void stopLookAt()
1831 { 2019 {
1832 SceneObjectPart rootpart = m_rootPart; 2020 SceneObjectPart rootpart = m_rootPart;
1833 if (rootpart != null) 2021 if (rootpart != null)
1834 { 2022 {
1835 if (rootpart.PhysActor != null) 2023 if (rootpart.PhysActor != null)
1836 { 2024 { // APID must be implemented in your physics system for this to function.
1837 rootpart.PhysActor.APIDActive = false; 2025 rootpart.PhysActor.APIDActive = false;
1838 } 2026 }
1839 } 2027 }
@@ -1901,10 +2089,11 @@ namespace OpenSim.Region.Framework.Scenes
1901 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 2089 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
1902 newPart.SetParent(this); 2090 newPart.SetParent(this);
1903 2091
1904 lock (m_parts) 2092 lockPartsForWrite(true);
1905 { 2093 {
1906 m_parts.Add(newPart.UUID, newPart); 2094 m_parts.Add(newPart.UUID, newPart);
1907 } 2095 }
2096 lockPartsForWrite(false);
1908 2097
1909 SetPartAsNonRoot(newPart); 2098 SetPartAsNonRoot(newPart);
1910 2099
@@ -1967,7 +2156,7 @@ namespace OpenSim.Region.Framework.Scenes
1967 //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0) 2156 //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
1968 // return; 2157 // return;
1969 2158
1970 lock (m_parts) 2159 lockPartsForRead(true);
1971 { 2160 {
1972 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0); 2161 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0);
1973 2162
@@ -1987,9 +2176,12 @@ namespace OpenSim.Region.Framework.Scenes
1987 { 2176 {
1988 if (!IsSelected) 2177 if (!IsSelected)
1989 part.UpdateLookAt(); 2178 part.UpdateLookAt();
2179
1990 part.SendScheduledUpdates(); 2180 part.SendScheduledUpdates();
2181
1991 } 2182 }
1992 } 2183 }
2184 lockPartsForRead(false);
1993 } 2185 }
1994 2186
1995 public void ScheduleFullUpdateToAvatar(ScenePresence presence) 2187 public void ScheduleFullUpdateToAvatar(ScenePresence presence)
@@ -1998,27 +2190,31 @@ namespace OpenSim.Region.Framework.Scenes
1998 2190
1999 RootPart.AddFullUpdateToAvatar(presence); 2191 RootPart.AddFullUpdateToAvatar(presence);
2000 2192
2001 lock (m_parts) 2193 lockPartsForRead(true);
2002 { 2194 {
2003 foreach (SceneObjectPart part in m_parts.Values) 2195 foreach (SceneObjectPart part in m_parts.Values)
2004 { 2196 {
2197
2005 if (part != RootPart) 2198 if (part != RootPart)
2006 part.AddFullUpdateToAvatar(presence); 2199 part.AddFullUpdateToAvatar(presence);
2200
2007 } 2201 }
2008 } 2202 }
2203 lockPartsForRead(false);
2009 } 2204 }
2010 2205
2011 public void ScheduleTerseUpdateToAvatar(ScenePresence presence) 2206 public void ScheduleTerseUpdateToAvatar(ScenePresence presence)
2012 { 2207 {
2013// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1} just to avatar {2}", Name, UUID, presence.Name); 2208 lockPartsForRead(true);
2014
2015 lock (m_parts)
2016 { 2209 {
2017 foreach (SceneObjectPart part in m_parts.Values) 2210 foreach (SceneObjectPart part in m_parts.Values)
2018 { 2211 {
2212
2019 part.AddTerseUpdateToAvatar(presence); 2213 part.AddTerseUpdateToAvatar(presence);
2214
2020 } 2215 }
2021 } 2216 }
2217 lockPartsForRead(false);
2022 } 2218 }
2023 2219
2024 /// <summary> 2220 /// <summary>
@@ -2031,14 +2227,17 @@ namespace OpenSim.Region.Framework.Scenes
2031 checkAtTargets(); 2227 checkAtTargets();
2032 RootPart.ScheduleFullUpdate(); 2228 RootPart.ScheduleFullUpdate();
2033 2229
2034 lock (m_parts) 2230 lockPartsForRead(true);
2035 { 2231 {
2036 foreach (SceneObjectPart part in m_parts.Values) 2232 foreach (SceneObjectPart part in m_parts.Values)
2037 { 2233 {
2234
2038 if (part != RootPart) 2235 if (part != RootPart)
2039 part.ScheduleFullUpdate(); 2236 part.ScheduleFullUpdate();
2237
2040 } 2238 }
2041 } 2239 }
2240 lockPartsForRead(false);
2042 } 2241 }
2043 2242
2044 /// <summary> 2243 /// <summary>
@@ -2046,15 +2245,16 @@ namespace OpenSim.Region.Framework.Scenes
2046 /// </summary> 2245 /// </summary>
2047 public void ScheduleGroupForTerseUpdate() 2246 public void ScheduleGroupForTerseUpdate()
2048 { 2247 {
2049// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1}", Name, UUID); 2248 lockPartsForRead(true);
2050
2051 lock (m_parts)
2052 { 2249 {
2053 foreach (SceneObjectPart part in m_parts.Values) 2250 foreach (SceneObjectPart part in m_parts.Values)
2054 { 2251 {
2252
2055 part.ScheduleTerseUpdate(); 2253 part.ScheduleTerseUpdate();
2254
2056 } 2255 }
2057 } 2256 }
2257 lockPartsForRead(false);
2058 } 2258 }
2059 2259
2060 /// <summary> 2260 /// <summary>
@@ -2069,14 +2269,17 @@ namespace OpenSim.Region.Framework.Scenes
2069 2269
2070 RootPart.SendFullUpdateToAllClients(); 2270 RootPart.SendFullUpdateToAllClients();
2071 2271
2072 lock (m_parts) 2272 lockPartsForRead(true);
2073 { 2273 {
2074 foreach (SceneObjectPart part in m_parts.Values) 2274 foreach (SceneObjectPart part in m_parts.Values)
2075 { 2275 {
2276
2076 if (part != RootPart) 2277 if (part != RootPart)
2077 part.SendFullUpdateToAllClients(); 2278 part.SendFullUpdateToAllClients();
2279
2078 } 2280 }
2079 } 2281 }
2282 lockPartsForRead(false);
2080 } 2283 }
2081 2284
2082 /// <summary> 2285 /// <summary>
@@ -2108,14 +2311,15 @@ namespace OpenSim.Region.Framework.Scenes
2108 { 2311 {
2109 if (IsDeleted) 2312 if (IsDeleted)
2110 return; 2313 return;
2111 2314
2112 lock (m_parts) 2315 lockPartsForRead(true);
2113 { 2316 {
2114 foreach (SceneObjectPart part in m_parts.Values) 2317 foreach (SceneObjectPart part in m_parts.Values)
2115 { 2318 {
2116 part.SendTerseUpdateToAllClients(); 2319 part.SendTerseUpdateToAllClients();
2117 } 2320 }
2118 } 2321 }
2322 lockPartsForRead(false);
2119 } 2323 }
2120 2324
2121 #endregion 2325 #endregion
@@ -2129,16 +2333,18 @@ namespace OpenSim.Region.Framework.Scenes
2129 /// <returns>null if no child part with that linknum or child part</returns> 2333 /// <returns>null if no child part with that linknum or child part</returns>
2130 public SceneObjectPart GetLinkNumPart(int linknum) 2334 public SceneObjectPart GetLinkNumPart(int linknum)
2131 { 2335 {
2132 lock (m_parts) 2336 lockPartsForRead(true);
2133 { 2337 {
2134 foreach (SceneObjectPart part in m_parts.Values) 2338 foreach (SceneObjectPart part in m_parts.Values)
2135 { 2339 {
2136 if (part.LinkNum == linknum) 2340 if (part.LinkNum == linknum)
2137 { 2341 {
2342 lockPartsForRead(false);
2138 return part; 2343 return part;
2139 } 2344 }
2140 } 2345 }
2141 } 2346 }
2347 lockPartsForRead(false);
2142 2348
2143 return null; 2349 return null;
2144 } 2350 }
@@ -2166,17 +2372,19 @@ namespace OpenSim.Region.Framework.Scenes
2166 public SceneObjectPart GetChildPart(uint localID) 2372 public SceneObjectPart GetChildPart(uint localID)
2167 { 2373 {
2168 //m_log.DebugFormat("Entered looking for {0}", localID); 2374 //m_log.DebugFormat("Entered looking for {0}", localID);
2169 lock (m_parts) 2375 lockPartsForRead(true);
2170 { 2376 {
2171 foreach (SceneObjectPart part in m_parts.Values) 2377 foreach (SceneObjectPart part in m_parts.Values)
2172 { 2378 {
2173 //m_log.DebugFormat("Found {0}", part.LocalId); 2379 //m_log.DebugFormat("Found {0}", part.LocalId);
2174 if (part.LocalId == localID) 2380 if (part.LocalId == localID)
2175 { 2381 {
2382 lockPartsForRead(false);
2176 return part; 2383 return part;
2177 } 2384 }
2178 } 2385 }
2179 } 2386 }
2387 lockPartsForRead(false);
2180 2388
2181 return null; 2389 return null;
2182 } 2390 }
@@ -2206,17 +2414,19 @@ namespace OpenSim.Region.Framework.Scenes
2206 public bool HasChildPrim(uint localID) 2414 public bool HasChildPrim(uint localID)
2207 { 2415 {
2208 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID); 2416 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID);
2209 lock (m_parts) 2417 lockPartsForRead(true);
2210 { 2418 {
2211 foreach (SceneObjectPart part in m_parts.Values) 2419 foreach (SceneObjectPart part in m_parts.Values)
2212 { 2420 {
2213 //m_log.DebugFormat("Found {0}", part.LocalId); 2421 //m_log.DebugFormat("Found {0}", part.LocalId);
2214 if (part.LocalId == localID) 2422 if (part.LocalId == localID)
2215 { 2423 {
2424 lockPartsForRead(false);
2216 return true; 2425 return true;
2217 } 2426 }
2218 } 2427 }
2219 } 2428 }
2429 lockPartsForRead(false);
2220 2430
2221 return false; 2431 return false;
2222 } 2432 }
@@ -2266,53 +2476,57 @@ namespace OpenSim.Region.Framework.Scenes
2266 if (m_rootPart.LinkNum == 0) 2476 if (m_rootPart.LinkNum == 0)
2267 m_rootPart.LinkNum = 1; 2477 m_rootPart.LinkNum = 1;
2268 2478
2269 lock (m_parts) 2479 lockPartsForWrite(true);
2270 { 2480
2271 m_parts.Add(linkPart.UUID, linkPart); 2481 m_parts.Add(linkPart.UUID, linkPart);
2482
2483 lockPartsForWrite(false);
2272 2484
2273 // Insert in terms of link numbers, the new links 2485 // Insert in terms of link numbers, the new links
2274 // before the current ones (with the exception of 2486 // before the current ones (with the exception of
2275 // the root prim. Shuffle the old ones up 2487 // the root prim. Shuffle the old ones up
2276 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts) 2488 lockPartsForRead(true);
2489 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts)
2490 {
2491 if (kvp.Value.LinkNum != 1)
2277 { 2492 {
2278 if (kvp.Value.LinkNum != 1) 2493 // Don't update root prim link number
2279 { 2494 kvp.Value.LinkNum += objectGroup.PrimCount;
2280 // Don't update root prim link number
2281 kvp.Value.LinkNum += objectGroup.PrimCount;
2282 }
2283 } 2495 }
2496 }
2497 lockPartsForRead(false);
2284 2498
2285 linkPart.LinkNum = 2; 2499 linkPart.LinkNum = 2;
2286 2500
2287 linkPart.SetParent(this); 2501 linkPart.SetParent(this);
2288 linkPart.AddFlag(PrimFlags.CreateSelected); 2502 linkPart.AddFlag(PrimFlags.CreateSelected);
2289 2503
2290 //if (linkPart.PhysActor != null) 2504 //if (linkPart.PhysActor != null)
2291 //{ 2505 //{
2292 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); 2506 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor);
2293 2507
2294 //linkPart.PhysActor = null; 2508 //linkPart.PhysActor = null;
2295 //} 2509 //}
2296 2510
2297 //TODO: rest of parts 2511 //TODO: rest of parts
2298 int linkNum = 3; 2512 int linkNum = 3;
2299 foreach (SceneObjectPart part in objectGroup.Children.Values) 2513 foreach (SceneObjectPart part in objectGroup.Children.Values)
2514 {
2515 if (part.UUID != objectGroup.m_rootPart.UUID)
2300 { 2516 {
2301 if (part.UUID != objectGroup.m_rootPart.UUID) 2517 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2302 {
2303 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2304 }
2305 part.ClearUndoState();
2306 } 2518 }
2519 part.ClearUndoState();
2307 } 2520 }
2308 2521
2309 m_scene.UnlinkSceneObject(objectGroup.UUID, true); 2522 m_scene.UnlinkSceneObject(objectGroup.UUID, true);
2310 objectGroup.m_isDeleted = true; 2523 objectGroup.m_isDeleted = true;
2524
2525 objectGroup.lockPartsForWrite(true);
2311 2526
2312 lock (objectGroup.m_parts) 2527 objectGroup.m_parts.Clear();
2313 { 2528
2314 objectGroup.m_parts.Clear(); 2529 objectGroup.lockPartsForWrite(false);
2315 }
2316 2530
2317 // Can't do this yet since backup still makes use of the root part without any synchronization 2531 // Can't do this yet since backup still makes use of the root part without any synchronization
2318// objectGroup.m_rootPart = null; 2532// objectGroup.m_rootPart = null;
@@ -2382,11 +2596,12 @@ namespace OpenSim.Region.Framework.Scenes
2382 Quaternion worldRot = linkPart.GetWorldRotation(); 2596 Quaternion worldRot = linkPart.GetWorldRotation();
2383 2597
2384 // Remove the part from this object 2598 // Remove the part from this object
2385 lock (m_parts) 2599 lockPartsForWrite(true);
2386 { 2600 {
2387 m_parts.Remove(linkPart.UUID); 2601 m_parts.Remove(linkPart.UUID);
2388 } 2602 }
2389 2603 lockPartsForWrite(false);
2604 lockPartsForRead(true);
2390 if (m_parts.Count == 1 && RootPart != null) //Single prim is left 2605 if (m_parts.Count == 1 && RootPart != null) //Single prim is left
2391 RootPart.LinkNum = 0; 2606 RootPart.LinkNum = 0;
2392 else 2607 else
@@ -2397,6 +2612,7 @@ namespace OpenSim.Region.Framework.Scenes
2397 p.LinkNum--; 2612 p.LinkNum--;
2398 } 2613 }
2399 } 2614 }
2615 lockPartsForRead(false);
2400 2616
2401 linkPart.ParentID = 0; 2617 linkPart.ParentID = 0;
2402 linkPart.LinkNum = 0; 2618 linkPart.LinkNum = 0;
@@ -2718,9 +2934,12 @@ namespace OpenSim.Region.Framework.Scenes
2718 2934
2719 if (selectionPart != null) 2935 if (selectionPart != null)
2720 { 2936 {
2721 lock (m_parts) 2937 lockPartsForRead(true);
2938 List<SceneObjectPart> parts = new List<SceneObjectPart>(m_parts.Values);
2939 lockPartsForRead(false);
2940 foreach (SceneObjectPart part in parts)
2722 { 2941 {
2723 foreach (SceneObjectPart part in m_parts.Values) 2942 if (part.Scale.X > 10.0 || part.Scale.Y > 10.0 || part.Scale.Z > 10.0)
2724 { 2943 {
2725 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax || 2944 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax ||
2726 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax || 2945 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax ||
@@ -2730,12 +2949,13 @@ namespace OpenSim.Region.Framework.Scenes
2730 break; 2949 break;
2731 } 2950 }
2732 } 2951 }
2952 }
2733 2953
2734 foreach (SceneObjectPart part in m_parts.Values) 2954 foreach (SceneObjectPart part in parts)
2735 { 2955 {
2736 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect); 2956 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
2737 }
2738 } 2957 }
2958
2739 } 2959 }
2740 } 2960 }
2741 2961
@@ -2821,11 +3041,9 @@ namespace OpenSim.Region.Framework.Scenes
2821 scale.Y = m_scene.m_maxNonphys; 3041 scale.Y = m_scene.m_maxNonphys;
2822 if (scale.Z > m_scene.m_maxNonphys) 3042 if (scale.Z > m_scene.m_maxNonphys)
2823 scale.Z = m_scene.m_maxNonphys; 3043 scale.Z = m_scene.m_maxNonphys;
2824
2825 SceneObjectPart part = GetChildPart(localID); 3044 SceneObjectPart part = GetChildPart(localID);
2826 if (part != null) 3045 if (part != null)
2827 { 3046 {
2828 part.Resize(scale);
2829 if (part.PhysActor != null) 3047 if (part.PhysActor != null)
2830 { 3048 {
2831 if (part.PhysActor.IsPhysical) 3049 if (part.PhysActor.IsPhysical)
@@ -2840,7 +3058,7 @@ namespace OpenSim.Region.Framework.Scenes
2840 part.PhysActor.Size = scale; 3058 part.PhysActor.Size = scale;
2841 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); 3059 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor);
2842 } 3060 }
2843 //if (part.UUID != m_rootPart.UUID) 3061 part.Resize(scale);
2844 3062
2845 HasGroupChanged = true; 3063 HasGroupChanged = true;
2846 ScheduleGroupForFullUpdate(); 3064 ScheduleGroupForFullUpdate();
@@ -2882,73 +3100,71 @@ namespace OpenSim.Region.Framework.Scenes
2882 float y = (scale.Y / part.Scale.Y); 3100 float y = (scale.Y / part.Scale.Y);
2883 float z = (scale.Z / part.Scale.Z); 3101 float z = (scale.Z / part.Scale.Z);
2884 3102
2885 lock (m_parts) 3103 lockPartsForRead(true);
3104 if (x > 1.0f || y > 1.0f || z > 1.0f)
2886 { 3105 {
2887 if (x > 1.0f || y > 1.0f || z > 1.0f) 3106 foreach (SceneObjectPart obPart in m_parts.Values)
2888 { 3107 {
2889 foreach (SceneObjectPart obPart in m_parts.Values) 3108 if (obPart.UUID != m_rootPart.UUID)
2890 { 3109 {
2891 if (obPart.UUID != m_rootPart.UUID) 3110 obPart.IgnoreUndoUpdate = true;
2892 { 3111 Vector3 oldSize = new Vector3(obPart.Scale);
2893 obPart.IgnoreUndoUpdate = true;
2894 Vector3 oldSize = new Vector3(obPart.Scale);
2895 3112
2896 float f = 1.0f; 3113 float f = 1.0f;
2897 float a = 1.0f; 3114 float a = 1.0f;
2898 3115
2899 if (part.PhysActor != null && part.PhysActor.IsPhysical) 3116 if (part.PhysActor != null && part.PhysActor.IsPhysical)
3117 {
3118 if (oldSize.X*x > m_scene.m_maxPhys)
2900 { 3119 {
2901 if (oldSize.X*x > m_scene.m_maxPhys) 3120 f = m_scene.m_maxPhys / oldSize.X;
2902 { 3121 a = f / x;
2903 f = m_scene.m_maxPhys / oldSize.X; 3122 x *= a;
2904 a = f / x; 3123 y *= a;
2905 x *= a; 3124 z *= a;
2906 y *= a;
2907 z *= a;
2908 }
2909 if (oldSize.Y*y > m_scene.m_maxPhys)
2910 {
2911 f = m_scene.m_maxPhys / oldSize.Y;
2912 a = f / y;
2913 x *= a;
2914 y *= a;
2915 z *= a;
2916 }
2917 if (oldSize.Z*z > m_scene.m_maxPhys)
2918 {
2919 f = m_scene.m_maxPhys / oldSize.Z;
2920 a = f / z;
2921 x *= a;
2922 y *= a;
2923 z *= a;
2924 }
2925 } 3125 }
2926 else 3126 if (oldSize.Y*y > m_scene.m_maxPhys)
2927 { 3127 {
2928 if (oldSize.X*x > m_scene.m_maxNonphys) 3128 f = m_scene.m_maxPhys / oldSize.Y;
2929 { 3129 a = f / y;
2930 f = m_scene.m_maxNonphys / oldSize.X; 3130 x *= a;
2931 a = f / x; 3131 y *= a;
2932 x *= a; 3132 z *= a;
2933 y *= a; 3133 }
2934 z *= a; 3134 if (oldSize.Z*z > m_scene.m_maxPhys)
2935 } 3135 {
2936 if (oldSize.Y*y > m_scene.m_maxNonphys) 3136 f = m_scene.m_maxPhys / oldSize.Z;
2937 { 3137 a = f / z;
2938 f = m_scene.m_maxNonphys / oldSize.Y; 3138 x *= a;
2939 a = f / y; 3139 y *= a;
2940 x *= a; 3140 z *= a;
2941 y *= a; 3141 }
2942 z *= a; 3142 }
2943 } 3143 else
2944 if (oldSize.Z*z > m_scene.m_maxNonphys) 3144 {
2945 { 3145 if (oldSize.X*x > m_scene.m_maxNonphys)
2946 f = m_scene.m_maxNonphys / oldSize.Z; 3146 {
2947 a = f / z; 3147 f = m_scene.m_maxNonphys / oldSize.X;
2948 x *= a; 3148 a = f / x;
2949 y *= a; 3149 x *= a;
2950 z *= a; 3150 y *= a;
2951 } 3151 z *= a;
3152 }
3153 if (oldSize.Y*y > m_scene.m_maxNonphys)
3154 {
3155 f = m_scene.m_maxNonphys / oldSize.Y;
3156 a = f / y;
3157 x *= a;
3158 y *= a;
3159 z *= a;
3160 }
3161 if (oldSize.Z*z > m_scene.m_maxNonphys)
3162 {
3163 f = m_scene.m_maxNonphys / oldSize.Z;
3164 a = f / z;
3165 x *= a;
3166 y *= a;
3167 z *= a;
2952 } 3168 }
2953 obPart.IgnoreUndoUpdate = false; 3169 obPart.IgnoreUndoUpdate = false;
2954 obPart.StoreUndoState(); 3170 obPart.StoreUndoState();
@@ -2956,6 +3172,7 @@ namespace OpenSim.Region.Framework.Scenes
2956 } 3172 }
2957 } 3173 }
2958 } 3174 }
3175 lockPartsForRead(false);
2959 3176
2960 Vector3 prevScale = part.Scale; 3177 Vector3 prevScale = part.Scale;
2961 prevScale.X *= x; 3178 prevScale.X *= x;
@@ -2963,7 +3180,7 @@ namespace OpenSim.Region.Framework.Scenes
2963 prevScale.Z *= z; 3180 prevScale.Z *= z;
2964 part.Resize(prevScale); 3181 part.Resize(prevScale);
2965 3182
2966 lock (m_parts) 3183 lockPartsForRead(true);
2967 { 3184 {
2968 foreach (SceneObjectPart obPart in m_parts.Values) 3185 foreach (SceneObjectPart obPart in m_parts.Values)
2969 { 3186 {
@@ -2985,6 +3202,7 @@ namespace OpenSim.Region.Framework.Scenes
2985 obPart.StoreUndoState(); 3202 obPart.StoreUndoState();
2986 } 3203 }
2987 } 3204 }
3205 lockPartsForRead(false);
2988 3206
2989 if (part.PhysActor != null) 3207 if (part.PhysActor != null)
2990 { 3208 {
@@ -3087,7 +3305,7 @@ namespace OpenSim.Region.Framework.Scenes
3087 axDiff *= Quaternion.Inverse(partRotation); 3305 axDiff *= Quaternion.Inverse(partRotation);
3088 diff = axDiff; 3306 diff = axDiff;
3089 3307
3090 lock (m_parts) 3308 lockPartsForRead(true);
3091 { 3309 {
3092 foreach (SceneObjectPart obPart in m_parts.Values) 3310 foreach (SceneObjectPart obPart in m_parts.Values)
3093 { 3311 {
@@ -3097,6 +3315,7 @@ namespace OpenSim.Region.Framework.Scenes
3097 } 3315 }
3098 } 3316 }
3099 } 3317 }
3318 lockPartsForRead(false);
3100 3319
3101 AbsolutePosition = newPos; 3320 AbsolutePosition = newPos;
3102 3321
@@ -3230,25 +3449,25 @@ namespace OpenSim.Region.Framework.Scenes
3230 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); 3449 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
3231 } 3450 }
3232 3451
3233 lock (m_parts) 3452 lockPartsForRead(true);
3453
3454 foreach (SceneObjectPart prim in m_parts.Values)
3234 { 3455 {
3235 foreach (SceneObjectPart prim in m_parts.Values) 3456 if (prim.UUID != m_rootPart.UUID)
3236 { 3457 {
3237 if (prim.UUID != m_rootPart.UUID) 3458 prim.IgnoreUndoUpdate = true;
3238 { 3459 Vector3 axPos = prim.OffsetPosition;
3239 prim.IgnoreUndoUpdate = true; 3460 axPos *= oldParentRot;
3240 Vector3 axPos = prim.OffsetPosition; 3461 axPos *= Quaternion.Inverse(axRot);
3241 axPos *= oldParentRot; 3462 prim.OffsetPosition = axPos;
3242 axPos *= Quaternion.Inverse(axRot); 3463 Quaternion primsRot = prim.RotationOffset;
3243 prim.OffsetPosition = axPos; 3464 Quaternion newRot = primsRot * oldParentRot;
3244 Quaternion primsRot = prim.RotationOffset; 3465 newRot *= Quaternion.Inverse(axRot);
3245 Quaternion newRot = primsRot * oldParentRot; 3466 prim.RotationOffset = newRot;
3246 newRot *= Quaternion.Inverse(axRot); 3467 prim.ScheduleTerseUpdate();
3247 prim.RotationOffset = newRot;
3248 prim.ScheduleTerseUpdate();
3249 }
3250 } 3468 }
3251 } 3469 }
3470
3252 foreach (SceneObjectPart childpart in Children.Values) 3471 foreach (SceneObjectPart childpart in Children.Values)
3253 { 3472 {
3254 if (childpart != m_rootPart) 3473 if (childpart != m_rootPart)
@@ -3257,6 +3476,9 @@ namespace OpenSim.Region.Framework.Scenes
3257 childpart.StoreUndoState(); 3476 childpart.StoreUndoState();
3258 } 3477 }
3259 } 3478 }
3479
3480 lockPartsForRead(false);
3481
3260 m_rootPart.ScheduleTerseUpdate(); 3482 m_rootPart.ScheduleTerseUpdate();
3261 } 3483 }
3262 3484
@@ -3378,7 +3600,7 @@ namespace OpenSim.Region.Framework.Scenes
3378 if (atTargets.Count > 0) 3600 if (atTargets.Count > 0)
3379 { 3601 {
3380 uint[] localids = new uint[0]; 3602 uint[] localids = new uint[0];
3381 lock (m_parts) 3603 lockPartsForRead(true);
3382 { 3604 {
3383 localids = new uint[m_parts.Count]; 3605 localids = new uint[m_parts.Count];
3384 int cntr = 0; 3606 int cntr = 0;
@@ -3388,6 +3610,7 @@ namespace OpenSim.Region.Framework.Scenes
3388 cntr++; 3610 cntr++;
3389 } 3611 }
3390 } 3612 }
3613 lockPartsForRead(false);
3391 3614
3392 for (int ctr = 0; ctr < localids.Length; ctr++) 3615 for (int ctr = 0; ctr < localids.Length; ctr++)
3393 { 3616 {
@@ -3406,7 +3629,7 @@ namespace OpenSim.Region.Framework.Scenes
3406 { 3629 {
3407 //trigger not_at_target 3630 //trigger not_at_target
3408 uint[] localids = new uint[0]; 3631 uint[] localids = new uint[0];
3409 lock (m_parts) 3632 lockPartsForRead(true);
3410 { 3633 {
3411 localids = new uint[m_parts.Count]; 3634 localids = new uint[m_parts.Count];
3412 int cntr = 0; 3635 int cntr = 0;
@@ -3416,7 +3639,8 @@ namespace OpenSim.Region.Framework.Scenes
3416 cntr++; 3639 cntr++;
3417 } 3640 }
3418 } 3641 }
3419 3642 lockPartsForRead(false);
3643
3420 for (int ctr = 0; ctr < localids.Length; ctr++) 3644 for (int ctr = 0; ctr < localids.Length; ctr++)
3421 { 3645 {
3422 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]); 3646 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]);
@@ -3508,19 +3732,20 @@ namespace OpenSim.Region.Framework.Scenes
3508 public float GetMass() 3732 public float GetMass()
3509 { 3733 {
3510 float retmass = 0f; 3734 float retmass = 0f;
3511 lock (m_parts) 3735 lockPartsForRead(true);
3512 { 3736 {
3513 foreach (SceneObjectPart part in m_parts.Values) 3737 foreach (SceneObjectPart part in m_parts.Values)
3514 { 3738 {
3515 retmass += part.GetMass(); 3739 retmass += part.GetMass();
3516 } 3740 }
3517 } 3741 }
3742 lockPartsForRead(false);
3518 return retmass; 3743 return retmass;
3519 } 3744 }
3520 3745
3521 public void CheckSculptAndLoad() 3746 public void CheckSculptAndLoad()
3522 { 3747 {
3523 lock (m_parts) 3748 lockPartsForRead(true);
3524 { 3749 {
3525 if (!IsDeleted) 3750 if (!IsDeleted)
3526 { 3751 {
@@ -3545,6 +3770,7 @@ namespace OpenSim.Region.Framework.Scenes
3545 } 3770 }
3546 } 3771 }
3547 } 3772 }
3773 lockPartsForRead(false);
3548 } 3774 }
3549 3775
3550 protected void AssetReceived(string id, Object sender, AssetBase asset) 3776 protected void AssetReceived(string id, Object sender, AssetBase asset)
@@ -3565,7 +3791,7 @@ namespace OpenSim.Region.Framework.Scenes
3565 /// <param name="client"></param> 3791 /// <param name="client"></param>
3566 public void SetGroup(UUID GroupID, IClientAPI client) 3792 public void SetGroup(UUID GroupID, IClientAPI client)
3567 { 3793 {
3568 lock (m_parts) 3794 lockPartsForRead(true);
3569 { 3795 {
3570 foreach (SceneObjectPart part in m_parts.Values) 3796 foreach (SceneObjectPart part in m_parts.Values)
3571 { 3797 {
@@ -3575,6 +3801,7 @@ namespace OpenSim.Region.Framework.Scenes
3575 3801
3576 HasGroupChanged = true; 3802 HasGroupChanged = true;
3577 } 3803 }
3804 lockPartsForRead(false);
3578 3805
3579 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled 3806 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled
3580 // for the same object with very different properties. The caller must schedule the update. 3807 // for the same object with very different properties. The caller must schedule the update.
@@ -3596,11 +3823,12 @@ namespace OpenSim.Region.Framework.Scenes
3596 3823
3597 public void SetAttachmentPoint(byte point) 3824 public void SetAttachmentPoint(byte point)
3598 { 3825 {
3599 lock (m_parts) 3826 lockPartsForRead(true);
3600 { 3827 {
3601 foreach (SceneObjectPart part in m_parts.Values) 3828 foreach (SceneObjectPart part in m_parts.Values)
3602 part.SetAttachmentPoint(point); 3829 part.SetAttachmentPoint(point);
3603 } 3830 }
3831 lockPartsForRead(false);
3604 } 3832 }
3605 3833
3606 #region ISceneObject 3834 #region ISceneObject