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.cs706
1 files changed, 485 insertions, 221 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index e23f39f..c7d21bb 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -104,8 +104,95 @@ 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 private bool m_suspendUpdates;
113
114 private System.Threading.ReaderWriterLockSlim m_partsLock = new System.Threading.ReaderWriterLockSlim();
115
116 public bool areUpdatesSuspended
117 {
118 get
119 {
120 return m_suspendUpdates;
121 }
122 set
123 {
124 m_suspendUpdates = value;
125 if (!value)
126 {
127 QueueForUpdateCheck();
128 }
129 }
130 }
131
132 public void lockPartsForRead(bool locked)
133 {
134 if (locked)
135 {
136 if (m_partsLock.RecursiveReadCount > 0)
137 {
138 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.");
139 m_partsLock.ExitReadLock();
140 }
141 if (m_partsLock.RecursiveWriteCount > 0)
142 {
143 m_log.Error("[SceneObjectGroup.m_parts] Recursive read lock requested (write lock exists on this thread). This should not happen and means something needs to be fixed.");
144 m_partsLock.ExitWriteLock();
145 }
146
147 while (!m_partsLock.TryEnterReadLock(60000))
148 {
149 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.");
150 if (m_partsLock.IsWriteLockHeld)
151 {
152 m_partsLock = new System.Threading.ReaderWriterLockSlim();
153 }
154 }
155 }
156 else
157 {
158 if (m_partsLock.RecursiveReadCount > 0)
159 {
160 m_partsLock.ExitReadLock();
161 }
162 }
163 }
164 public void lockPartsForWrite(bool locked)
165 {
166 if (locked)
167 {
168 if (m_partsLock.RecursiveReadCount > 0)
169 {
170 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.");
171 m_partsLock.ExitReadLock();
172 }
173 if (m_partsLock.RecursiveWriteCount > 0)
174 {
175 m_log.Error("[SceneObjectGroup.m_parts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
176 m_partsLock.ExitWriteLock();
177 }
178
179 while (!m_partsLock.TryEnterWriteLock(60000))
180 {
181 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.");
182 if (m_partsLock.IsWriteLockHeld)
183 {
184 m_partsLock = new System.Threading.ReaderWriterLockSlim();
185 }
186 }
187 }
188 else
189 {
190 if (m_partsLock.RecursiveWriteCount > 0)
191 {
192 m_partsLock.ExitWriteLock();
193 }
194 }
195 }
109 196
110 public bool HasGroupChanged 197 public bool HasGroupChanged
111 { 198 {
@@ -116,6 +203,32 @@ namespace OpenSim.Region.Framework.Scenes
116 timeLastChanged = DateTime.Now.Ticks; 203 timeLastChanged = DateTime.Now.Ticks;
117 if (!m_hasGroupChanged) 204 if (!m_hasGroupChanged)
118 timeFirstChanged = DateTime.Now.Ticks; 205 timeFirstChanged = DateTime.Now.Ticks;
206 if (m_rootPart != null && m_rootPart.UUID != null && m_scene != null)
207 {
208 if (m_rand == null)
209 {
210 byte[] val = new byte[16];
211 m_rootPart.UUID.ToBytes(val, 0);
212 m_rand = new Random(BitConverter.ToInt32(val, 0));
213 }
214
215 if (m_scene.GetRootAgentCount() == 0)
216 {
217 //If the region is empty, this change has been made by an automated process
218 //and thus we delay the persist time by a random amount between 1.5 and 2.5.
219
220 float factor = 1.5f + (float)(m_rand.NextDouble());
221 m_maxPersistTime = (long)((float)m_scene.m_persistAfter * factor);
222 m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * factor);
223 }
224 else
225 {
226 //If the region is not empty, we want to obey the minimum and maximum persist times
227 //but add a random factor so we stagger the object persistance a little
228 m_maxPersistTime = (long)((float)m_scene.m_persistAfter * (1.0d - (m_rand.NextDouble() / 5.0d))); //Multiply by 1.0-1.5
229 m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * (1.0d + (m_rand.NextDouble() / 2.0d))); //Multiply by 0.8-1.0
230 }
231 }
119 } 232 }
120 m_hasGroupChanged = value; 233 m_hasGroupChanged = value;
121 } 234 }
@@ -131,8 +244,19 @@ namespace OpenSim.Region.Framework.Scenes
131 return false; 244 return false;
132 if (m_scene.ShuttingDown) 245 if (m_scene.ShuttingDown)
133 return true; 246 return true;
247
248 if (m_minPersistTime == 0 || m_maxPersistTime == 0)
249 {
250 m_maxPersistTime = m_scene.m_persistAfter;
251 m_minPersistTime = m_scene.m_dontPersistBefore;
252 }
253
134 long currentTime = DateTime.Now.Ticks; 254 long currentTime = DateTime.Now.Ticks;
135 if (currentTime - timeLastChanged > m_scene.m_dontPersistBefore || currentTime - timeFirstChanged > m_scene.m_persistAfter) 255
256 if (timeLastChanged == 0) timeLastChanged = currentTime;
257 if (timeFirstChanged == 0) timeFirstChanged = currentTime;
258
259 if (currentTime - timeLastChanged > m_minPersistTime || currentTime - timeFirstChanged > m_maxPersistTime)
136 return true; 260 return true;
137 return false; 261 return false;
138 } 262 }
@@ -258,13 +382,16 @@ namespace OpenSim.Region.Framework.Scenes
258 set 382 set
259 { 383 {
260 m_regionHandle = value; 384 m_regionHandle = value;
261 lock (m_parts) 385 lockPartsForRead(true);
262 { 386 {
263 foreach (SceneObjectPart part in m_parts.Values) 387 foreach (SceneObjectPart part in m_parts.Values)
264 { 388 {
389
265 part.RegionHandle = m_regionHandle; 390 part.RegionHandle = m_regionHandle;
391
266 } 392 }
267 } 393 }
394 lockPartsForRead(false);
268 } 395 }
269 } 396 }
270 397
@@ -298,6 +425,9 @@ namespace OpenSim.Region.Framework.Scenes
298 { 425 {
299 m_scene.CrossPrimGroupIntoNewRegion(val, this, true); 426 m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
300 } 427 }
428
429 lockPartsForRead(true);
430
301 if (RootPart.GetStatusSandbox()) 431 if (RootPart.GetStatusSandbox())
302 { 432 {
303 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) 433 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10)
@@ -305,17 +435,18 @@ namespace OpenSim.Region.Framework.Scenes
305 RootPart.ScriptSetPhysicsStatus(false); 435 RootPart.ScriptSetPhysicsStatus(false);
306 Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"), 436 Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"),
307 ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false); 437 ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false);
438 lockPartsForRead(false);
308 return; 439 return;
309 } 440 }
310 } 441 }
311 lock (m_parts) 442
443 foreach (SceneObjectPart part in m_parts.Values)
312 { 444 {
313 foreach (SceneObjectPart part in m_parts.Values) 445 part.GroupPosition = val;
314 {
315 part.GroupPosition = val;
316 }
317 } 446 }
318 447
448 lockPartsForRead(false);
449
319 //if (m_rootPart.PhysActor != null) 450 //if (m_rootPart.PhysActor != null)
320 //{ 451 //{
321 //m_rootPart.PhysActor.Position = 452 //m_rootPart.PhysActor.Position =
@@ -457,6 +588,7 @@ namespace OpenSim.Region.Framework.Scenes
457 /// </summary> 588 /// </summary>
458 public SceneObjectGroup() 589 public SceneObjectGroup()
459 { 590 {
591
460 } 592 }
461 593
462 /// <summary> 594 /// <summary>
@@ -473,7 +605,7 @@ namespace OpenSim.Region.Framework.Scenes
473 /// Constructor. This object is added to the scene later via AttachToScene() 605 /// Constructor. This object is added to the scene later via AttachToScene()
474 /// </summary> 606 /// </summary>
475 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) 607 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape)
476 { 608 {
477 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero)); 609 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero));
478 } 610 }
479 611
@@ -504,13 +636,16 @@ namespace OpenSim.Region.Framework.Scenes
504 636
505 public void SetFromItemID(UUID AssetId) 637 public void SetFromItemID(UUID AssetId)
506 { 638 {
507 lock (m_parts) 639 lockPartsForRead(true);
508 { 640 {
509 foreach (SceneObjectPart part in m_parts.Values) 641 foreach (SceneObjectPart part in m_parts.Values)
510 { 642 {
643
511 part.FromItemID = AssetId; 644 part.FromItemID = AssetId;
645
512 } 646 }
513 } 647 }
648 lockPartsForRead(false);
514 } 649 }
515 650
516 public UUID GetFromItemID() 651 public UUID GetFromItemID()
@@ -579,10 +714,11 @@ namespace OpenSim.Region.Framework.Scenes
579 Vector3 maxScale = Vector3.Zero; 714 Vector3 maxScale = Vector3.Zero;
580 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f); 715 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f);
581 716
582 lock (m_parts) 717 lockPartsForRead(true);
583 { 718 {
584 foreach (SceneObjectPart part in m_parts.Values) 719 foreach (SceneObjectPart part in m_parts.Values)
585 { 720 {
721
586 Vector3 partscale = part.Scale; 722 Vector3 partscale = part.Scale;
587 Vector3 partoffset = part.OffsetPosition; 723 Vector3 partoffset = part.OffsetPosition;
588 724
@@ -593,8 +729,11 @@ namespace OpenSim.Region.Framework.Scenes
593 maxScale.X = (partscale.X + partoffset.X > maxScale.X) ? partscale.X + partoffset.X : maxScale.X; 729 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; 730 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; 731 maxScale.Z = (partscale.Z + partoffset.Z > maxScale.Z) ? partscale.Z + partoffset.Z : maxScale.Z;
732
596 } 733 }
597 } 734 }
735 lockPartsForRead(false);
736
598 finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X; 737 finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X;
599 finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y; 738 finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y;
600 finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z; 739 finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z;
@@ -610,10 +749,11 @@ namespace OpenSim.Region.Framework.Scenes
610 749
611 EntityIntersection result = new EntityIntersection(); 750 EntityIntersection result = new EntityIntersection();
612 751
613 lock (m_parts) 752 lockPartsForRead(true);
614 { 753 {
615 foreach (SceneObjectPart part in m_parts.Values) 754 foreach (SceneObjectPart part in m_parts.Values)
616 { 755 {
756
617 // Temporary commented to stop compiler warning 757 // Temporary commented to stop compiler warning
618 //Vector3 partPosition = 758 //Vector3 partPosition =
619 // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z); 759 // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z);
@@ -641,8 +781,10 @@ namespace OpenSim.Region.Framework.Scenes
641 result.distance = inter.distance; 781 result.distance = inter.distance;
642 } 782 }
643 } 783 }
784
644 } 785 }
645 } 786 }
787 lockPartsForRead(false);
646 return result; 788 return result;
647 } 789 }
648 790
@@ -661,10 +803,11 @@ namespace OpenSim.Region.Framework.Scenes
661 minY = 256f; 803 minY = 256f;
662 minZ = 8192f; 804 minZ = 8192f;
663 805
664 lock(m_parts); 806 lockPartsForRead(true);
665 { 807 {
666 foreach (SceneObjectPart part in m_parts.Values) 808 foreach (SceneObjectPart part in m_parts.Values)
667 { 809 {
810
668 Vector3 worldPos = part.GetWorldPosition(); 811 Vector3 worldPos = part.GetWorldPosition();
669 Vector3 offset = worldPos - AbsolutePosition; 812 Vector3 offset = worldPos - AbsolutePosition;
670 Quaternion worldRot; 813 Quaternion worldRot;
@@ -723,6 +866,8 @@ namespace OpenSim.Region.Framework.Scenes
723 backBottomRight.Y = orig.Y + (part.Scale.Y / 2); 866 backBottomRight.Y = orig.Y + (part.Scale.Y / 2);
724 backBottomRight.Z = orig.Z - (part.Scale.Z / 2); 867 backBottomRight.Z = orig.Z - (part.Scale.Z / 2);
725 868
869
870
726 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z); 871 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
727 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z); 872 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
728 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z); 873 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
@@ -894,6 +1039,7 @@ namespace OpenSim.Region.Framework.Scenes
894 minZ = backBottomLeft.Z; 1039 minZ = backBottomLeft.Z;
895 } 1040 }
896 } 1041 }
1042 lockPartsForRead(false);
897 } 1043 }
898 1044
899 public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight) 1045 public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight)
@@ -929,21 +1075,29 @@ namespace OpenSim.Region.Framework.Scenes
929 1075
930 public void SaveScriptedState(XmlTextWriter writer) 1076 public void SaveScriptedState(XmlTextWriter writer)
931 { 1077 {
1078 SaveScriptedState(writer, false);
1079 }
1080
1081 public void SaveScriptedState(XmlTextWriter writer, bool oldIDs)
1082 {
932 XmlDocument doc = new XmlDocument(); 1083 XmlDocument doc = new XmlDocument();
933 Dictionary<UUID,string> states = new Dictionary<UUID,string>(); 1084 Dictionary<UUID,string> states = new Dictionary<UUID,string>();
934 1085
935 // Capture script state while holding the lock 1086 // Capture script state while holding the lock
936 lock (m_parts) 1087 lockPartsForRead(true);
937 { 1088 {
938 foreach (SceneObjectPart part in m_parts.Values) 1089 foreach (SceneObjectPart part in m_parts.Values)
939 { 1090 {
940 Dictionary<UUID,string> pstates = part.Inventory.GetScriptStates(); 1091
1092 Dictionary<UUID,string> pstates = part.Inventory.GetScriptStates(oldIDs);
941 foreach (UUID itemid in pstates.Keys) 1093 foreach (UUID itemid in pstates.Keys)
942 { 1094 {
943 states.Add(itemid, pstates[itemid]); 1095 states.Add(itemid, pstates[itemid]);
944 } 1096 }
1097
945 } 1098 }
946 } 1099 }
1100 lockPartsForRead(false);
947 1101
948 if (states.Count > 0) 1102 if (states.Count > 0)
949 { 1103 {
@@ -1112,13 +1266,16 @@ namespace OpenSim.Region.Framework.Scenes
1112 1266
1113 public override void UpdateMovement() 1267 public override void UpdateMovement()
1114 { 1268 {
1115 lock (m_parts) 1269 lockPartsForRead(true);
1116 { 1270 {
1117 foreach (SceneObjectPart part in m_parts.Values) 1271 foreach (SceneObjectPart part in m_parts.Values)
1118 { 1272 {
1273
1119 part.UpdateMovement(); 1274 part.UpdateMovement();
1275
1120 } 1276 }
1121 } 1277 }
1278 lockPartsForRead(false);
1122 } 1279 }
1123 1280
1124 public ushort GetTimeDilation() 1281 public ushort GetTimeDilation()
@@ -1162,7 +1319,7 @@ namespace OpenSim.Region.Framework.Scenes
1162 /// <param name="part"></param> 1319 /// <param name="part"></param>
1163 public void AddPart(SceneObjectPart part) 1320 public void AddPart(SceneObjectPart part)
1164 { 1321 {
1165 lock (m_parts) 1322 lockPartsForWrite(true);
1166 { 1323 {
1167 part.SetParent(this); 1324 part.SetParent(this);
1168 m_parts.Add(part.UUID, part); 1325 m_parts.Add(part.UUID, part);
@@ -1172,6 +1329,7 @@ namespace OpenSim.Region.Framework.Scenes
1172 if (part.LinkNum == 2 && RootPart != null) 1329 if (part.LinkNum == 2 && RootPart != null)
1173 RootPart.LinkNum = 1; 1330 RootPart.LinkNum = 1;
1174 } 1331 }
1332 lockPartsForWrite(false);
1175 } 1333 }
1176 1334
1177 /// <summary> 1335 /// <summary>
@@ -1179,28 +1337,33 @@ namespace OpenSim.Region.Framework.Scenes
1179 /// </summary> 1337 /// </summary>
1180 private void UpdateParentIDs() 1338 private void UpdateParentIDs()
1181 { 1339 {
1182 lock (m_parts) 1340 lockPartsForRead(true);
1183 { 1341 {
1184 foreach (SceneObjectPart part in m_parts.Values) 1342 foreach (SceneObjectPart part in m_parts.Values)
1185 { 1343 {
1344
1186 if (part.UUID != m_rootPart.UUID) 1345 if (part.UUID != m_rootPart.UUID)
1187 { 1346 {
1188 part.ParentID = m_rootPart.LocalId; 1347 part.ParentID = m_rootPart.LocalId;
1189 } 1348 }
1349
1190 } 1350 }
1191 } 1351 }
1352 lockPartsForRead(false);
1192 } 1353 }
1193 1354
1194 public void RegenerateFullIDs() 1355 public void RegenerateFullIDs()
1195 { 1356 {
1196 lock (m_parts) 1357 lockPartsForRead(true);
1197 { 1358 {
1198 foreach (SceneObjectPart part in m_parts.Values) 1359 foreach (SceneObjectPart part in m_parts.Values)
1199 { 1360 {
1361
1200 part.UUID = UUID.Random(); 1362 part.UUID = UUID.Random();
1201 1363
1202 } 1364 }
1203 } 1365 }
1366 lockPartsForRead(false);
1204 } 1367 }
1205 1368
1206 // helper provided for parts. 1369 // helper provided for parts.
@@ -1281,27 +1444,32 @@ namespace OpenSim.Region.Framework.Scenes
1281 1444
1282 DetachFromBackup(); 1445 DetachFromBackup();
1283 1446
1284 lock (m_parts) 1447 lockPartsForRead(true);
1448 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1449 lockPartsForRead(false);
1450
1451 foreach (SceneObjectPart part in values)
1285 { 1452 {
1286 foreach (SceneObjectPart part in m_parts.Values)
1287 {
1288// part.Inventory.RemoveScriptInstances(); 1453// part.Inventory.RemoveScriptInstances();
1289 Scene.ForEachScenePresence(delegate(ScenePresence avatar) 1454
1455 Scene.ForEachScenePresence(delegate (ScenePresence sp)
1456 {
1457 if (sp.ParentID == LocalId)
1290 { 1458 {
1291 if (avatar.ParentID == LocalId) 1459 sp.StandUp();
1292 { 1460 }
1293 avatar.StandUp();
1294 }
1295 1461
1296 if (!silent) 1462 if (!silent)
1297 { 1463 {
1298 part.UpdateFlag = 0; 1464 part.UpdateFlag = 0;
1299 if (part == m_rootPart) 1465 if (part == m_rootPart)
1300 avatar.ControllingClient.SendKillObject(m_regionHandle, part.LocalId); 1466 sp.ControllingClient.SendKillObject(m_regionHandle, part.LocalId);
1301 } 1467 }
1302 }); 1468 });
1303 } 1469
1304 } 1470 }
1471
1472
1305 } 1473 }
1306 1474
1307 public void AddScriptLPS(int count) 1475 public void AddScriptLPS(int count)
@@ -1326,17 +1494,20 @@ namespace OpenSim.Region.Framework.Scenes
1326 1494
1327 scriptEvents aggregateScriptEvents=0; 1495 scriptEvents aggregateScriptEvents=0;
1328 1496
1329 lock (m_parts) 1497 lockPartsForRead(true);
1330 { 1498 {
1331 foreach (SceneObjectPart part in m_parts.Values) 1499 foreach (SceneObjectPart part in m_parts.Values)
1332 { 1500 {
1501
1333 if (part == null) 1502 if (part == null)
1334 continue; 1503 continue;
1335 if (part != RootPart) 1504 if (part != RootPart)
1336 part.ObjectFlags = objectflagupdate; 1505 part.ObjectFlags = objectflagupdate;
1337 aggregateScriptEvents |= part.AggregateScriptEvents; 1506 aggregateScriptEvents |= part.AggregateScriptEvents;
1507
1338 } 1508 }
1339 } 1509 }
1510 lockPartsForRead(false);
1340 1511
1341 m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0); 1512 m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0);
1342 m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0); 1513 m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0);
@@ -1378,42 +1549,52 @@ namespace OpenSim.Region.Framework.Scenes
1378 /// <param name="m_physicalPrim"></param> 1549 /// <param name="m_physicalPrim"></param>
1379 public void ApplyPhysics(bool m_physicalPrim) 1550 public void ApplyPhysics(bool m_physicalPrim)
1380 { 1551 {
1381 lock (m_parts) 1552 lockPartsForRead(true);
1553
1554 if (m_parts.Count > 1)
1382 { 1555 {
1383 if (m_parts.Count > 1) 1556 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1557 lockPartsForRead(false);
1558 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1559 foreach (SceneObjectPart part in values)
1384 { 1560 {
1385 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim); 1561
1386 foreach (SceneObjectPart part in m_parts.Values) 1562 if (part.LocalId != m_rootPart.LocalId)
1387 { 1563 {
1388 if (part.LocalId != m_rootPart.LocalId) 1564 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim);
1389 {
1390 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim);
1391 }
1392 } 1565 }
1393 1566
1394 // Hack to get the physics scene geometries in the right spot
1395 ResetChildPrimPhysicsPositions();
1396 }
1397 else
1398 {
1399 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1400 } 1567 }
1568 // Hack to get the physics scene geometries in the right spot
1569 ResetChildPrimPhysicsPositions();
1570 }
1571 else
1572 {
1573 lockPartsForRead(false);
1574 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1401 } 1575 }
1402 } 1576 }
1403 1577
1404 public void SetOwnerId(UUID userId) 1578 public void SetOwnerId(UUID userId)
1405 { 1579 {
1406 ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); 1580 ForEachPart(delegate(SceneObjectPart part)
1581 {
1582
1583 part.OwnerID = userId;
1584
1585 });
1407 } 1586 }
1408 1587
1409 public void ForEachPart(Action<SceneObjectPart> whatToDo) 1588 public void ForEachPart(Action<SceneObjectPart> whatToDo)
1410 { 1589 {
1411 lock (m_parts) 1590 lockPartsForRead(true);
1591 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1592 lockPartsForRead(false);
1593 foreach (SceneObjectPart part in values)
1412 { 1594 {
1413 foreach (SceneObjectPart part in m_parts.Values) 1595
1414 { 1596 whatToDo(part);
1415 whatToDo(part); 1597
1416 }
1417 } 1598 }
1418 } 1599 }
1419 1600
@@ -1511,15 +1692,17 @@ namespace OpenSim.Region.Framework.Scenes
1511 RootPart.SendFullUpdate( 1692 RootPart.SendFullUpdate(
1512 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID)); 1693 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID));
1513 1694
1514 lock (m_parts) 1695 lockPartsForRead(true);
1515 { 1696 {
1516 foreach (SceneObjectPart part in m_parts.Values) 1697 foreach (SceneObjectPart part in m_parts.Values)
1517 { 1698 {
1699
1518 if (part != RootPart) 1700 if (part != RootPart)
1519 part.SendFullUpdate( 1701 part.SendFullUpdate(
1520 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID)); 1702 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID));
1521 } 1703 }
1522 } 1704 }
1705 lockPartsForRead(false);
1523 } 1706 }
1524 1707
1525 #region Copying 1708 #region Copying
@@ -1588,10 +1771,11 @@ namespace OpenSim.Region.Framework.Scenes
1588 1771
1589 List<SceneObjectPart> partList; 1772 List<SceneObjectPart> partList;
1590 1773
1591 lock (m_parts) 1774 lockPartsForRead(true);
1592 { 1775
1593 partList = new List<SceneObjectPart>(m_parts.Values); 1776 partList = new List<SceneObjectPart>(m_parts.Values);
1594 } 1777
1778 lockPartsForRead(false);
1595 1779
1596 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) 1780 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1597 { 1781 {
@@ -1814,13 +1998,40 @@ namespace OpenSim.Region.Framework.Scenes
1814 } 1998 }
1815 } 1999 }
1816 2000
2001 public void rotLookAt(Quaternion target, float strength, float damping)
2002 {
2003 SceneObjectPart rootpart = m_rootPart;
2004 if (rootpart != null)
2005 {
2006 if (IsAttachment)
2007 {
2008 /*
2009 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
2010 if (avatar != null)
2011 {
2012 Rotate the Av?
2013 } */
2014 }
2015 else
2016 {
2017 if (rootpart.PhysActor != null)
2018 { // APID must be implemented in your physics system for this to function.
2019 rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W);
2020 rootpart.PhysActor.APIDStrength = strength;
2021 rootpart.PhysActor.APIDDamping = damping;
2022 rootpart.PhysActor.APIDActive = true;
2023 }
2024 }
2025 }
2026 }
2027
1817 public void stopLookAt() 2028 public void stopLookAt()
1818 { 2029 {
1819 SceneObjectPart rootpart = m_rootPart; 2030 SceneObjectPart rootpart = m_rootPart;
1820 if (rootpart != null) 2031 if (rootpart != null)
1821 { 2032 {
1822 if (rootpart.PhysActor != null) 2033 if (rootpart.PhysActor != null)
1823 { 2034 { // APID must be implemented in your physics system for this to function.
1824 rootpart.PhysActor.APIDActive = false; 2035 rootpart.PhysActor.APIDActive = false;
1825 } 2036 }
1826 } 2037 }
@@ -1888,10 +2099,11 @@ namespace OpenSim.Region.Framework.Scenes
1888 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 2099 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
1889 newPart.SetParent(this); 2100 newPart.SetParent(this);
1890 2101
1891 lock (m_parts) 2102 lockPartsForWrite(true);
1892 { 2103 {
1893 m_parts.Add(newPart.UUID, newPart); 2104 m_parts.Add(newPart.UUID, newPart);
1894 } 2105 }
2106 lockPartsForWrite(false);
1895 2107
1896 SetPartAsNonRoot(newPart); 2108 SetPartAsNonRoot(newPart);
1897 2109
@@ -1954,7 +2166,7 @@ namespace OpenSim.Region.Framework.Scenes
1954 //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0) 2166 //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
1955 // return; 2167 // return;
1956 2168
1957 lock (m_parts) 2169 lockPartsForRead(true);
1958 { 2170 {
1959 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0); 2171 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0);
1960 2172
@@ -1974,9 +2186,12 @@ namespace OpenSim.Region.Framework.Scenes
1974 { 2186 {
1975 if (!IsSelected) 2187 if (!IsSelected)
1976 part.UpdateLookAt(); 2188 part.UpdateLookAt();
2189
1977 part.SendScheduledUpdates(); 2190 part.SendScheduledUpdates();
2191
1978 } 2192 }
1979 } 2193 }
2194 lockPartsForRead(false);
1980 } 2195 }
1981 2196
1982 public void ScheduleFullUpdateToAvatar(ScenePresence presence) 2197 public void ScheduleFullUpdateToAvatar(ScenePresence presence)
@@ -1985,27 +2200,29 @@ namespace OpenSim.Region.Framework.Scenes
1985 2200
1986 RootPart.AddFullUpdateToAvatar(presence); 2201 RootPart.AddFullUpdateToAvatar(presence);
1987 2202
1988 lock (m_parts) 2203 lockPartsForRead(true);
1989 { 2204 {
1990 foreach (SceneObjectPart part in m_parts.Values) 2205 foreach (SceneObjectPart part in m_parts.Values)
1991 { 2206 {
2207
1992 if (part != RootPart) 2208 if (part != RootPart)
1993 part.AddFullUpdateToAvatar(presence); 2209 part.AddFullUpdateToAvatar(presence);
2210
1994 } 2211 }
1995 } 2212 }
2213 lockPartsForRead(false);
1996 } 2214 }
1997 2215
1998 public void ScheduleTerseUpdateToAvatar(ScenePresence presence) 2216 public void ScheduleTerseUpdateToAvatar(ScenePresence presence)
1999 { 2217 {
2000// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1} just to avatar {2}", Name, UUID, presence.Name); 2218 lockPartsForRead(true);
2001 2219
2002 lock (m_parts) 2220 foreach (SceneObjectPart part in m_parts.Values)
2003 { 2221 {
2004 foreach (SceneObjectPart part in m_parts.Values) 2222 part.AddTerseUpdateToAvatar(presence);
2005 {
2006 part.AddTerseUpdateToAvatar(presence);
2007 }
2008 } 2223 }
2224
2225 lockPartsForRead(false);
2009 } 2226 }
2010 2227
2011 /// <summary> 2228 /// <summary>
@@ -2013,20 +2230,23 @@ namespace OpenSim.Region.Framework.Scenes
2013 /// </summary> 2230 /// </summary>
2014 public void ScheduleGroupForFullUpdate() 2231 public void ScheduleGroupForFullUpdate()
2015 { 2232 {
2016 if (IsAttachment) 2233 //if (IsAttachment)
2017 m_log.DebugFormat("[SOG]: Scheduling full update for {0} {1}", Name, LocalId); 2234 // m_log.DebugFormat("[SOG]: Scheduling full update for {0} {1}", Name, LocalId);
2018 2235
2019 checkAtTargets(); 2236 checkAtTargets();
2020 RootPart.ScheduleFullUpdate(); 2237 RootPart.ScheduleFullUpdate();
2021 2238
2022 lock (m_parts) 2239 lockPartsForRead(true);
2023 { 2240 {
2024 foreach (SceneObjectPart part in m_parts.Values) 2241 foreach (SceneObjectPart part in m_parts.Values)
2025 { 2242 {
2243
2026 if (part != RootPart) 2244 if (part != RootPart)
2027 part.ScheduleFullUpdate(); 2245 part.ScheduleFullUpdate();
2246
2028 } 2247 }
2029 } 2248 }
2249 lockPartsForRead(false);
2030 } 2250 }
2031 2251
2032 /// <summary> 2252 /// <summary>
@@ -2034,37 +2254,38 @@ namespace OpenSim.Region.Framework.Scenes
2034 /// </summary> 2254 /// </summary>
2035 public void ScheduleGroupForTerseUpdate() 2255 public void ScheduleGroupForTerseUpdate()
2036 { 2256 {
2037// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1}", Name, UUID); 2257 lockPartsForRead(true);
2038 2258 foreach (SceneObjectPart part in m_parts.Values)
2039 lock (m_parts)
2040 { 2259 {
2041 foreach (SceneObjectPart part in m_parts.Values) 2260 part.ScheduleTerseUpdate();
2042 {
2043 part.ScheduleTerseUpdate();
2044 }
2045 } 2261 }
2262
2263 lockPartsForRead(false);
2046 } 2264 }
2047 2265
2048 /// <summary> 2266 /// <summary>
2049 /// Immediately send a full update for this scene object. 2267 /// Immediately send a full update for this scene object.
2050 /// </summary> 2268 /// </summary>
2051 public void SendGroupFullUpdate() 2269 public void SendGroupFullUpdate()
2052 { 2270 {
2053 if (IsDeleted) 2271 if (IsDeleted)
2054 return; 2272 return;
2055 2273
2056// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); 2274// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID);
2057 2275
2058 RootPart.SendFullUpdateToAllClients(); 2276 RootPart.SendFullUpdateToAllClients();
2059 2277
2060 lock (m_parts) 2278 lockPartsForRead(true);
2061 { 2279 {
2062 foreach (SceneObjectPart part in m_parts.Values) 2280 foreach (SceneObjectPart part in m_parts.Values)
2063 { 2281 {
2282
2064 if (part != RootPart) 2283 if (part != RootPart)
2065 part.SendFullUpdateToAllClients(); 2284 part.SendFullUpdateToAllClients();
2285
2066 } 2286 }
2067 } 2287 }
2288 lockPartsForRead(false);
2068 } 2289 }
2069 2290
2070 /// <summary> 2291 /// <summary>
@@ -2096,14 +2317,15 @@ namespace OpenSim.Region.Framework.Scenes
2096 { 2317 {
2097 if (IsDeleted) 2318 if (IsDeleted)
2098 return; 2319 return;
2099 2320
2100 lock (m_parts) 2321 lockPartsForRead(true);
2101 { 2322 {
2102 foreach (SceneObjectPart part in m_parts.Values) 2323 foreach (SceneObjectPart part in m_parts.Values)
2103 { 2324 {
2104 part.SendTerseUpdateToAllClients(); 2325 part.SendTerseUpdateToAllClients();
2105 } 2326 }
2106 } 2327 }
2328 lockPartsForRead(false);
2107 } 2329 }
2108 2330
2109 #endregion 2331 #endregion
@@ -2117,16 +2339,18 @@ namespace OpenSim.Region.Framework.Scenes
2117 /// <returns>null if no child part with that linknum or child part</returns> 2339 /// <returns>null if no child part with that linknum or child part</returns>
2118 public SceneObjectPart GetLinkNumPart(int linknum) 2340 public SceneObjectPart GetLinkNumPart(int linknum)
2119 { 2341 {
2120 lock (m_parts) 2342 lockPartsForRead(true);
2121 { 2343 {
2122 foreach (SceneObjectPart part in m_parts.Values) 2344 foreach (SceneObjectPart part in m_parts.Values)
2123 { 2345 {
2124 if (part.LinkNum == linknum) 2346 if (part.LinkNum == linknum)
2125 { 2347 {
2348 lockPartsForRead(false);
2126 return part; 2349 return part;
2127 } 2350 }
2128 } 2351 }
2129 } 2352 }
2353 lockPartsForRead(false);
2130 2354
2131 return null; 2355 return null;
2132 } 2356 }
@@ -2154,17 +2378,19 @@ namespace OpenSim.Region.Framework.Scenes
2154 public SceneObjectPart GetChildPart(uint localID) 2378 public SceneObjectPart GetChildPart(uint localID)
2155 { 2379 {
2156 //m_log.DebugFormat("Entered looking for {0}", localID); 2380 //m_log.DebugFormat("Entered looking for {0}", localID);
2157 lock (m_parts) 2381 lockPartsForRead(true);
2158 { 2382 {
2159 foreach (SceneObjectPart part in m_parts.Values) 2383 foreach (SceneObjectPart part in m_parts.Values)
2160 { 2384 {
2161 //m_log.DebugFormat("Found {0}", part.LocalId); 2385 //m_log.DebugFormat("Found {0}", part.LocalId);
2162 if (part.LocalId == localID) 2386 if (part.LocalId == localID)
2163 { 2387 {
2388 lockPartsForRead(false);
2164 return part; 2389 return part;
2165 } 2390 }
2166 } 2391 }
2167 } 2392 }
2393 lockPartsForRead(false);
2168 2394
2169 return null; 2395 return null;
2170 } 2396 }
@@ -2194,17 +2420,19 @@ namespace OpenSim.Region.Framework.Scenes
2194 public bool HasChildPrim(uint localID) 2420 public bool HasChildPrim(uint localID)
2195 { 2421 {
2196 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID); 2422 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID);
2197 lock (m_parts) 2423 lockPartsForRead(true);
2198 { 2424 {
2199 foreach (SceneObjectPart part in m_parts.Values) 2425 foreach (SceneObjectPart part in m_parts.Values)
2200 { 2426 {
2201 //m_log.DebugFormat("Found {0}", part.LocalId); 2427 //m_log.DebugFormat("Found {0}", part.LocalId);
2202 if (part.LocalId == localID) 2428 if (part.LocalId == localID)
2203 { 2429 {
2430 lockPartsForRead(false);
2204 return true; 2431 return true;
2205 } 2432 }
2206 } 2433 }
2207 } 2434 }
2435 lockPartsForRead(false);
2208 2436
2209 return false; 2437 return false;
2210 } 2438 }
@@ -2254,53 +2482,57 @@ namespace OpenSim.Region.Framework.Scenes
2254 if (m_rootPart.LinkNum == 0) 2482 if (m_rootPart.LinkNum == 0)
2255 m_rootPart.LinkNum = 1; 2483 m_rootPart.LinkNum = 1;
2256 2484
2257 lock (m_parts) 2485 lockPartsForWrite(true);
2258 { 2486
2259 m_parts.Add(linkPart.UUID, linkPart); 2487 m_parts.Add(linkPart.UUID, linkPart);
2488
2489 lockPartsForWrite(false);
2260 2490
2261 // Insert in terms of link numbers, the new links 2491 // Insert in terms of link numbers, the new links
2262 // before the current ones (with the exception of 2492 // before the current ones (with the exception of
2263 // the root prim. Shuffle the old ones up 2493 // the root prim. Shuffle the old ones up
2264 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts) 2494 lockPartsForRead(true);
2495 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts)
2496 {
2497 if (kvp.Value.LinkNum != 1)
2265 { 2498 {
2266 if (kvp.Value.LinkNum != 1) 2499 // Don't update root prim link number
2267 { 2500 kvp.Value.LinkNum += objectGroup.PrimCount;
2268 // Don't update root prim link number
2269 kvp.Value.LinkNum += objectGroup.PrimCount;
2270 }
2271 } 2501 }
2502 }
2503 lockPartsForRead(false);
2272 2504
2273 linkPart.LinkNum = 2; 2505 linkPart.LinkNum = 2;
2274 2506
2275 linkPart.SetParent(this); 2507 linkPart.SetParent(this);
2276 linkPart.CreateSelected = true; 2508 linkPart.CreateSelected = true;
2277 2509
2278 //if (linkPart.PhysActor != null) 2510 //if (linkPart.PhysActor != null)
2279 //{ 2511 //{
2280 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); 2512 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor);
2281 2513
2282 //linkPart.PhysActor = null; 2514 //linkPart.PhysActor = null;
2283 //} 2515 //}
2284 2516
2285 //TODO: rest of parts 2517 //TODO: rest of parts
2286 int linkNum = 3; 2518 int linkNum = 3;
2287 foreach (SceneObjectPart part in objectGroup.Children.Values) 2519 foreach (SceneObjectPart part in objectGroup.Children.Values)
2520 {
2521 if (part.UUID != objectGroup.m_rootPart.UUID)
2288 { 2522 {
2289 if (part.UUID != objectGroup.m_rootPart.UUID) 2523 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2290 {
2291 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2292 }
2293 part.ClearUndoState();
2294 } 2524 }
2525 part.ClearUndoState();
2295 } 2526 }
2296 2527
2297 m_scene.UnlinkSceneObject(objectGroup.UUID, true); 2528 m_scene.UnlinkSceneObject(objectGroup.UUID, true);
2298 objectGroup.m_isDeleted = true; 2529 objectGroup.m_isDeleted = true;
2530
2531 objectGroup.lockPartsForWrite(true);
2299 2532
2300 lock (objectGroup.m_parts) 2533 objectGroup.m_parts.Clear();
2301 { 2534
2302 objectGroup.m_parts.Clear(); 2535 objectGroup.lockPartsForWrite(false);
2303 }
2304 2536
2305 // Can't do this yet since backup still makes use of the root part without any synchronization 2537 // Can't do this yet since backup still makes use of the root part without any synchronization
2306// objectGroup.m_rootPart = null; 2538// objectGroup.m_rootPart = null;
@@ -2370,11 +2602,12 @@ namespace OpenSim.Region.Framework.Scenes
2370 Quaternion worldRot = linkPart.GetWorldRotation(); 2602 Quaternion worldRot = linkPart.GetWorldRotation();
2371 2603
2372 // Remove the part from this object 2604 // Remove the part from this object
2373 lock (m_parts) 2605 lockPartsForWrite(true);
2374 { 2606 {
2375 m_parts.Remove(linkPart.UUID); 2607 m_parts.Remove(linkPart.UUID);
2376 } 2608 }
2377 2609 lockPartsForWrite(false);
2610 lockPartsForRead(true);
2378 if (m_parts.Count == 1 && RootPart != null) //Single prim is left 2611 if (m_parts.Count == 1 && RootPart != null) //Single prim is left
2379 RootPart.LinkNum = 0; 2612 RootPart.LinkNum = 0;
2380 else 2613 else
@@ -2385,6 +2618,7 @@ namespace OpenSim.Region.Framework.Scenes
2385 p.LinkNum--; 2618 p.LinkNum--;
2386 } 2619 }
2387 } 2620 }
2621 lockPartsForRead(false);
2388 2622
2389 linkPart.ParentID = 0; 2623 linkPart.ParentID = 0;
2390 linkPart.LinkNum = 0; 2624 linkPart.LinkNum = 0;
@@ -2706,9 +2940,12 @@ namespace OpenSim.Region.Framework.Scenes
2706 2940
2707 if (selectionPart != null) 2941 if (selectionPart != null)
2708 { 2942 {
2709 lock (m_parts) 2943 lockPartsForRead(true);
2944 List<SceneObjectPart> parts = new List<SceneObjectPart>(m_parts.Values);
2945 lockPartsForRead(false);
2946 foreach (SceneObjectPart part in parts)
2710 { 2947 {
2711 foreach (SceneObjectPart part in m_parts.Values) 2948 if (part.Scale.X > 10.0 || part.Scale.Y > 10.0 || part.Scale.Z > 10.0)
2712 { 2949 {
2713 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax || 2950 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax ||
2714 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax || 2951 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax ||
@@ -2718,12 +2955,13 @@ namespace OpenSim.Region.Framework.Scenes
2718 break; 2955 break;
2719 } 2956 }
2720 } 2957 }
2958 }
2721 2959
2722 foreach (SceneObjectPart part in m_parts.Values) 2960 foreach (SceneObjectPart part in parts)
2723 { 2961 {
2724 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect); 2962 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
2725 }
2726 } 2963 }
2964
2727 } 2965 }
2728 } 2966 }
2729 2967
@@ -2809,11 +3047,9 @@ namespace OpenSim.Region.Framework.Scenes
2809 scale.Y = m_scene.m_maxNonphys; 3047 scale.Y = m_scene.m_maxNonphys;
2810 if (scale.Z > m_scene.m_maxNonphys) 3048 if (scale.Z > m_scene.m_maxNonphys)
2811 scale.Z = m_scene.m_maxNonphys; 3049 scale.Z = m_scene.m_maxNonphys;
2812
2813 SceneObjectPart part = GetChildPart(localID); 3050 SceneObjectPart part = GetChildPart(localID);
2814 if (part != null) 3051 if (part != null)
2815 { 3052 {
2816 part.Resize(scale);
2817 if (part.PhysActor != null) 3053 if (part.PhysActor != null)
2818 { 3054 {
2819 if (part.PhysActor.IsPhysical) 3055 if (part.PhysActor.IsPhysical)
@@ -2828,7 +3064,7 @@ namespace OpenSim.Region.Framework.Scenes
2828 part.PhysActor.Size = scale; 3064 part.PhysActor.Size = scale;
2829 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); 3065 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor);
2830 } 3066 }
2831 //if (part.UUID != m_rootPart.UUID) 3067 part.Resize(scale);
2832 3068
2833 HasGroupChanged = true; 3069 HasGroupChanged = true;
2834 ScheduleGroupForFullUpdate(); 3070 ScheduleGroupForFullUpdate();
@@ -2870,73 +3106,71 @@ namespace OpenSim.Region.Framework.Scenes
2870 float y = (scale.Y / part.Scale.Y); 3106 float y = (scale.Y / part.Scale.Y);
2871 float z = (scale.Z / part.Scale.Z); 3107 float z = (scale.Z / part.Scale.Z);
2872 3108
2873 lock (m_parts) 3109 lockPartsForRead(true);
3110 if (x > 1.0f || y > 1.0f || z > 1.0f)
2874 { 3111 {
2875 if (x > 1.0f || y > 1.0f || z > 1.0f) 3112 foreach (SceneObjectPart obPart in m_parts.Values)
2876 { 3113 {
2877 foreach (SceneObjectPart obPart in m_parts.Values) 3114 if (obPart.UUID != m_rootPart.UUID)
2878 { 3115 {
2879 if (obPart.UUID != m_rootPart.UUID) 3116 Vector3 oldSize = new Vector3(obPart.Scale);
2880 { 3117 obPart.IgnoreUndoUpdate = true;
2881 obPart.IgnoreUndoUpdate = true;
2882 Vector3 oldSize = new Vector3(obPart.Scale);
2883 3118
2884 float f = 1.0f; 3119 float f = 1.0f;
2885 float a = 1.0f; 3120 float a = 1.0f;
2886 3121
2887 if (part.PhysActor != null && part.PhysActor.IsPhysical) 3122 if (part.PhysActor != null && part.PhysActor.IsPhysical)
3123 {
3124 if (oldSize.X*x > m_scene.m_maxPhys)
2888 { 3125 {
2889 if (oldSize.X*x > m_scene.m_maxPhys) 3126 f = m_scene.m_maxPhys / oldSize.X;
2890 { 3127 a = f / x;
2891 f = m_scene.m_maxPhys / oldSize.X; 3128 x *= a;
2892 a = f / x; 3129 y *= a;
2893 x *= a; 3130 z *= a;
2894 y *= a;
2895 z *= a;
2896 }
2897 if (oldSize.Y*y > m_scene.m_maxPhys)
2898 {
2899 f = m_scene.m_maxPhys / oldSize.Y;
2900 a = f / y;
2901 x *= a;
2902 y *= a;
2903 z *= a;
2904 }
2905 if (oldSize.Z*z > m_scene.m_maxPhys)
2906 {
2907 f = m_scene.m_maxPhys / oldSize.Z;
2908 a = f / z;
2909 x *= a;
2910 y *= a;
2911 z *= a;
2912 }
2913 } 3131 }
2914 else 3132 if (oldSize.Y*y > m_scene.m_maxPhys)
2915 { 3133 {
2916 if (oldSize.X*x > m_scene.m_maxNonphys) 3134 f = m_scene.m_maxPhys / oldSize.Y;
2917 { 3135 a = f / y;
2918 f = m_scene.m_maxNonphys / oldSize.X; 3136 x *= a;
2919 a = f / x; 3137 y *= a;
2920 x *= a; 3138 z *= a;
2921 y *= a; 3139 }
2922 z *= a; 3140 if (oldSize.Z*z > m_scene.m_maxPhys)
2923 } 3141 {
2924 if (oldSize.Y*y > m_scene.m_maxNonphys) 3142 f = m_scene.m_maxPhys / oldSize.Z;
2925 { 3143 a = f / z;
2926 f = m_scene.m_maxNonphys / oldSize.Y; 3144 x *= a;
2927 a = f / y; 3145 y *= a;
2928 x *= a; 3146 z *= a;
2929 y *= a; 3147 }
2930 z *= a; 3148 }
2931 } 3149 else
2932 if (oldSize.Z*z > m_scene.m_maxNonphys) 3150 {
2933 { 3151 if (oldSize.X*x > m_scene.m_maxNonphys)
2934 f = m_scene.m_maxNonphys / oldSize.Z; 3152 {
2935 a = f / z; 3153 f = m_scene.m_maxNonphys / oldSize.X;
2936 x *= a; 3154 a = f / x;
2937 y *= a; 3155 x *= a;
2938 z *= a; 3156 y *= a;
2939 } 3157 z *= a;
3158 }
3159 if (oldSize.Y*y > m_scene.m_maxNonphys)
3160 {
3161 f = m_scene.m_maxNonphys / oldSize.Y;
3162 a = f / y;
3163 x *= a;
3164 y *= a;
3165 z *= a;
3166 }
3167 if (oldSize.Z*z > m_scene.m_maxNonphys)
3168 {
3169 f = m_scene.m_maxNonphys / oldSize.Z;
3170 a = f / z;
3171 x *= a;
3172 y *= a;
3173 z *= a;
2940 } 3174 }
2941 obPart.IgnoreUndoUpdate = false; 3175 obPart.IgnoreUndoUpdate = false;
2942 obPart.StoreUndoState(); 3176 obPart.StoreUndoState();
@@ -2944,6 +3178,7 @@ namespace OpenSim.Region.Framework.Scenes
2944 } 3178 }
2945 } 3179 }
2946 } 3180 }
3181 lockPartsForRead(false);
2947 3182
2948 Vector3 prevScale = part.Scale; 3183 Vector3 prevScale = part.Scale;
2949 prevScale.X *= x; 3184 prevScale.X *= x;
@@ -2951,7 +3186,7 @@ namespace OpenSim.Region.Framework.Scenes
2951 prevScale.Z *= z; 3186 prevScale.Z *= z;
2952 part.Resize(prevScale); 3187 part.Resize(prevScale);
2953 3188
2954 lock (m_parts) 3189 lockPartsForRead(true);
2955 { 3190 {
2956 foreach (SceneObjectPart obPart in m_parts.Values) 3191 foreach (SceneObjectPart obPart in m_parts.Values)
2957 { 3192 {
@@ -2973,6 +3208,7 @@ namespace OpenSim.Region.Framework.Scenes
2973 obPart.StoreUndoState(); 3208 obPart.StoreUndoState();
2974 } 3209 }
2975 } 3210 }
3211 lockPartsForRead(false);
2976 3212
2977 if (part.PhysActor != null) 3213 if (part.PhysActor != null)
2978 { 3214 {
@@ -3075,7 +3311,7 @@ namespace OpenSim.Region.Framework.Scenes
3075 axDiff *= Quaternion.Inverse(partRotation); 3311 axDiff *= Quaternion.Inverse(partRotation);
3076 diff = axDiff; 3312 diff = axDiff;
3077 3313
3078 lock (m_parts) 3314 lockPartsForRead(true);
3079 { 3315 {
3080 foreach (SceneObjectPart obPart in m_parts.Values) 3316 foreach (SceneObjectPart obPart in m_parts.Values)
3081 { 3317 {
@@ -3085,6 +3321,7 @@ namespace OpenSim.Region.Framework.Scenes
3085 } 3321 }
3086 } 3322 }
3087 } 3323 }
3324 lockPartsForRead(false);
3088 3325
3089 AbsolutePosition = newPos; 3326 AbsolutePosition = newPos;
3090 3327
@@ -3218,25 +3455,25 @@ namespace OpenSim.Region.Framework.Scenes
3218 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); 3455 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
3219 } 3456 }
3220 3457
3221 lock (m_parts) 3458 lockPartsForRead(true);
3459
3460 foreach (SceneObjectPart prim in m_parts.Values)
3222 { 3461 {
3223 foreach (SceneObjectPart prim in m_parts.Values) 3462 if (prim.UUID != m_rootPart.UUID)
3224 { 3463 {
3225 if (prim.UUID != m_rootPart.UUID) 3464 prim.IgnoreUndoUpdate = true;
3226 { 3465 Vector3 axPos = prim.OffsetPosition;
3227 prim.IgnoreUndoUpdate = true; 3466 axPos *= oldParentRot;
3228 Vector3 axPos = prim.OffsetPosition; 3467 axPos *= Quaternion.Inverse(axRot);
3229 axPos *= oldParentRot; 3468 prim.OffsetPosition = axPos;
3230 axPos *= Quaternion.Inverse(axRot); 3469 Quaternion primsRot = prim.RotationOffset;
3231 prim.OffsetPosition = axPos; 3470 Quaternion newRot = primsRot * oldParentRot;
3232 Quaternion primsRot = prim.RotationOffset; 3471 newRot *= Quaternion.Inverse(axRot);
3233 Quaternion newRot = primsRot * oldParentRot; 3472 prim.RotationOffset = newRot;
3234 newRot *= Quaternion.Inverse(axRot); 3473 prim.ScheduleTerseUpdate();
3235 prim.RotationOffset = newRot;
3236 prim.ScheduleTerseUpdate();
3237 }
3238 } 3474 }
3239 } 3475 }
3476
3240 foreach (SceneObjectPart childpart in Children.Values) 3477 foreach (SceneObjectPart childpart in Children.Values)
3241 { 3478 {
3242 if (childpart != m_rootPart) 3479 if (childpart != m_rootPart)
@@ -3245,6 +3482,9 @@ namespace OpenSim.Region.Framework.Scenes
3245 childpart.StoreUndoState(); 3482 childpart.StoreUndoState();
3246 } 3483 }
3247 } 3484 }
3485
3486 lockPartsForRead(false);
3487
3248 m_rootPart.ScheduleTerseUpdate(); 3488 m_rootPart.ScheduleTerseUpdate();
3249 } 3489 }
3250 3490
@@ -3366,7 +3606,7 @@ namespace OpenSim.Region.Framework.Scenes
3366 if (atTargets.Count > 0) 3606 if (atTargets.Count > 0)
3367 { 3607 {
3368 uint[] localids = new uint[0]; 3608 uint[] localids = new uint[0];
3369 lock (m_parts) 3609 lockPartsForRead(true);
3370 { 3610 {
3371 localids = new uint[m_parts.Count]; 3611 localids = new uint[m_parts.Count];
3372 int cntr = 0; 3612 int cntr = 0;
@@ -3376,6 +3616,7 @@ namespace OpenSim.Region.Framework.Scenes
3376 cntr++; 3616 cntr++;
3377 } 3617 }
3378 } 3618 }
3619 lockPartsForRead(false);
3379 3620
3380 for (int ctr = 0; ctr < localids.Length; ctr++) 3621 for (int ctr = 0; ctr < localids.Length; ctr++)
3381 { 3622 {
@@ -3394,7 +3635,7 @@ namespace OpenSim.Region.Framework.Scenes
3394 { 3635 {
3395 //trigger not_at_target 3636 //trigger not_at_target
3396 uint[] localids = new uint[0]; 3637 uint[] localids = new uint[0];
3397 lock (m_parts) 3638 lockPartsForRead(true);
3398 { 3639 {
3399 localids = new uint[m_parts.Count]; 3640 localids = new uint[m_parts.Count];
3400 int cntr = 0; 3641 int cntr = 0;
@@ -3404,7 +3645,8 @@ namespace OpenSim.Region.Framework.Scenes
3404 cntr++; 3645 cntr++;
3405 } 3646 }
3406 } 3647 }
3407 3648 lockPartsForRead(false);
3649
3408 for (int ctr = 0; ctr < localids.Length; ctr++) 3650 for (int ctr = 0; ctr < localids.Length; ctr++)
3409 { 3651 {
3410 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]); 3652 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]);
@@ -3445,7 +3687,8 @@ namespace OpenSim.Region.Framework.Scenes
3445 if (atRotTargets.Count > 0) 3687 if (atRotTargets.Count > 0)
3446 { 3688 {
3447 uint[] localids = new uint[0]; 3689 uint[] localids = new uint[0];
3448 lock (m_parts) 3690 lockPartsForRead(true);
3691 try
3449 { 3692 {
3450 localids = new uint[m_parts.Count]; 3693 localids = new uint[m_parts.Count];
3451 int cntr = 0; 3694 int cntr = 0;
@@ -3455,6 +3698,10 @@ namespace OpenSim.Region.Framework.Scenes
3455 cntr++; 3698 cntr++;
3456 } 3699 }
3457 } 3700 }
3701 finally
3702 {
3703 lockPartsForRead(false);
3704 }
3458 3705
3459 for (int ctr = 0; ctr < localids.Length; ctr++) 3706 for (int ctr = 0; ctr < localids.Length; ctr++)
3460 { 3707 {
@@ -3473,7 +3720,8 @@ namespace OpenSim.Region.Framework.Scenes
3473 { 3720 {
3474 //trigger not_at_target 3721 //trigger not_at_target
3475 uint[] localids = new uint[0]; 3722 uint[] localids = new uint[0];
3476 lock (m_parts) 3723 lockPartsForRead(true);
3724 try
3477 { 3725 {
3478 localids = new uint[m_parts.Count]; 3726 localids = new uint[m_parts.Count];
3479 int cntr = 0; 3727 int cntr = 0;
@@ -3483,6 +3731,10 @@ namespace OpenSim.Region.Framework.Scenes
3483 cntr++; 3731 cntr++;
3484 } 3732 }
3485 } 3733 }
3734 finally
3735 {
3736 lockPartsForRead(false);
3737 }
3486 3738
3487 for (int ctr = 0; ctr < localids.Length; ctr++) 3739 for (int ctr = 0; ctr < localids.Length; ctr++)
3488 { 3740 {
@@ -3496,19 +3748,20 @@ namespace OpenSim.Region.Framework.Scenes
3496 public float GetMass() 3748 public float GetMass()
3497 { 3749 {
3498 float retmass = 0f; 3750 float retmass = 0f;
3499 lock (m_parts) 3751 lockPartsForRead(true);
3500 { 3752 {
3501 foreach (SceneObjectPart part in m_parts.Values) 3753 foreach (SceneObjectPart part in m_parts.Values)
3502 { 3754 {
3503 retmass += part.GetMass(); 3755 retmass += part.GetMass();
3504 } 3756 }
3505 } 3757 }
3758 lockPartsForRead(false);
3506 return retmass; 3759 return retmass;
3507 } 3760 }
3508 3761
3509 public void CheckSculptAndLoad() 3762 public void CheckSculptAndLoad()
3510 { 3763 {
3511 lock (m_parts) 3764 lockPartsForRead(true);
3512 { 3765 {
3513 if (!IsDeleted) 3766 if (!IsDeleted)
3514 { 3767 {
@@ -3533,6 +3786,7 @@ namespace OpenSim.Region.Framework.Scenes
3533 } 3786 }
3534 } 3787 }
3535 } 3788 }
3789 lockPartsForRead(false);
3536 } 3790 }
3537 3791
3538 protected void AssetReceived(string id, Object sender, AssetBase asset) 3792 protected void AssetReceived(string id, Object sender, AssetBase asset)
@@ -3553,7 +3807,7 @@ namespace OpenSim.Region.Framework.Scenes
3553 /// <param name="client"></param> 3807 /// <param name="client"></param>
3554 public void SetGroup(UUID GroupID, IClientAPI client) 3808 public void SetGroup(UUID GroupID, IClientAPI client)
3555 { 3809 {
3556 lock (m_parts) 3810 lockPartsForRead(true);
3557 { 3811 {
3558 foreach (SceneObjectPart part in m_parts.Values) 3812 foreach (SceneObjectPart part in m_parts.Values)
3559 { 3813 {
@@ -3563,6 +3817,7 @@ namespace OpenSim.Region.Framework.Scenes
3563 3817
3564 HasGroupChanged = true; 3818 HasGroupChanged = true;
3565 } 3819 }
3820 lockPartsForRead(false);
3566 3821
3567 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled 3822 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled
3568 // for the same object with very different properties. The caller must schedule the update. 3823 // for the same object with very different properties. The caller must schedule the update.
@@ -3584,11 +3839,12 @@ namespace OpenSim.Region.Framework.Scenes
3584 3839
3585 public void SetAttachmentPoint(byte point) 3840 public void SetAttachmentPoint(byte point)
3586 { 3841 {
3587 lock (m_parts) 3842 lockPartsForRead(true);
3588 { 3843 {
3589 foreach (SceneObjectPart part in m_parts.Values) 3844 foreach (SceneObjectPart part in m_parts.Values)
3590 part.SetAttachmentPoint(point); 3845 part.SetAttachmentPoint(point);
3591 } 3846 }
3847 lockPartsForRead(false);
3592 } 3848 }
3593 3849
3594 #region ISceneObject 3850 #region ISceneObject
@@ -3622,6 +3878,14 @@ namespace OpenSim.Region.Framework.Scenes
3622 SetFromItemID(uuid); 3878 SetFromItemID(uuid);
3623 } 3879 }
3624 3880
3881 public void ResetOwnerChangeFlag()
3882 {
3883 ForEachPart(delegate(SceneObjectPart part)
3884 {
3885 part.ResetOwnerChangeFlag();
3886 });
3887 }
3888
3625 #endregion 3889 #endregion
3626 } 3890 }
3627} 3891}