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 78c2566..f918291 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>
@@ -2018,14 +2235,17 @@ namespace OpenSim.Region.Framework.Scenes
2018 checkAtTargets(); 2235 checkAtTargets();
2019 RootPart.ScheduleFullUpdate(); 2236 RootPart.ScheduleFullUpdate();
2020 2237
2021 lock (m_parts) 2238 lockPartsForRead(true);
2022 { 2239 {
2023 foreach (SceneObjectPart part in m_parts.Values) 2240 foreach (SceneObjectPart part in m_parts.Values)
2024 { 2241 {
2242
2025 if (part != RootPart) 2243 if (part != RootPart)
2026 part.ScheduleFullUpdate(); 2244 part.ScheduleFullUpdate();
2245
2027 } 2246 }
2028 } 2247 }
2248 lockPartsForRead(false);
2029 } 2249 }
2030 2250
2031 /// <summary> 2251 /// <summary>
@@ -2033,37 +2253,38 @@ namespace OpenSim.Region.Framework.Scenes
2033 /// </summary> 2253 /// </summary>
2034 public void ScheduleGroupForTerseUpdate() 2254 public void ScheduleGroupForTerseUpdate()
2035 { 2255 {
2036// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1}", Name, UUID); 2256 lockPartsForRead(true);
2037 2257 foreach (SceneObjectPart part in m_parts.Values)
2038 lock (m_parts)
2039 { 2258 {
2040 foreach (SceneObjectPart part in m_parts.Values) 2259 part.ScheduleTerseUpdate();
2041 {
2042 part.ScheduleTerseUpdate();
2043 }
2044 } 2260 }
2261
2262 lockPartsForRead(false);
2045 } 2263 }
2046 2264
2047 /// <summary> 2265 /// <summary>
2048 /// Immediately send a full update for this scene object. 2266 /// Immediately send a full update for this scene object.
2049 /// </summary> 2267 /// </summary>
2050 public void SendGroupFullUpdate() 2268 public void SendGroupFullUpdate()
2051 { 2269 {
2052 if (IsDeleted) 2270 if (IsDeleted)
2053 return; 2271 return;
2054 2272
2055// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); 2273// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID);
2056 2274
2057 RootPart.SendFullUpdateToAllClients(); 2275 RootPart.SendFullUpdateToAllClients();
2058 2276
2059 lock (m_parts) 2277 lockPartsForRead(true);
2060 { 2278 {
2061 foreach (SceneObjectPart part in m_parts.Values) 2279 foreach (SceneObjectPart part in m_parts.Values)
2062 { 2280 {
2281
2063 if (part != RootPart) 2282 if (part != RootPart)
2064 part.SendFullUpdateToAllClients(); 2283 part.SendFullUpdateToAllClients();
2284
2065 } 2285 }
2066 } 2286 }
2287 lockPartsForRead(false);
2067 } 2288 }
2068 2289
2069 /// <summary> 2290 /// <summary>
@@ -2095,14 +2316,15 @@ namespace OpenSim.Region.Framework.Scenes
2095 { 2316 {
2096 if (IsDeleted) 2317 if (IsDeleted)
2097 return; 2318 return;
2098 2319
2099 lock (m_parts) 2320 lockPartsForRead(true);
2100 { 2321 {
2101 foreach (SceneObjectPart part in m_parts.Values) 2322 foreach (SceneObjectPart part in m_parts.Values)
2102 { 2323 {
2103 part.SendTerseUpdateToAllClients(); 2324 part.SendTerseUpdateToAllClients();
2104 } 2325 }
2105 } 2326 }
2327 lockPartsForRead(false);
2106 } 2328 }
2107 2329
2108 #endregion 2330 #endregion
@@ -2116,16 +2338,18 @@ namespace OpenSim.Region.Framework.Scenes
2116 /// <returns>null if no child part with that linknum or child part</returns> 2338 /// <returns>null if no child part with that linknum or child part</returns>
2117 public SceneObjectPart GetLinkNumPart(int linknum) 2339 public SceneObjectPart GetLinkNumPart(int linknum)
2118 { 2340 {
2119 lock (m_parts) 2341 lockPartsForRead(true);
2120 { 2342 {
2121 foreach (SceneObjectPart part in m_parts.Values) 2343 foreach (SceneObjectPart part in m_parts.Values)
2122 { 2344 {
2123 if (part.LinkNum == linknum) 2345 if (part.LinkNum == linknum)
2124 { 2346 {
2347 lockPartsForRead(false);
2125 return part; 2348 return part;
2126 } 2349 }
2127 } 2350 }
2128 } 2351 }
2352 lockPartsForRead(false);
2129 2353
2130 return null; 2354 return null;
2131 } 2355 }
@@ -2153,17 +2377,19 @@ namespace OpenSim.Region.Framework.Scenes
2153 public SceneObjectPart GetChildPart(uint localID) 2377 public SceneObjectPart GetChildPart(uint localID)
2154 { 2378 {
2155 //m_log.DebugFormat("Entered looking for {0}", localID); 2379 //m_log.DebugFormat("Entered looking for {0}", localID);
2156 lock (m_parts) 2380 lockPartsForRead(true);
2157 { 2381 {
2158 foreach (SceneObjectPart part in m_parts.Values) 2382 foreach (SceneObjectPart part in m_parts.Values)
2159 { 2383 {
2160 //m_log.DebugFormat("Found {0}", part.LocalId); 2384 //m_log.DebugFormat("Found {0}", part.LocalId);
2161 if (part.LocalId == localID) 2385 if (part.LocalId == localID)
2162 { 2386 {
2387 lockPartsForRead(false);
2163 return part; 2388 return part;
2164 } 2389 }
2165 } 2390 }
2166 } 2391 }
2392 lockPartsForRead(false);
2167 2393
2168 return null; 2394 return null;
2169 } 2395 }
@@ -2193,17 +2419,19 @@ namespace OpenSim.Region.Framework.Scenes
2193 public bool HasChildPrim(uint localID) 2419 public bool HasChildPrim(uint localID)
2194 { 2420 {
2195 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID); 2421 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID);
2196 lock (m_parts) 2422 lockPartsForRead(true);
2197 { 2423 {
2198 foreach (SceneObjectPart part in m_parts.Values) 2424 foreach (SceneObjectPart part in m_parts.Values)
2199 { 2425 {
2200 //m_log.DebugFormat("Found {0}", part.LocalId); 2426 //m_log.DebugFormat("Found {0}", part.LocalId);
2201 if (part.LocalId == localID) 2427 if (part.LocalId == localID)
2202 { 2428 {
2429 lockPartsForRead(false);
2203 return true; 2430 return true;
2204 } 2431 }
2205 } 2432 }
2206 } 2433 }
2434 lockPartsForRead(false);
2207 2435
2208 return false; 2436 return false;
2209 } 2437 }
@@ -2253,53 +2481,57 @@ namespace OpenSim.Region.Framework.Scenes
2253 if (m_rootPart.LinkNum == 0) 2481 if (m_rootPart.LinkNum == 0)
2254 m_rootPart.LinkNum = 1; 2482 m_rootPart.LinkNum = 1;
2255 2483
2256 lock (m_parts) 2484 lockPartsForWrite(true);
2257 { 2485
2258 m_parts.Add(linkPart.UUID, linkPart); 2486 m_parts.Add(linkPart.UUID, linkPart);
2487
2488 lockPartsForWrite(false);
2259 2489
2260 // Insert in terms of link numbers, the new links 2490 // Insert in terms of link numbers, the new links
2261 // before the current ones (with the exception of 2491 // before the current ones (with the exception of
2262 // the root prim. Shuffle the old ones up 2492 // the root prim. Shuffle the old ones up
2263 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts) 2493 lockPartsForRead(true);
2494 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts)
2495 {
2496 if (kvp.Value.LinkNum != 1)
2264 { 2497 {
2265 if (kvp.Value.LinkNum != 1) 2498 // Don't update root prim link number
2266 { 2499 kvp.Value.LinkNum += objectGroup.PrimCount;
2267 // Don't update root prim link number
2268 kvp.Value.LinkNum += objectGroup.PrimCount;
2269 }
2270 } 2500 }
2501 }
2502 lockPartsForRead(false);
2271 2503
2272 linkPart.LinkNum = 2; 2504 linkPart.LinkNum = 2;
2273 2505
2274 linkPart.SetParent(this); 2506 linkPart.SetParent(this);
2275 linkPart.CreateSelected = true; 2507 linkPart.CreateSelected = true;
2276 2508
2277 //if (linkPart.PhysActor != null) 2509 //if (linkPart.PhysActor != null)
2278 //{ 2510 //{
2279 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); 2511 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor);
2280 2512
2281 //linkPart.PhysActor = null; 2513 //linkPart.PhysActor = null;
2282 //} 2514 //}
2283 2515
2284 //TODO: rest of parts 2516 //TODO: rest of parts
2285 int linkNum = 3; 2517 int linkNum = 3;
2286 foreach (SceneObjectPart part in objectGroup.Children.Values) 2518 foreach (SceneObjectPart part in objectGroup.Children.Values)
2519 {
2520 if (part.UUID != objectGroup.m_rootPart.UUID)
2287 { 2521 {
2288 if (part.UUID != objectGroup.m_rootPart.UUID) 2522 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2289 {
2290 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2291 }
2292 part.ClearUndoState();
2293 } 2523 }
2524 part.ClearUndoState();
2294 } 2525 }
2295 2526
2296 m_scene.UnlinkSceneObject(objectGroup.UUID, true); 2527 m_scene.UnlinkSceneObject(objectGroup.UUID, true);
2297 objectGroup.m_isDeleted = true; 2528 objectGroup.m_isDeleted = true;
2529
2530 objectGroup.lockPartsForWrite(true);
2298 2531
2299 lock (objectGroup.m_parts) 2532 objectGroup.m_parts.Clear();
2300 { 2533
2301 objectGroup.m_parts.Clear(); 2534 objectGroup.lockPartsForWrite(false);
2302 }
2303 2535
2304 // Can't do this yet since backup still makes use of the root part without any synchronization 2536 // Can't do this yet since backup still makes use of the root part without any synchronization
2305// objectGroup.m_rootPart = null; 2537// objectGroup.m_rootPart = null;
@@ -2369,11 +2601,12 @@ namespace OpenSim.Region.Framework.Scenes
2369 Quaternion worldRot = linkPart.GetWorldRotation(); 2601 Quaternion worldRot = linkPart.GetWorldRotation();
2370 2602
2371 // Remove the part from this object 2603 // Remove the part from this object
2372 lock (m_parts) 2604 lockPartsForWrite(true);
2373 { 2605 {
2374 m_parts.Remove(linkPart.UUID); 2606 m_parts.Remove(linkPart.UUID);
2375 } 2607 }
2376 2608 lockPartsForWrite(false);
2609 lockPartsForRead(true);
2377 if (m_parts.Count == 1 && RootPart != null) //Single prim is left 2610 if (m_parts.Count == 1 && RootPart != null) //Single prim is left
2378 RootPart.LinkNum = 0; 2611 RootPart.LinkNum = 0;
2379 else 2612 else
@@ -2384,6 +2617,7 @@ namespace OpenSim.Region.Framework.Scenes
2384 p.LinkNum--; 2617 p.LinkNum--;
2385 } 2618 }
2386 } 2619 }
2620 lockPartsForRead(false);
2387 2621
2388 linkPart.ParentID = 0; 2622 linkPart.ParentID = 0;
2389 linkPart.LinkNum = 0; 2623 linkPart.LinkNum = 0;
@@ -2705,9 +2939,12 @@ namespace OpenSim.Region.Framework.Scenes
2705 2939
2706 if (selectionPart != null) 2940 if (selectionPart != null)
2707 { 2941 {
2708 lock (m_parts) 2942 lockPartsForRead(true);
2943 List<SceneObjectPart> parts = new List<SceneObjectPart>(m_parts.Values);
2944 lockPartsForRead(false);
2945 foreach (SceneObjectPart part in parts)
2709 { 2946 {
2710 foreach (SceneObjectPart part in m_parts.Values) 2947 if (part.Scale.X > 10.0 || part.Scale.Y > 10.0 || part.Scale.Z > 10.0)
2711 { 2948 {
2712 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax || 2949 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax ||
2713 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax || 2950 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax ||
@@ -2717,12 +2954,13 @@ namespace OpenSim.Region.Framework.Scenes
2717 break; 2954 break;
2718 } 2955 }
2719 } 2956 }
2957 }
2720 2958
2721 foreach (SceneObjectPart part in m_parts.Values) 2959 foreach (SceneObjectPart part in parts)
2722 { 2960 {
2723 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect); 2961 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
2724 }
2725 } 2962 }
2963
2726 } 2964 }
2727 } 2965 }
2728 2966
@@ -2808,11 +3046,9 @@ namespace OpenSim.Region.Framework.Scenes
2808 scale.Y = m_scene.m_maxNonphys; 3046 scale.Y = m_scene.m_maxNonphys;
2809 if (scale.Z > m_scene.m_maxNonphys) 3047 if (scale.Z > m_scene.m_maxNonphys)
2810 scale.Z = m_scene.m_maxNonphys; 3048 scale.Z = m_scene.m_maxNonphys;
2811
2812 SceneObjectPart part = GetChildPart(localID); 3049 SceneObjectPart part = GetChildPart(localID);
2813 if (part != null) 3050 if (part != null)
2814 { 3051 {
2815 part.Resize(scale);
2816 if (part.PhysActor != null) 3052 if (part.PhysActor != null)
2817 { 3053 {
2818 if (part.PhysActor.IsPhysical) 3054 if (part.PhysActor.IsPhysical)
@@ -2827,7 +3063,7 @@ namespace OpenSim.Region.Framework.Scenes
2827 part.PhysActor.Size = scale; 3063 part.PhysActor.Size = scale;
2828 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); 3064 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor);
2829 } 3065 }
2830 //if (part.UUID != m_rootPart.UUID) 3066 part.Resize(scale);
2831 3067
2832 HasGroupChanged = true; 3068 HasGroupChanged = true;
2833 ScheduleGroupForFullUpdate(); 3069 ScheduleGroupForFullUpdate();
@@ -2869,73 +3105,71 @@ namespace OpenSim.Region.Framework.Scenes
2869 float y = (scale.Y / part.Scale.Y); 3105 float y = (scale.Y / part.Scale.Y);
2870 float z = (scale.Z / part.Scale.Z); 3106 float z = (scale.Z / part.Scale.Z);
2871 3107
2872 lock (m_parts) 3108 lockPartsForRead(true);
3109 if (x > 1.0f || y > 1.0f || z > 1.0f)
2873 { 3110 {
2874 if (x > 1.0f || y > 1.0f || z > 1.0f) 3111 foreach (SceneObjectPart obPart in m_parts.Values)
2875 { 3112 {
2876 foreach (SceneObjectPart obPart in m_parts.Values) 3113 if (obPart.UUID != m_rootPart.UUID)
2877 { 3114 {
2878 if (obPart.UUID != m_rootPart.UUID) 3115 Vector3 oldSize = new Vector3(obPart.Scale);
2879 { 3116 obPart.IgnoreUndoUpdate = true;
2880 obPart.IgnoreUndoUpdate = true;
2881 Vector3 oldSize = new Vector3(obPart.Scale);
2882 3117
2883 float f = 1.0f; 3118 float f = 1.0f;
2884 float a = 1.0f; 3119 float a = 1.0f;
2885 3120
2886 if (part.PhysActor != null && part.PhysActor.IsPhysical) 3121 if (part.PhysActor != null && part.PhysActor.IsPhysical)
3122 {
3123 if (oldSize.X*x > m_scene.m_maxPhys)
2887 { 3124 {
2888 if (oldSize.X*x > m_scene.m_maxPhys) 3125 f = m_scene.m_maxPhys / oldSize.X;
2889 { 3126 a = f / x;
2890 f = m_scene.m_maxPhys / oldSize.X; 3127 x *= a;
2891 a = f / x; 3128 y *= a;
2892 x *= a; 3129 z *= a;
2893 y *= a;
2894 z *= a;
2895 }
2896 if (oldSize.Y*y > m_scene.m_maxPhys)
2897 {
2898 f = m_scene.m_maxPhys / oldSize.Y;
2899 a = f / y;
2900 x *= a;
2901 y *= a;
2902 z *= a;
2903 }
2904 if (oldSize.Z*z > m_scene.m_maxPhys)
2905 {
2906 f = m_scene.m_maxPhys / oldSize.Z;
2907 a = f / z;
2908 x *= a;
2909 y *= a;
2910 z *= a;
2911 }
2912 } 3130 }
2913 else 3131 if (oldSize.Y*y > m_scene.m_maxPhys)
2914 { 3132 {
2915 if (oldSize.X*x > m_scene.m_maxNonphys) 3133 f = m_scene.m_maxPhys / oldSize.Y;
2916 { 3134 a = f / y;
2917 f = m_scene.m_maxNonphys / oldSize.X; 3135 x *= a;
2918 a = f / x; 3136 y *= a;
2919 x *= a; 3137 z *= a;
2920 y *= a; 3138 }
2921 z *= a; 3139 if (oldSize.Z*z > m_scene.m_maxPhys)
2922 } 3140 {
2923 if (oldSize.Y*y > m_scene.m_maxNonphys) 3141 f = m_scene.m_maxPhys / oldSize.Z;
2924 { 3142 a = f / z;
2925 f = m_scene.m_maxNonphys / oldSize.Y; 3143 x *= a;
2926 a = f / y; 3144 y *= a;
2927 x *= a; 3145 z *= a;
2928 y *= a; 3146 }
2929 z *= a; 3147 }
2930 } 3148 else
2931 if (oldSize.Z*z > m_scene.m_maxNonphys) 3149 {
2932 { 3150 if (oldSize.X*x > m_scene.m_maxNonphys)
2933 f = m_scene.m_maxNonphys / oldSize.Z; 3151 {
2934 a = f / z; 3152 f = m_scene.m_maxNonphys / oldSize.X;
2935 x *= a; 3153 a = f / x;
2936 y *= a; 3154 x *= a;
2937 z *= a; 3155 y *= a;
2938 } 3156 z *= a;
3157 }
3158 if (oldSize.Y*y > m_scene.m_maxNonphys)
3159 {
3160 f = m_scene.m_maxNonphys / oldSize.Y;
3161 a = f / y;
3162 x *= a;
3163 y *= a;
3164 z *= a;
3165 }
3166 if (oldSize.Z*z > m_scene.m_maxNonphys)
3167 {
3168 f = m_scene.m_maxNonphys / oldSize.Z;
3169 a = f / z;
3170 x *= a;
3171 y *= a;
3172 z *= a;
2939 } 3173 }
2940 obPart.IgnoreUndoUpdate = false; 3174 obPart.IgnoreUndoUpdate = false;
2941 obPart.StoreUndoState(); 3175 obPart.StoreUndoState();
@@ -2943,6 +3177,7 @@ namespace OpenSim.Region.Framework.Scenes
2943 } 3177 }
2944 } 3178 }
2945 } 3179 }
3180 lockPartsForRead(false);
2946 3181
2947 Vector3 prevScale = part.Scale; 3182 Vector3 prevScale = part.Scale;
2948 prevScale.X *= x; 3183 prevScale.X *= x;
@@ -2950,7 +3185,7 @@ namespace OpenSim.Region.Framework.Scenes
2950 prevScale.Z *= z; 3185 prevScale.Z *= z;
2951 part.Resize(prevScale); 3186 part.Resize(prevScale);
2952 3187
2953 lock (m_parts) 3188 lockPartsForRead(true);
2954 { 3189 {
2955 foreach (SceneObjectPart obPart in m_parts.Values) 3190 foreach (SceneObjectPart obPart in m_parts.Values)
2956 { 3191 {
@@ -2972,6 +3207,7 @@ namespace OpenSim.Region.Framework.Scenes
2972 obPart.StoreUndoState(); 3207 obPart.StoreUndoState();
2973 } 3208 }
2974 } 3209 }
3210 lockPartsForRead(false);
2975 3211
2976 if (part.PhysActor != null) 3212 if (part.PhysActor != null)
2977 { 3213 {
@@ -3074,7 +3310,7 @@ namespace OpenSim.Region.Framework.Scenes
3074 axDiff *= Quaternion.Inverse(partRotation); 3310 axDiff *= Quaternion.Inverse(partRotation);
3075 diff = axDiff; 3311 diff = axDiff;
3076 3312
3077 lock (m_parts) 3313 lockPartsForRead(true);
3078 { 3314 {
3079 foreach (SceneObjectPart obPart in m_parts.Values) 3315 foreach (SceneObjectPart obPart in m_parts.Values)
3080 { 3316 {
@@ -3084,6 +3320,7 @@ namespace OpenSim.Region.Framework.Scenes
3084 } 3320 }
3085 } 3321 }
3086 } 3322 }
3323 lockPartsForRead(false);
3087 3324
3088 AbsolutePosition = newPos; 3325 AbsolutePosition = newPos;
3089 3326
@@ -3217,25 +3454,25 @@ namespace OpenSim.Region.Framework.Scenes
3217 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); 3454 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
3218 } 3455 }
3219 3456
3220 lock (m_parts) 3457 lockPartsForRead(true);
3458
3459 foreach (SceneObjectPart prim in m_parts.Values)
3221 { 3460 {
3222 foreach (SceneObjectPart prim in m_parts.Values) 3461 if (prim.UUID != m_rootPart.UUID)
3223 { 3462 {
3224 if (prim.UUID != m_rootPart.UUID) 3463 prim.IgnoreUndoUpdate = true;
3225 { 3464 Vector3 axPos = prim.OffsetPosition;
3226 prim.IgnoreUndoUpdate = true; 3465 axPos *= oldParentRot;
3227 Vector3 axPos = prim.OffsetPosition; 3466 axPos *= Quaternion.Inverse(axRot);
3228 axPos *= oldParentRot; 3467 prim.OffsetPosition = axPos;
3229 axPos *= Quaternion.Inverse(axRot); 3468 Quaternion primsRot = prim.RotationOffset;
3230 prim.OffsetPosition = axPos; 3469 Quaternion newRot = primsRot * oldParentRot;
3231 Quaternion primsRot = prim.RotationOffset; 3470 newRot *= Quaternion.Inverse(axRot);
3232 Quaternion newRot = primsRot * oldParentRot; 3471 prim.RotationOffset = newRot;
3233 newRot *= Quaternion.Inverse(axRot); 3472 prim.ScheduleTerseUpdate();
3234 prim.RotationOffset = newRot;
3235 prim.ScheduleTerseUpdate();
3236 }
3237 } 3473 }
3238 } 3474 }
3475
3239 foreach (SceneObjectPart childpart in Children.Values) 3476 foreach (SceneObjectPart childpart in Children.Values)
3240 { 3477 {
3241 if (childpart != m_rootPart) 3478 if (childpart != m_rootPart)
@@ -3244,6 +3481,9 @@ namespace OpenSim.Region.Framework.Scenes
3244 childpart.StoreUndoState(); 3481 childpart.StoreUndoState();
3245 } 3482 }
3246 } 3483 }
3484
3485 lockPartsForRead(false);
3486
3247 m_rootPart.ScheduleTerseUpdate(); 3487 m_rootPart.ScheduleTerseUpdate();
3248 } 3488 }
3249 3489
@@ -3365,7 +3605,7 @@ namespace OpenSim.Region.Framework.Scenes
3365 if (atTargets.Count > 0) 3605 if (atTargets.Count > 0)
3366 { 3606 {
3367 uint[] localids = new uint[0]; 3607 uint[] localids = new uint[0];
3368 lock (m_parts) 3608 lockPartsForRead(true);
3369 { 3609 {
3370 localids = new uint[m_parts.Count]; 3610 localids = new uint[m_parts.Count];
3371 int cntr = 0; 3611 int cntr = 0;
@@ -3375,6 +3615,7 @@ namespace OpenSim.Region.Framework.Scenes
3375 cntr++; 3615 cntr++;
3376 } 3616 }
3377 } 3617 }
3618 lockPartsForRead(false);
3378 3619
3379 for (int ctr = 0; ctr < localids.Length; ctr++) 3620 for (int ctr = 0; ctr < localids.Length; ctr++)
3380 { 3621 {
@@ -3393,7 +3634,7 @@ namespace OpenSim.Region.Framework.Scenes
3393 { 3634 {
3394 //trigger not_at_target 3635 //trigger not_at_target
3395 uint[] localids = new uint[0]; 3636 uint[] localids = new uint[0];
3396 lock (m_parts) 3637 lockPartsForRead(true);
3397 { 3638 {
3398 localids = new uint[m_parts.Count]; 3639 localids = new uint[m_parts.Count];
3399 int cntr = 0; 3640 int cntr = 0;
@@ -3403,7 +3644,8 @@ namespace OpenSim.Region.Framework.Scenes
3403 cntr++; 3644 cntr++;
3404 } 3645 }
3405 } 3646 }
3406 3647 lockPartsForRead(false);
3648
3407 for (int ctr = 0; ctr < localids.Length; ctr++) 3649 for (int ctr = 0; ctr < localids.Length; ctr++)
3408 { 3650 {
3409 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]); 3651 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]);
@@ -3444,7 +3686,8 @@ namespace OpenSim.Region.Framework.Scenes
3444 if (atRotTargets.Count > 0) 3686 if (atRotTargets.Count > 0)
3445 { 3687 {
3446 uint[] localids = new uint[0]; 3688 uint[] localids = new uint[0];
3447 lock (m_parts) 3689 lockPartsForRead(true);
3690 try
3448 { 3691 {
3449 localids = new uint[m_parts.Count]; 3692 localids = new uint[m_parts.Count];
3450 int cntr = 0; 3693 int cntr = 0;
@@ -3454,6 +3697,10 @@ namespace OpenSim.Region.Framework.Scenes
3454 cntr++; 3697 cntr++;
3455 } 3698 }
3456 } 3699 }
3700 finally
3701 {
3702 lockPartsForRead(false);
3703 }
3457 3704
3458 for (int ctr = 0; ctr < localids.Length; ctr++) 3705 for (int ctr = 0; ctr < localids.Length; ctr++)
3459 { 3706 {
@@ -3472,7 +3719,8 @@ namespace OpenSim.Region.Framework.Scenes
3472 { 3719 {
3473 //trigger not_at_target 3720 //trigger not_at_target
3474 uint[] localids = new uint[0]; 3721 uint[] localids = new uint[0];
3475 lock (m_parts) 3722 lockPartsForRead(true);
3723 try
3476 { 3724 {
3477 localids = new uint[m_parts.Count]; 3725 localids = new uint[m_parts.Count];
3478 int cntr = 0; 3726 int cntr = 0;
@@ -3482,6 +3730,10 @@ namespace OpenSim.Region.Framework.Scenes
3482 cntr++; 3730 cntr++;
3483 } 3731 }
3484 } 3732 }
3733 finally
3734 {
3735 lockPartsForRead(false);
3736 }
3485 3737
3486 for (int ctr = 0; ctr < localids.Length; ctr++) 3738 for (int ctr = 0; ctr < localids.Length; ctr++)
3487 { 3739 {
@@ -3495,19 +3747,20 @@ namespace OpenSim.Region.Framework.Scenes
3495 public float GetMass() 3747 public float GetMass()
3496 { 3748 {
3497 float retmass = 0f; 3749 float retmass = 0f;
3498 lock (m_parts) 3750 lockPartsForRead(true);
3499 { 3751 {
3500 foreach (SceneObjectPart part in m_parts.Values) 3752 foreach (SceneObjectPart part in m_parts.Values)
3501 { 3753 {
3502 retmass += part.GetMass(); 3754 retmass += part.GetMass();
3503 } 3755 }
3504 } 3756 }
3757 lockPartsForRead(false);
3505 return retmass; 3758 return retmass;
3506 } 3759 }
3507 3760
3508 public void CheckSculptAndLoad() 3761 public void CheckSculptAndLoad()
3509 { 3762 {
3510 lock (m_parts) 3763 lockPartsForRead(true);
3511 { 3764 {
3512 if (!IsDeleted) 3765 if (!IsDeleted)
3513 { 3766 {
@@ -3532,6 +3785,7 @@ namespace OpenSim.Region.Framework.Scenes
3532 } 3785 }
3533 } 3786 }
3534 } 3787 }
3788 lockPartsForRead(false);
3535 } 3789 }
3536 3790
3537 protected void AssetReceived(string id, Object sender, AssetBase asset) 3791 protected void AssetReceived(string id, Object sender, AssetBase asset)
@@ -3552,7 +3806,7 @@ namespace OpenSim.Region.Framework.Scenes
3552 /// <param name="client"></param> 3806 /// <param name="client"></param>
3553 public void SetGroup(UUID GroupID, IClientAPI client) 3807 public void SetGroup(UUID GroupID, IClientAPI client)
3554 { 3808 {
3555 lock (m_parts) 3809 lockPartsForRead(true);
3556 { 3810 {
3557 foreach (SceneObjectPart part in m_parts.Values) 3811 foreach (SceneObjectPart part in m_parts.Values)
3558 { 3812 {
@@ -3562,6 +3816,7 @@ namespace OpenSim.Region.Framework.Scenes
3562 3816
3563 HasGroupChanged = true; 3817 HasGroupChanged = true;
3564 } 3818 }
3819 lockPartsForRead(false);
3565 3820
3566 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled 3821 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled
3567 // for the same object with very different properties. The caller must schedule the update. 3822 // for the same object with very different properties. The caller must schedule the update.
@@ -3583,11 +3838,12 @@ namespace OpenSim.Region.Framework.Scenes
3583 3838
3584 public void SetAttachmentPoint(byte point) 3839 public void SetAttachmentPoint(byte point)
3585 { 3840 {
3586 lock (m_parts) 3841 lockPartsForRead(true);
3587 { 3842 {
3588 foreach (SceneObjectPart part in m_parts.Values) 3843 foreach (SceneObjectPart part in m_parts.Values)
3589 part.SetAttachmentPoint(point); 3844 part.SetAttachmentPoint(point);
3590 } 3845 }
3846 lockPartsForRead(false);
3591 } 3847 }
3592 3848
3593 #region ISceneObject 3849 #region ISceneObject
@@ -3621,6 +3877,14 @@ namespace OpenSim.Region.Framework.Scenes
3621 SetFromItemID(uuid); 3877 SetFromItemID(uuid);
3622 } 3878 }
3623 3879
3880 public void ResetOwnerChangeFlag()
3881 {
3882 ForEachPart(delegate(SceneObjectPart part)
3883 {
3884 part.ResetOwnerChangeFlag();
3885 });
3886 }
3887
3624 #endregion 3888 #endregion
3625 } 3889 }
3626} 3890}