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.cs702
1 files changed, 483 insertions, 219 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 837d3a2..7e73f91 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 {
@@ -1111,13 +1265,16 @@ namespace OpenSim.Region.Framework.Scenes
1111 1265
1112 public override void UpdateMovement() 1266 public override void UpdateMovement()
1113 { 1267 {
1114 lock (m_parts) 1268 lockPartsForRead(true);
1115 { 1269 {
1116 foreach (SceneObjectPart part in m_parts.Values) 1270 foreach (SceneObjectPart part in m_parts.Values)
1117 { 1271 {
1272
1118 part.UpdateMovement(); 1273 part.UpdateMovement();
1274
1119 } 1275 }
1120 } 1276 }
1277 lockPartsForRead(false);
1121 } 1278 }
1122 1279
1123 public ushort GetTimeDilation() 1280 public ushort GetTimeDilation()
@@ -1161,7 +1318,7 @@ namespace OpenSim.Region.Framework.Scenes
1161 /// <param name="part"></param> 1318 /// <param name="part"></param>
1162 public void AddPart(SceneObjectPart part) 1319 public void AddPart(SceneObjectPart part)
1163 { 1320 {
1164 lock (m_parts) 1321 lockPartsForWrite(true);
1165 { 1322 {
1166 part.SetParent(this); 1323 part.SetParent(this);
1167 m_parts.Add(part.UUID, part); 1324 m_parts.Add(part.UUID, part);
@@ -1171,6 +1328,7 @@ namespace OpenSim.Region.Framework.Scenes
1171 if (part.LinkNum == 2 && RootPart != null) 1328 if (part.LinkNum == 2 && RootPart != null)
1172 RootPart.LinkNum = 1; 1329 RootPart.LinkNum = 1;
1173 } 1330 }
1331 lockPartsForWrite(false);
1174 } 1332 }
1175 1333
1176 /// <summary> 1334 /// <summary>
@@ -1178,28 +1336,33 @@ namespace OpenSim.Region.Framework.Scenes
1178 /// </summary> 1336 /// </summary>
1179 private void UpdateParentIDs() 1337 private void UpdateParentIDs()
1180 { 1338 {
1181 lock (m_parts) 1339 lockPartsForRead(true);
1182 { 1340 {
1183 foreach (SceneObjectPart part in m_parts.Values) 1341 foreach (SceneObjectPart part in m_parts.Values)
1184 { 1342 {
1343
1185 if (part.UUID != m_rootPart.UUID) 1344 if (part.UUID != m_rootPart.UUID)
1186 { 1345 {
1187 part.ParentID = m_rootPart.LocalId; 1346 part.ParentID = m_rootPart.LocalId;
1188 } 1347 }
1348
1189 } 1349 }
1190 } 1350 }
1351 lockPartsForRead(false);
1191 } 1352 }
1192 1353
1193 public void RegenerateFullIDs() 1354 public void RegenerateFullIDs()
1194 { 1355 {
1195 lock (m_parts) 1356 lockPartsForRead(true);
1196 { 1357 {
1197 foreach (SceneObjectPart part in m_parts.Values) 1358 foreach (SceneObjectPart part in m_parts.Values)
1198 { 1359 {
1360
1199 part.UUID = UUID.Random(); 1361 part.UUID = UUID.Random();
1200 1362
1201 } 1363 }
1202 } 1364 }
1365 lockPartsForRead(false);
1203 } 1366 }
1204 1367
1205 // helper provided for parts. 1368 // helper provided for parts.
@@ -1280,27 +1443,32 @@ namespace OpenSim.Region.Framework.Scenes
1280 1443
1281 DetachFromBackup(); 1444 DetachFromBackup();
1282 1445
1283 lock (m_parts) 1446 lockPartsForRead(true);
1447 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1448 lockPartsForRead(false);
1449
1450 foreach (SceneObjectPart part in values)
1284 { 1451 {
1285 foreach (SceneObjectPart part in m_parts.Values)
1286 {
1287// part.Inventory.RemoveScriptInstances(); 1452// part.Inventory.RemoveScriptInstances();
1288 Scene.ForEachScenePresence(delegate(ScenePresence avatar) 1453
1454 Scene.ForEachScenePresence(delegate (ScenePresence sp)
1455 {
1456 if (sp.ParentID == LocalId)
1289 { 1457 {
1290 if (avatar.ParentID == LocalId) 1458 sp.StandUp();
1291 { 1459 }
1292 avatar.StandUp();
1293 }
1294 1460
1295 if (!silent) 1461 if (!silent)
1296 { 1462 {
1297 part.UpdateFlag = 0; 1463 part.UpdateFlag = 0;
1298 if (part == m_rootPart) 1464 if (part == m_rootPart)
1299 avatar.ControllingClient.SendKillObject(m_regionHandle, part.LocalId); 1465 sp.ControllingClient.SendKillObject(m_regionHandle, part.LocalId);
1300 } 1466 }
1301 }); 1467 });
1302 } 1468
1303 } 1469 }
1470
1471
1304 } 1472 }
1305 1473
1306 public void AddScriptLPS(int count) 1474 public void AddScriptLPS(int count)
@@ -1325,17 +1493,20 @@ namespace OpenSim.Region.Framework.Scenes
1325 1493
1326 scriptEvents aggregateScriptEvents=0; 1494 scriptEvents aggregateScriptEvents=0;
1327 1495
1328 lock (m_parts) 1496 lockPartsForRead(true);
1329 { 1497 {
1330 foreach (SceneObjectPart part in m_parts.Values) 1498 foreach (SceneObjectPart part in m_parts.Values)
1331 { 1499 {
1500
1332 if (part == null) 1501 if (part == null)
1333 continue; 1502 continue;
1334 if (part != RootPart) 1503 if (part != RootPart)
1335 part.ObjectFlags = objectflagupdate; 1504 part.ObjectFlags = objectflagupdate;
1336 aggregateScriptEvents |= part.AggregateScriptEvents; 1505 aggregateScriptEvents |= part.AggregateScriptEvents;
1506
1337 } 1507 }
1338 } 1508 }
1509 lockPartsForRead(false);
1339 1510
1340 m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0); 1511 m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0);
1341 m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0); 1512 m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0);
@@ -1377,42 +1548,52 @@ namespace OpenSim.Region.Framework.Scenes
1377 /// <param name="m_physicalPrim"></param> 1548 /// <param name="m_physicalPrim"></param>
1378 public void ApplyPhysics(bool m_physicalPrim) 1549 public void ApplyPhysics(bool m_physicalPrim)
1379 { 1550 {
1380 lock (m_parts) 1551 lockPartsForRead(true);
1552
1553 if (m_parts.Count > 1)
1381 { 1554 {
1382 if (m_parts.Count > 1) 1555 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1556 lockPartsForRead(false);
1557 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1558 foreach (SceneObjectPart part in values)
1383 { 1559 {
1384 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim); 1560
1385 foreach (SceneObjectPart part in m_parts.Values) 1561 if (part.LocalId != m_rootPart.LocalId)
1386 { 1562 {
1387 if (part.LocalId != m_rootPart.LocalId) 1563 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim);
1388 {
1389 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim);
1390 }
1391 } 1564 }
1392 1565
1393 // Hack to get the physics scene geometries in the right spot
1394 ResetChildPrimPhysicsPositions();
1395 }
1396 else
1397 {
1398 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1399 } 1566 }
1567 // Hack to get the physics scene geometries in the right spot
1568 ResetChildPrimPhysicsPositions();
1569 }
1570 else
1571 {
1572 lockPartsForRead(false);
1573 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1400 } 1574 }
1401 } 1575 }
1402 1576
1403 public void SetOwnerId(UUID userId) 1577 public void SetOwnerId(UUID userId)
1404 { 1578 {
1405 ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); 1579 ForEachPart(delegate(SceneObjectPart part)
1580 {
1581
1582 part.OwnerID = userId;
1583
1584 });
1406 } 1585 }
1407 1586
1408 public void ForEachPart(Action<SceneObjectPart> whatToDo) 1587 public void ForEachPart(Action<SceneObjectPart> whatToDo)
1409 { 1588 {
1410 lock (m_parts) 1589 lockPartsForRead(true);
1590 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1591 lockPartsForRead(false);
1592 foreach (SceneObjectPart part in values)
1411 { 1593 {
1412 foreach (SceneObjectPart part in m_parts.Values) 1594
1413 { 1595 whatToDo(part);
1414 whatToDo(part); 1596
1415 }
1416 } 1597 }
1417 } 1598 }
1418 1599
@@ -1510,15 +1691,17 @@ namespace OpenSim.Region.Framework.Scenes
1510 RootPart.SendFullUpdate( 1691 RootPart.SendFullUpdate(
1511 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID)); 1692 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID));
1512 1693
1513 lock (m_parts) 1694 lockPartsForRead(true);
1514 { 1695 {
1515 foreach (SceneObjectPart part in m_parts.Values) 1696 foreach (SceneObjectPart part in m_parts.Values)
1516 { 1697 {
1698
1517 if (part != RootPart) 1699 if (part != RootPart)
1518 part.SendFullUpdate( 1700 part.SendFullUpdate(
1519 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID)); 1701 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID));
1520 } 1702 }
1521 } 1703 }
1704 lockPartsForRead(false);
1522 } 1705 }
1523 1706
1524 #region Copying 1707 #region Copying
@@ -1587,10 +1770,11 @@ namespace OpenSim.Region.Framework.Scenes
1587 1770
1588 List<SceneObjectPart> partList; 1771 List<SceneObjectPart> partList;
1589 1772
1590 lock (m_parts) 1773 lockPartsForRead(true);
1591 { 1774
1592 partList = new List<SceneObjectPart>(m_parts.Values); 1775 partList = new List<SceneObjectPart>(m_parts.Values);
1593 } 1776
1777 lockPartsForRead(false);
1594 1778
1595 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) 1779 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1596 { 1780 {
@@ -1813,13 +1997,40 @@ namespace OpenSim.Region.Framework.Scenes
1813 } 1997 }
1814 } 1998 }
1815 1999
2000 public void rotLookAt(Quaternion target, float strength, float damping)
2001 {
2002 SceneObjectPart rootpart = m_rootPart;
2003 if (rootpart != null)
2004 {
2005 if (IsAttachment)
2006 {
2007 /*
2008 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
2009 if (avatar != null)
2010 {
2011 Rotate the Av?
2012 } */
2013 }
2014 else
2015 {
2016 if (rootpart.PhysActor != null)
2017 { // APID must be implemented in your physics system for this to function.
2018 rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W);
2019 rootpart.PhysActor.APIDStrength = strength;
2020 rootpart.PhysActor.APIDDamping = damping;
2021 rootpart.PhysActor.APIDActive = true;
2022 }
2023 }
2024 }
2025 }
2026
1816 public void stopLookAt() 2027 public void stopLookAt()
1817 { 2028 {
1818 SceneObjectPart rootpart = m_rootPart; 2029 SceneObjectPart rootpart = m_rootPart;
1819 if (rootpart != null) 2030 if (rootpart != null)
1820 { 2031 {
1821 if (rootpart.PhysActor != null) 2032 if (rootpart.PhysActor != null)
1822 { 2033 { // APID must be implemented in your physics system for this to function.
1823 rootpart.PhysActor.APIDActive = false; 2034 rootpart.PhysActor.APIDActive = false;
1824 } 2035 }
1825 } 2036 }
@@ -1887,10 +2098,11 @@ namespace OpenSim.Region.Framework.Scenes
1887 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 2098 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
1888 newPart.SetParent(this); 2099 newPart.SetParent(this);
1889 2100
1890 lock (m_parts) 2101 lockPartsForWrite(true);
1891 { 2102 {
1892 m_parts.Add(newPart.UUID, newPart); 2103 m_parts.Add(newPart.UUID, newPart);
1893 } 2104 }
2105 lockPartsForWrite(false);
1894 2106
1895 SetPartAsNonRoot(newPart); 2107 SetPartAsNonRoot(newPart);
1896 2108
@@ -1953,7 +2165,7 @@ namespace OpenSim.Region.Framework.Scenes
1953 //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0) 2165 //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
1954 // return; 2166 // return;
1955 2167
1956 lock (m_parts) 2168 lockPartsForRead(true);
1957 { 2169 {
1958 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0); 2170 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0);
1959 2171
@@ -1973,9 +2185,12 @@ namespace OpenSim.Region.Framework.Scenes
1973 { 2185 {
1974 if (!IsSelected) 2186 if (!IsSelected)
1975 part.UpdateLookAt(); 2187 part.UpdateLookAt();
2188
1976 part.SendScheduledUpdates(); 2189 part.SendScheduledUpdates();
2190
1977 } 2191 }
1978 } 2192 }
2193 lockPartsForRead(false);
1979 } 2194 }
1980 2195
1981 public void ScheduleFullUpdateToAvatar(ScenePresence presence) 2196 public void ScheduleFullUpdateToAvatar(ScenePresence presence)
@@ -1984,27 +2199,29 @@ namespace OpenSim.Region.Framework.Scenes
1984 2199
1985 RootPart.AddFullUpdateToAvatar(presence); 2200 RootPart.AddFullUpdateToAvatar(presence);
1986 2201
1987 lock (m_parts) 2202 lockPartsForRead(true);
1988 { 2203 {
1989 foreach (SceneObjectPart part in m_parts.Values) 2204 foreach (SceneObjectPart part in m_parts.Values)
1990 { 2205 {
2206
1991 if (part != RootPart) 2207 if (part != RootPart)
1992 part.AddFullUpdateToAvatar(presence); 2208 part.AddFullUpdateToAvatar(presence);
2209
1993 } 2210 }
1994 } 2211 }
2212 lockPartsForRead(false);
1995 } 2213 }
1996 2214
1997 public void ScheduleTerseUpdateToAvatar(ScenePresence presence) 2215 public void ScheduleTerseUpdateToAvatar(ScenePresence presence)
1998 { 2216 {
1999// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1} just to avatar {2}", Name, UUID, presence.Name); 2217 lockPartsForRead(true);
2000 2218
2001 lock (m_parts) 2219 foreach (SceneObjectPart part in m_parts.Values)
2002 { 2220 {
2003 foreach (SceneObjectPart part in m_parts.Values) 2221 part.AddTerseUpdateToAvatar(presence);
2004 {
2005 part.AddTerseUpdateToAvatar(presence);
2006 }
2007 } 2222 }
2223
2224 lockPartsForRead(false);
2008 } 2225 }
2009 2226
2010 /// <summary> 2227 /// <summary>
@@ -2017,14 +2234,17 @@ namespace OpenSim.Region.Framework.Scenes
2017 checkAtTargets(); 2234 checkAtTargets();
2018 RootPart.ScheduleFullUpdate(); 2235 RootPart.ScheduleFullUpdate();
2019 2236
2020 lock (m_parts) 2237 lockPartsForRead(true);
2021 { 2238 {
2022 foreach (SceneObjectPart part in m_parts.Values) 2239 foreach (SceneObjectPart part in m_parts.Values)
2023 { 2240 {
2241
2024 if (part != RootPart) 2242 if (part != RootPart)
2025 part.ScheduleFullUpdate(); 2243 part.ScheduleFullUpdate();
2244
2026 } 2245 }
2027 } 2246 }
2247 lockPartsForRead(false);
2028 } 2248 }
2029 2249
2030 /// <summary> 2250 /// <summary>
@@ -2032,37 +2252,38 @@ namespace OpenSim.Region.Framework.Scenes
2032 /// </summary> 2252 /// </summary>
2033 public void ScheduleGroupForTerseUpdate() 2253 public void ScheduleGroupForTerseUpdate()
2034 { 2254 {
2035// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1}", Name, UUID); 2255 lockPartsForRead(true);
2036 2256 foreach (SceneObjectPart part in m_parts.Values)
2037 lock (m_parts)
2038 { 2257 {
2039 foreach (SceneObjectPart part in m_parts.Values) 2258 part.ScheduleTerseUpdate();
2040 {
2041 part.ScheduleTerseUpdate();
2042 }
2043 } 2259 }
2260
2261 lockPartsForRead(false);
2044 } 2262 }
2045 2263
2046 /// <summary> 2264 /// <summary>
2047 /// Immediately send a full update for this scene object. 2265 /// Immediately send a full update for this scene object.
2048 /// </summary> 2266 /// </summary>
2049 public void SendGroupFullUpdate() 2267 public void SendGroupFullUpdate()
2050 { 2268 {
2051 if (IsDeleted) 2269 if (IsDeleted)
2052 return; 2270 return;
2053 2271
2054// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); 2272// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID);
2055 2273
2056 RootPart.SendFullUpdateToAllClients(); 2274 RootPart.SendFullUpdateToAllClients();
2057 2275
2058 lock (m_parts) 2276 lockPartsForRead(true);
2059 { 2277 {
2060 foreach (SceneObjectPart part in m_parts.Values) 2278 foreach (SceneObjectPart part in m_parts.Values)
2061 { 2279 {
2280
2062 if (part != RootPart) 2281 if (part != RootPart)
2063 part.SendFullUpdateToAllClients(); 2282 part.SendFullUpdateToAllClients();
2283
2064 } 2284 }
2065 } 2285 }
2286 lockPartsForRead(false);
2066 } 2287 }
2067 2288
2068 /// <summary> 2289 /// <summary>
@@ -2094,14 +2315,15 @@ namespace OpenSim.Region.Framework.Scenes
2094 { 2315 {
2095 if (IsDeleted) 2316 if (IsDeleted)
2096 return; 2317 return;
2097 2318
2098 lock (m_parts) 2319 lockPartsForRead(true);
2099 { 2320 {
2100 foreach (SceneObjectPart part in m_parts.Values) 2321 foreach (SceneObjectPart part in m_parts.Values)
2101 { 2322 {
2102 part.SendTerseUpdateToAllClients(); 2323 part.SendTerseUpdateToAllClients();
2103 } 2324 }
2104 } 2325 }
2326 lockPartsForRead(false);
2105 } 2327 }
2106 2328
2107 #endregion 2329 #endregion
@@ -2115,16 +2337,18 @@ namespace OpenSim.Region.Framework.Scenes
2115 /// <returns>null if no child part with that linknum or child part</returns> 2337 /// <returns>null if no child part with that linknum or child part</returns>
2116 public SceneObjectPart GetLinkNumPart(int linknum) 2338 public SceneObjectPart GetLinkNumPart(int linknum)
2117 { 2339 {
2118 lock (m_parts) 2340 lockPartsForRead(true);
2119 { 2341 {
2120 foreach (SceneObjectPart part in m_parts.Values) 2342 foreach (SceneObjectPart part in m_parts.Values)
2121 { 2343 {
2122 if (part.LinkNum == linknum) 2344 if (part.LinkNum == linknum)
2123 { 2345 {
2346 lockPartsForRead(false);
2124 return part; 2347 return part;
2125 } 2348 }
2126 } 2349 }
2127 } 2350 }
2351 lockPartsForRead(false);
2128 2352
2129 return null; 2353 return null;
2130 } 2354 }
@@ -2152,17 +2376,19 @@ namespace OpenSim.Region.Framework.Scenes
2152 public SceneObjectPart GetChildPart(uint localID) 2376 public SceneObjectPart GetChildPart(uint localID)
2153 { 2377 {
2154 //m_log.DebugFormat("Entered looking for {0}", localID); 2378 //m_log.DebugFormat("Entered looking for {0}", localID);
2155 lock (m_parts) 2379 lockPartsForRead(true);
2156 { 2380 {
2157 foreach (SceneObjectPart part in m_parts.Values) 2381 foreach (SceneObjectPart part in m_parts.Values)
2158 { 2382 {
2159 //m_log.DebugFormat("Found {0}", part.LocalId); 2383 //m_log.DebugFormat("Found {0}", part.LocalId);
2160 if (part.LocalId == localID) 2384 if (part.LocalId == localID)
2161 { 2385 {
2386 lockPartsForRead(false);
2162 return part; 2387 return part;
2163 } 2388 }
2164 } 2389 }
2165 } 2390 }
2391 lockPartsForRead(false);
2166 2392
2167 return null; 2393 return null;
2168 } 2394 }
@@ -2192,17 +2418,19 @@ namespace OpenSim.Region.Framework.Scenes
2192 public bool HasChildPrim(uint localID) 2418 public bool HasChildPrim(uint localID)
2193 { 2419 {
2194 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID); 2420 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID);
2195 lock (m_parts) 2421 lockPartsForRead(true);
2196 { 2422 {
2197 foreach (SceneObjectPart part in m_parts.Values) 2423 foreach (SceneObjectPart part in m_parts.Values)
2198 { 2424 {
2199 //m_log.DebugFormat("Found {0}", part.LocalId); 2425 //m_log.DebugFormat("Found {0}", part.LocalId);
2200 if (part.LocalId == localID) 2426 if (part.LocalId == localID)
2201 { 2427 {
2428 lockPartsForRead(false);
2202 return true; 2429 return true;
2203 } 2430 }
2204 } 2431 }
2205 } 2432 }
2433 lockPartsForRead(false);
2206 2434
2207 return false; 2435 return false;
2208 } 2436 }
@@ -2252,53 +2480,57 @@ namespace OpenSim.Region.Framework.Scenes
2252 if (m_rootPart.LinkNum == 0) 2480 if (m_rootPart.LinkNum == 0)
2253 m_rootPart.LinkNum = 1; 2481 m_rootPart.LinkNum = 1;
2254 2482
2255 lock (m_parts) 2483 lockPartsForWrite(true);
2256 { 2484
2257 m_parts.Add(linkPart.UUID, linkPart); 2485 m_parts.Add(linkPart.UUID, linkPart);
2486
2487 lockPartsForWrite(false);
2258 2488
2259 // Insert in terms of link numbers, the new links 2489 // Insert in terms of link numbers, the new links
2260 // before the current ones (with the exception of 2490 // before the current ones (with the exception of
2261 // the root prim. Shuffle the old ones up 2491 // the root prim. Shuffle the old ones up
2262 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts) 2492 lockPartsForRead(true);
2493 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts)
2494 {
2495 if (kvp.Value.LinkNum != 1)
2263 { 2496 {
2264 if (kvp.Value.LinkNum != 1) 2497 // Don't update root prim link number
2265 { 2498 kvp.Value.LinkNum += objectGroup.PrimCount;
2266 // Don't update root prim link number
2267 kvp.Value.LinkNum += objectGroup.PrimCount;
2268 }
2269 } 2499 }
2500 }
2501 lockPartsForRead(false);
2270 2502
2271 linkPart.LinkNum = 2; 2503 linkPart.LinkNum = 2;
2272 2504
2273 linkPart.SetParent(this); 2505 linkPart.SetParent(this);
2274 linkPart.CreateSelected = true; 2506 linkPart.CreateSelected = true;
2275 2507
2276 //if (linkPart.PhysActor != null) 2508 //if (linkPart.PhysActor != null)
2277 //{ 2509 //{
2278 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); 2510 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor);
2279 2511
2280 //linkPart.PhysActor = null; 2512 //linkPart.PhysActor = null;
2281 //} 2513 //}
2282 2514
2283 //TODO: rest of parts 2515 //TODO: rest of parts
2284 int linkNum = 3; 2516 int linkNum = 3;
2285 foreach (SceneObjectPart part in objectGroup.Children.Values) 2517 foreach (SceneObjectPart part in objectGroup.Children.Values)
2518 {
2519 if (part.UUID != objectGroup.m_rootPart.UUID)
2286 { 2520 {
2287 if (part.UUID != objectGroup.m_rootPart.UUID) 2521 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2288 {
2289 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2290 }
2291 part.ClearUndoState();
2292 } 2522 }
2523 part.ClearUndoState();
2293 } 2524 }
2294 2525
2295 m_scene.UnlinkSceneObject(objectGroup.UUID, true); 2526 m_scene.UnlinkSceneObject(objectGroup.UUID, true);
2296 objectGroup.m_isDeleted = true; 2527 objectGroup.m_isDeleted = true;
2528
2529 objectGroup.lockPartsForWrite(true);
2297 2530
2298 lock (objectGroup.m_parts) 2531 objectGroup.m_parts.Clear();
2299 { 2532
2300 objectGroup.m_parts.Clear(); 2533 objectGroup.lockPartsForWrite(false);
2301 }
2302 2534
2303 // Can't do this yet since backup still makes use of the root part without any synchronization 2535 // Can't do this yet since backup still makes use of the root part without any synchronization
2304// objectGroup.m_rootPart = null; 2536// objectGroup.m_rootPart = null;
@@ -2368,11 +2600,12 @@ namespace OpenSim.Region.Framework.Scenes
2368 Quaternion worldRot = linkPart.GetWorldRotation(); 2600 Quaternion worldRot = linkPart.GetWorldRotation();
2369 2601
2370 // Remove the part from this object 2602 // Remove the part from this object
2371 lock (m_parts) 2603 lockPartsForWrite(true);
2372 { 2604 {
2373 m_parts.Remove(linkPart.UUID); 2605 m_parts.Remove(linkPart.UUID);
2374 } 2606 }
2375 2607 lockPartsForWrite(false);
2608 lockPartsForRead(true);
2376 if (m_parts.Count == 1 && RootPart != null) //Single prim is left 2609 if (m_parts.Count == 1 && RootPart != null) //Single prim is left
2377 RootPart.LinkNum = 0; 2610 RootPart.LinkNum = 0;
2378 else 2611 else
@@ -2383,6 +2616,7 @@ namespace OpenSim.Region.Framework.Scenes
2383 p.LinkNum--; 2616 p.LinkNum--;
2384 } 2617 }
2385 } 2618 }
2619 lockPartsForRead(false);
2386 2620
2387 linkPart.ParentID = 0; 2621 linkPart.ParentID = 0;
2388 linkPart.LinkNum = 0; 2622 linkPart.LinkNum = 0;
@@ -2704,9 +2938,12 @@ namespace OpenSim.Region.Framework.Scenes
2704 2938
2705 if (selectionPart != null) 2939 if (selectionPart != null)
2706 { 2940 {
2707 lock (m_parts) 2941 lockPartsForRead(true);
2942 List<SceneObjectPart> parts = new List<SceneObjectPart>(m_parts.Values);
2943 lockPartsForRead(false);
2944 foreach (SceneObjectPart part in parts)
2708 { 2945 {
2709 foreach (SceneObjectPart part in m_parts.Values) 2946 if (part.Scale.X > 10.0 || part.Scale.Y > 10.0 || part.Scale.Z > 10.0)
2710 { 2947 {
2711 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax || 2948 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax ||
2712 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax || 2949 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax ||
@@ -2716,12 +2953,13 @@ namespace OpenSim.Region.Framework.Scenes
2716 break; 2953 break;
2717 } 2954 }
2718 } 2955 }
2956 }
2719 2957
2720 foreach (SceneObjectPart part in m_parts.Values) 2958 foreach (SceneObjectPart part in parts)
2721 { 2959 {
2722 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect); 2960 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
2723 }
2724 } 2961 }
2962
2725 } 2963 }
2726 } 2964 }
2727 2965
@@ -2807,11 +3045,9 @@ namespace OpenSim.Region.Framework.Scenes
2807 scale.Y = m_scene.m_maxNonphys; 3045 scale.Y = m_scene.m_maxNonphys;
2808 if (scale.Z > m_scene.m_maxNonphys) 3046 if (scale.Z > m_scene.m_maxNonphys)
2809 scale.Z = m_scene.m_maxNonphys; 3047 scale.Z = m_scene.m_maxNonphys;
2810
2811 SceneObjectPart part = GetChildPart(localID); 3048 SceneObjectPart part = GetChildPart(localID);
2812 if (part != null) 3049 if (part != null)
2813 { 3050 {
2814 part.Resize(scale);
2815 if (part.PhysActor != null) 3051 if (part.PhysActor != null)
2816 { 3052 {
2817 if (part.PhysActor.IsPhysical) 3053 if (part.PhysActor.IsPhysical)
@@ -2826,7 +3062,7 @@ namespace OpenSim.Region.Framework.Scenes
2826 part.PhysActor.Size = scale; 3062 part.PhysActor.Size = scale;
2827 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); 3063 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor);
2828 } 3064 }
2829 //if (part.UUID != m_rootPart.UUID) 3065 part.Resize(scale);
2830 3066
2831 HasGroupChanged = true; 3067 HasGroupChanged = true;
2832 ScheduleGroupForFullUpdate(); 3068 ScheduleGroupForFullUpdate();
@@ -2868,73 +3104,71 @@ namespace OpenSim.Region.Framework.Scenes
2868 float y = (scale.Y / part.Scale.Y); 3104 float y = (scale.Y / part.Scale.Y);
2869 float z = (scale.Z / part.Scale.Z); 3105 float z = (scale.Z / part.Scale.Z);
2870 3106
2871 lock (m_parts) 3107 lockPartsForRead(true);
3108 if (x > 1.0f || y > 1.0f || z > 1.0f)
2872 { 3109 {
2873 if (x > 1.0f || y > 1.0f || z > 1.0f) 3110 foreach (SceneObjectPart obPart in m_parts.Values)
2874 { 3111 {
2875 foreach (SceneObjectPart obPart in m_parts.Values) 3112 if (obPart.UUID != m_rootPart.UUID)
2876 { 3113 {
2877 if (obPart.UUID != m_rootPart.UUID) 3114 Vector3 oldSize = new Vector3(obPart.Scale);
2878 { 3115 obPart.IgnoreUndoUpdate = true;
2879 obPart.IgnoreUndoUpdate = true;
2880 Vector3 oldSize = new Vector3(obPart.Scale);
2881 3116
2882 float f = 1.0f; 3117 float f = 1.0f;
2883 float a = 1.0f; 3118 float a = 1.0f;
2884 3119
2885 if (part.PhysActor != null && part.PhysActor.IsPhysical) 3120 if (part.PhysActor != null && part.PhysActor.IsPhysical)
3121 {
3122 if (oldSize.X*x > m_scene.m_maxPhys)
2886 { 3123 {
2887 if (oldSize.X*x > m_scene.m_maxPhys) 3124 f = m_scene.m_maxPhys / oldSize.X;
2888 { 3125 a = f / x;
2889 f = m_scene.m_maxPhys / oldSize.X; 3126 x *= a;
2890 a = f / x; 3127 y *= a;
2891 x *= a; 3128 z *= a;
2892 y *= a;
2893 z *= a;
2894 }
2895 if (oldSize.Y*y > m_scene.m_maxPhys)
2896 {
2897 f = m_scene.m_maxPhys / oldSize.Y;
2898 a = f / y;
2899 x *= a;
2900 y *= a;
2901 z *= a;
2902 }
2903 if (oldSize.Z*z > m_scene.m_maxPhys)
2904 {
2905 f = m_scene.m_maxPhys / oldSize.Z;
2906 a = f / z;
2907 x *= a;
2908 y *= a;
2909 z *= a;
2910 }
2911 } 3129 }
2912 else 3130 if (oldSize.Y*y > m_scene.m_maxPhys)
2913 { 3131 {
2914 if (oldSize.X*x > m_scene.m_maxNonphys) 3132 f = m_scene.m_maxPhys / oldSize.Y;
2915 { 3133 a = f / y;
2916 f = m_scene.m_maxNonphys / oldSize.X; 3134 x *= a;
2917 a = f / x; 3135 y *= a;
2918 x *= a; 3136 z *= a;
2919 y *= a; 3137 }
2920 z *= a; 3138 if (oldSize.Z*z > m_scene.m_maxPhys)
2921 } 3139 {
2922 if (oldSize.Y*y > m_scene.m_maxNonphys) 3140 f = m_scene.m_maxPhys / oldSize.Z;
2923 { 3141 a = f / z;
2924 f = m_scene.m_maxNonphys / oldSize.Y; 3142 x *= a;
2925 a = f / y; 3143 y *= a;
2926 x *= a; 3144 z *= a;
2927 y *= a; 3145 }
2928 z *= a; 3146 }
2929 } 3147 else
2930 if (oldSize.Z*z > m_scene.m_maxNonphys) 3148 {
2931 { 3149 if (oldSize.X*x > m_scene.m_maxNonphys)
2932 f = m_scene.m_maxNonphys / oldSize.Z; 3150 {
2933 a = f / z; 3151 f = m_scene.m_maxNonphys / oldSize.X;
2934 x *= a; 3152 a = f / x;
2935 y *= a; 3153 x *= a;
2936 z *= a; 3154 y *= a;
2937 } 3155 z *= a;
3156 }
3157 if (oldSize.Y*y > m_scene.m_maxNonphys)
3158 {
3159 f = m_scene.m_maxNonphys / oldSize.Y;
3160 a = f / y;
3161 x *= a;
3162 y *= a;
3163 z *= a;
3164 }
3165 if (oldSize.Z*z > m_scene.m_maxNonphys)
3166 {
3167 f = m_scene.m_maxNonphys / oldSize.Z;
3168 a = f / z;
3169 x *= a;
3170 y *= a;
3171 z *= a;
2938 } 3172 }
2939 obPart.IgnoreUndoUpdate = false; 3173 obPart.IgnoreUndoUpdate = false;
2940 obPart.StoreUndoState(); 3174 obPart.StoreUndoState();
@@ -2942,6 +3176,7 @@ namespace OpenSim.Region.Framework.Scenes
2942 } 3176 }
2943 } 3177 }
2944 } 3178 }
3179 lockPartsForRead(false);
2945 3180
2946 Vector3 prevScale = part.Scale; 3181 Vector3 prevScale = part.Scale;
2947 prevScale.X *= x; 3182 prevScale.X *= x;
@@ -2949,7 +3184,7 @@ namespace OpenSim.Region.Framework.Scenes
2949 prevScale.Z *= z; 3184 prevScale.Z *= z;
2950 part.Resize(prevScale); 3185 part.Resize(prevScale);
2951 3186
2952 lock (m_parts) 3187 lockPartsForRead(true);
2953 { 3188 {
2954 foreach (SceneObjectPart obPart in m_parts.Values) 3189 foreach (SceneObjectPart obPart in m_parts.Values)
2955 { 3190 {
@@ -2971,6 +3206,7 @@ namespace OpenSim.Region.Framework.Scenes
2971 obPart.StoreUndoState(); 3206 obPart.StoreUndoState();
2972 } 3207 }
2973 } 3208 }
3209 lockPartsForRead(false);
2974 3210
2975 if (part.PhysActor != null) 3211 if (part.PhysActor != null)
2976 { 3212 {
@@ -3073,7 +3309,7 @@ namespace OpenSim.Region.Framework.Scenes
3073 axDiff *= Quaternion.Inverse(partRotation); 3309 axDiff *= Quaternion.Inverse(partRotation);
3074 diff = axDiff; 3310 diff = axDiff;
3075 3311
3076 lock (m_parts) 3312 lockPartsForRead(true);
3077 { 3313 {
3078 foreach (SceneObjectPart obPart in m_parts.Values) 3314 foreach (SceneObjectPart obPart in m_parts.Values)
3079 { 3315 {
@@ -3083,6 +3319,7 @@ namespace OpenSim.Region.Framework.Scenes
3083 } 3319 }
3084 } 3320 }
3085 } 3321 }
3322 lockPartsForRead(false);
3086 3323
3087 AbsolutePosition = newPos; 3324 AbsolutePosition = newPos;
3088 3325
@@ -3216,25 +3453,25 @@ namespace OpenSim.Region.Framework.Scenes
3216 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); 3453 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
3217 } 3454 }
3218 3455
3219 lock (m_parts) 3456 lockPartsForRead(true);
3457
3458 foreach (SceneObjectPart prim in m_parts.Values)
3220 { 3459 {
3221 foreach (SceneObjectPart prim in m_parts.Values) 3460 if (prim.UUID != m_rootPart.UUID)
3222 { 3461 {
3223 if (prim.UUID != m_rootPart.UUID) 3462 prim.IgnoreUndoUpdate = true;
3224 { 3463 Vector3 axPos = prim.OffsetPosition;
3225 prim.IgnoreUndoUpdate = true; 3464 axPos *= oldParentRot;
3226 Vector3 axPos = prim.OffsetPosition; 3465 axPos *= Quaternion.Inverse(axRot);
3227 axPos *= oldParentRot; 3466 prim.OffsetPosition = axPos;
3228 axPos *= Quaternion.Inverse(axRot); 3467 Quaternion primsRot = prim.RotationOffset;
3229 prim.OffsetPosition = axPos; 3468 Quaternion newRot = primsRot * oldParentRot;
3230 Quaternion primsRot = prim.RotationOffset; 3469 newRot *= Quaternion.Inverse(axRot);
3231 Quaternion newRot = primsRot * oldParentRot; 3470 prim.RotationOffset = newRot;
3232 newRot *= Quaternion.Inverse(axRot); 3471 prim.ScheduleTerseUpdate();
3233 prim.RotationOffset = newRot;
3234 prim.ScheduleTerseUpdate();
3235 }
3236 } 3472 }
3237 } 3473 }
3474
3238 foreach (SceneObjectPart childpart in Children.Values) 3475 foreach (SceneObjectPart childpart in Children.Values)
3239 { 3476 {
3240 if (childpart != m_rootPart) 3477 if (childpart != m_rootPart)
@@ -3243,6 +3480,9 @@ namespace OpenSim.Region.Framework.Scenes
3243 childpart.StoreUndoState(); 3480 childpart.StoreUndoState();
3244 } 3481 }
3245 } 3482 }
3483
3484 lockPartsForRead(false);
3485
3246 m_rootPart.ScheduleTerseUpdate(); 3486 m_rootPart.ScheduleTerseUpdate();
3247 } 3487 }
3248 3488
@@ -3364,7 +3604,7 @@ namespace OpenSim.Region.Framework.Scenes
3364 if (atTargets.Count > 0) 3604 if (atTargets.Count > 0)
3365 { 3605 {
3366 uint[] localids = new uint[0]; 3606 uint[] localids = new uint[0];
3367 lock (m_parts) 3607 lockPartsForRead(true);
3368 { 3608 {
3369 localids = new uint[m_parts.Count]; 3609 localids = new uint[m_parts.Count];
3370 int cntr = 0; 3610 int cntr = 0;
@@ -3374,6 +3614,7 @@ namespace OpenSim.Region.Framework.Scenes
3374 cntr++; 3614 cntr++;
3375 } 3615 }
3376 } 3616 }
3617 lockPartsForRead(false);
3377 3618
3378 for (int ctr = 0; ctr < localids.Length; ctr++) 3619 for (int ctr = 0; ctr < localids.Length; ctr++)
3379 { 3620 {
@@ -3392,7 +3633,7 @@ namespace OpenSim.Region.Framework.Scenes
3392 { 3633 {
3393 //trigger not_at_target 3634 //trigger not_at_target
3394 uint[] localids = new uint[0]; 3635 uint[] localids = new uint[0];
3395 lock (m_parts) 3636 lockPartsForRead(true);
3396 { 3637 {
3397 localids = new uint[m_parts.Count]; 3638 localids = new uint[m_parts.Count];
3398 int cntr = 0; 3639 int cntr = 0;
@@ -3402,7 +3643,8 @@ namespace OpenSim.Region.Framework.Scenes
3402 cntr++; 3643 cntr++;
3403 } 3644 }
3404 } 3645 }
3405 3646 lockPartsForRead(false);
3647
3406 for (int ctr = 0; ctr < localids.Length; ctr++) 3648 for (int ctr = 0; ctr < localids.Length; ctr++)
3407 { 3649 {
3408 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]); 3650 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]);
@@ -3443,7 +3685,8 @@ namespace OpenSim.Region.Framework.Scenes
3443 if (atRotTargets.Count > 0) 3685 if (atRotTargets.Count > 0)
3444 { 3686 {
3445 uint[] localids = new uint[0]; 3687 uint[] localids = new uint[0];
3446 lock (m_parts) 3688 lockPartsForRead(true);
3689 try
3447 { 3690 {
3448 localids = new uint[m_parts.Count]; 3691 localids = new uint[m_parts.Count];
3449 int cntr = 0; 3692 int cntr = 0;
@@ -3453,6 +3696,10 @@ namespace OpenSim.Region.Framework.Scenes
3453 cntr++; 3696 cntr++;
3454 } 3697 }
3455 } 3698 }
3699 finally
3700 {
3701 lockPartsForRead(false);
3702 }
3456 3703
3457 for (int ctr = 0; ctr < localids.Length; ctr++) 3704 for (int ctr = 0; ctr < localids.Length; ctr++)
3458 { 3705 {
@@ -3471,7 +3718,8 @@ namespace OpenSim.Region.Framework.Scenes
3471 { 3718 {
3472 //trigger not_at_target 3719 //trigger not_at_target
3473 uint[] localids = new uint[0]; 3720 uint[] localids = new uint[0];
3474 lock (m_parts) 3721 lockPartsForRead(true);
3722 try
3475 { 3723 {
3476 localids = new uint[m_parts.Count]; 3724 localids = new uint[m_parts.Count];
3477 int cntr = 0; 3725 int cntr = 0;
@@ -3481,6 +3729,10 @@ namespace OpenSim.Region.Framework.Scenes
3481 cntr++; 3729 cntr++;
3482 } 3730 }
3483 } 3731 }
3732 finally
3733 {
3734 lockPartsForRead(false);
3735 }
3484 3736
3485 for (int ctr = 0; ctr < localids.Length; ctr++) 3737 for (int ctr = 0; ctr < localids.Length; ctr++)
3486 { 3738 {
@@ -3494,19 +3746,20 @@ namespace OpenSim.Region.Framework.Scenes
3494 public float GetMass() 3746 public float GetMass()
3495 { 3747 {
3496 float retmass = 0f; 3748 float retmass = 0f;
3497 lock (m_parts) 3749 lockPartsForRead(true);
3498 { 3750 {
3499 foreach (SceneObjectPart part in m_parts.Values) 3751 foreach (SceneObjectPart part in m_parts.Values)
3500 { 3752 {
3501 retmass += part.GetMass(); 3753 retmass += part.GetMass();
3502 } 3754 }
3503 } 3755 }
3756 lockPartsForRead(false);
3504 return retmass; 3757 return retmass;
3505 } 3758 }
3506 3759
3507 public void CheckSculptAndLoad() 3760 public void CheckSculptAndLoad()
3508 { 3761 {
3509 lock (m_parts) 3762 lockPartsForRead(true);
3510 { 3763 {
3511 if (!IsDeleted) 3764 if (!IsDeleted)
3512 { 3765 {
@@ -3531,6 +3784,7 @@ namespace OpenSim.Region.Framework.Scenes
3531 } 3784 }
3532 } 3785 }
3533 } 3786 }
3787 lockPartsForRead(false);
3534 } 3788 }
3535 3789
3536 protected void AssetReceived(string id, Object sender, AssetBase asset) 3790 protected void AssetReceived(string id, Object sender, AssetBase asset)
@@ -3551,7 +3805,7 @@ namespace OpenSim.Region.Framework.Scenes
3551 /// <param name="client"></param> 3805 /// <param name="client"></param>
3552 public void SetGroup(UUID GroupID, IClientAPI client) 3806 public void SetGroup(UUID GroupID, IClientAPI client)
3553 { 3807 {
3554 lock (m_parts) 3808 lockPartsForRead(true);
3555 { 3809 {
3556 foreach (SceneObjectPart part in m_parts.Values) 3810 foreach (SceneObjectPart part in m_parts.Values)
3557 { 3811 {
@@ -3561,6 +3815,7 @@ namespace OpenSim.Region.Framework.Scenes
3561 3815
3562 HasGroupChanged = true; 3816 HasGroupChanged = true;
3563 } 3817 }
3818 lockPartsForRead(false);
3564 3819
3565 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled 3820 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled
3566 // for the same object with very different properties. The caller must schedule the update. 3821 // for the same object with very different properties. The caller must schedule the update.
@@ -3582,11 +3837,12 @@ namespace OpenSim.Region.Framework.Scenes
3582 3837
3583 public void SetAttachmentPoint(byte point) 3838 public void SetAttachmentPoint(byte point)
3584 { 3839 {
3585 lock (m_parts) 3840 lockPartsForRead(true);
3586 { 3841 {
3587 foreach (SceneObjectPart part in m_parts.Values) 3842 foreach (SceneObjectPart part in m_parts.Values)
3588 part.SetAttachmentPoint(point); 3843 part.SetAttachmentPoint(point);
3589 } 3844 }
3845 lockPartsForRead(false);
3590 } 3846 }
3591 3847
3592 #region ISceneObject 3848 #region ISceneObject
@@ -3620,6 +3876,14 @@ namespace OpenSim.Region.Framework.Scenes
3620 SetFromItemID(uuid); 3876 SetFromItemID(uuid);
3621 } 3877 }
3622 3878
3879 public void ResetOwnerChangeFlag()
3880 {
3881 ForEachPart(delegate(SceneObjectPart part)
3882 {
3883 part.ResetOwnerChangeFlag();
3884 });
3885 }
3886
3623 #endregion 3887 #endregion
3624 } 3888 }
3625} 3889}