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.cs758
1 files changed, 537 insertions, 221 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index e23f39f..3e92954 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 private System.Threading.ReaderWriterLockSlim m_partsLock = new System.Threading.ReaderWriterLockSlim();
114 private List<ScenePresence> m_linkedAvatars = new List<ScenePresence>();
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 {
@@ -962,6 +1116,47 @@ namespace OpenSim.Region.Framework.Scenes
962 } 1116 }
963 1117
964 /// <summary> 1118 /// <summary>
1119 /// Add the avatar to this linkset (avatar is sat).
1120 /// </summary>
1121 /// <param name="agentID"></param>
1122 public void AddAvatar(UUID agentID)
1123 {
1124 ScenePresence presence;
1125 if (m_scene.TryGetScenePresence(agentID, out presence))
1126 {
1127 if (!m_linkedAvatars.Contains(presence))
1128 {
1129 m_linkedAvatars.Add(presence);
1130 }
1131 }
1132 }
1133
1134 /// <summary>
1135 /// Delete the avatar from this linkset (avatar is unsat).
1136 /// </summary>
1137 /// <param name="agentID"></param>
1138 public void DeleteAvatar(UUID agentID)
1139 {
1140 ScenePresence presence;
1141 if (m_scene.TryGetScenePresence(agentID, out presence))
1142 {
1143 if (m_linkedAvatars.Contains(presence))
1144 {
1145 m_linkedAvatars.Remove(presence);
1146 }
1147 }
1148 }
1149
1150 /// <summary>
1151 /// Returns the list of linked presences (avatars sat on this group)
1152 /// </summary>
1153 /// <param name="agentID"></param>
1154 public List<ScenePresence> GetLinkedAvatars()
1155 {
1156 return m_linkedAvatars;
1157 }
1158
1159 /// <summary>
965 /// Attach this scene object to the given avatar. 1160 /// Attach this scene object to the given avatar.
966 /// </summary> 1161 /// </summary>
967 /// <param name="agentID"></param> 1162 /// <param name="agentID"></param>
@@ -1112,13 +1307,16 @@ namespace OpenSim.Region.Framework.Scenes
1112 1307
1113 public override void UpdateMovement() 1308 public override void UpdateMovement()
1114 { 1309 {
1115 lock (m_parts) 1310 lockPartsForRead(true);
1116 { 1311 {
1117 foreach (SceneObjectPart part in m_parts.Values) 1312 foreach (SceneObjectPart part in m_parts.Values)
1118 { 1313 {
1314
1119 part.UpdateMovement(); 1315 part.UpdateMovement();
1316
1120 } 1317 }
1121 } 1318 }
1319 lockPartsForRead(false);
1122 } 1320 }
1123 1321
1124 public ushort GetTimeDilation() 1322 public ushort GetTimeDilation()
@@ -1162,7 +1360,7 @@ namespace OpenSim.Region.Framework.Scenes
1162 /// <param name="part"></param> 1360 /// <param name="part"></param>
1163 public void AddPart(SceneObjectPart part) 1361 public void AddPart(SceneObjectPart part)
1164 { 1362 {
1165 lock (m_parts) 1363 lockPartsForWrite(true);
1166 { 1364 {
1167 part.SetParent(this); 1365 part.SetParent(this);
1168 m_parts.Add(part.UUID, part); 1366 m_parts.Add(part.UUID, part);
@@ -1172,6 +1370,7 @@ namespace OpenSim.Region.Framework.Scenes
1172 if (part.LinkNum == 2 && RootPart != null) 1370 if (part.LinkNum == 2 && RootPart != null)
1173 RootPart.LinkNum = 1; 1371 RootPart.LinkNum = 1;
1174 } 1372 }
1373 lockPartsForWrite(false);
1175 } 1374 }
1176 1375
1177 /// <summary> 1376 /// <summary>
@@ -1179,28 +1378,33 @@ namespace OpenSim.Region.Framework.Scenes
1179 /// </summary> 1378 /// </summary>
1180 private void UpdateParentIDs() 1379 private void UpdateParentIDs()
1181 { 1380 {
1182 lock (m_parts) 1381 lockPartsForRead(true);
1183 { 1382 {
1184 foreach (SceneObjectPart part in m_parts.Values) 1383 foreach (SceneObjectPart part in m_parts.Values)
1185 { 1384 {
1385
1186 if (part.UUID != m_rootPart.UUID) 1386 if (part.UUID != m_rootPart.UUID)
1187 { 1387 {
1188 part.ParentID = m_rootPart.LocalId; 1388 part.ParentID = m_rootPart.LocalId;
1189 } 1389 }
1390
1190 } 1391 }
1191 } 1392 }
1393 lockPartsForRead(false);
1192 } 1394 }
1193 1395
1194 public void RegenerateFullIDs() 1396 public void RegenerateFullIDs()
1195 { 1397 {
1196 lock (m_parts) 1398 lockPartsForRead(true);
1197 { 1399 {
1198 foreach (SceneObjectPart part in m_parts.Values) 1400 foreach (SceneObjectPart part in m_parts.Values)
1199 { 1401 {
1402
1200 part.UUID = UUID.Random(); 1403 part.UUID = UUID.Random();
1201 1404
1202 } 1405 }
1203 } 1406 }
1407 lockPartsForRead(false);
1204 } 1408 }
1205 1409
1206 // helper provided for parts. 1410 // helper provided for parts.
@@ -1281,27 +1485,32 @@ namespace OpenSim.Region.Framework.Scenes
1281 1485
1282 DetachFromBackup(); 1486 DetachFromBackup();
1283 1487
1284 lock (m_parts) 1488 lockPartsForRead(true);
1489 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1490 lockPartsForRead(false);
1491
1492 foreach (SceneObjectPart part in values)
1285 { 1493 {
1286 foreach (SceneObjectPart part in m_parts.Values)
1287 {
1288// part.Inventory.RemoveScriptInstances(); 1494// part.Inventory.RemoveScriptInstances();
1289 Scene.ForEachScenePresence(delegate(ScenePresence avatar) 1495
1496 Scene.ForEachScenePresence(delegate (ScenePresence sp)
1497 {
1498 if (sp.ParentID == LocalId)
1290 { 1499 {
1291 if (avatar.ParentID == LocalId) 1500 sp.StandUp();
1292 { 1501 }
1293 avatar.StandUp();
1294 }
1295 1502
1296 if (!silent) 1503 if (!silent)
1297 { 1504 {
1298 part.UpdateFlag = 0; 1505 part.UpdateFlag = 0;
1299 if (part == m_rootPart) 1506 if (part == m_rootPart)
1300 avatar.ControllingClient.SendKillObject(m_regionHandle, part.LocalId); 1507 sp.ControllingClient.SendKillObject(m_regionHandle, part.LocalId);
1301 } 1508 }
1302 }); 1509 });
1303 } 1510
1304 } 1511 }
1512
1513
1305 } 1514 }
1306 1515
1307 public void AddScriptLPS(int count) 1516 public void AddScriptLPS(int count)
@@ -1326,17 +1535,20 @@ namespace OpenSim.Region.Framework.Scenes
1326 1535
1327 scriptEvents aggregateScriptEvents=0; 1536 scriptEvents aggregateScriptEvents=0;
1328 1537
1329 lock (m_parts) 1538 lockPartsForRead(true);
1330 { 1539 {
1331 foreach (SceneObjectPart part in m_parts.Values) 1540 foreach (SceneObjectPart part in m_parts.Values)
1332 { 1541 {
1542
1333 if (part == null) 1543 if (part == null)
1334 continue; 1544 continue;
1335 if (part != RootPart) 1545 if (part != RootPart)
1336 part.ObjectFlags = objectflagupdate; 1546 part.ObjectFlags = objectflagupdate;
1337 aggregateScriptEvents |= part.AggregateScriptEvents; 1547 aggregateScriptEvents |= part.AggregateScriptEvents;
1548
1338 } 1549 }
1339 } 1550 }
1551 lockPartsForRead(false);
1340 1552
1341 m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0); 1553 m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0);
1342 m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0); 1554 m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0);
@@ -1378,42 +1590,52 @@ namespace OpenSim.Region.Framework.Scenes
1378 /// <param name="m_physicalPrim"></param> 1590 /// <param name="m_physicalPrim"></param>
1379 public void ApplyPhysics(bool m_physicalPrim) 1591 public void ApplyPhysics(bool m_physicalPrim)
1380 { 1592 {
1381 lock (m_parts) 1593 lockPartsForRead(true);
1594
1595 if (m_parts.Count > 1)
1382 { 1596 {
1383 if (m_parts.Count > 1) 1597 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1598 lockPartsForRead(false);
1599 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1600 foreach (SceneObjectPart part in values)
1384 { 1601 {
1385 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim); 1602
1386 foreach (SceneObjectPart part in m_parts.Values) 1603 if (part.LocalId != m_rootPart.LocalId)
1387 { 1604 {
1388 if (part.LocalId != m_rootPart.LocalId) 1605 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim);
1389 {
1390 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim);
1391 }
1392 } 1606 }
1393 1607
1394 // Hack to get the physics scene geometries in the right spot
1395 ResetChildPrimPhysicsPositions();
1396 }
1397 else
1398 {
1399 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1400 } 1608 }
1609 // Hack to get the physics scene geometries in the right spot
1610 ResetChildPrimPhysicsPositions();
1611 }
1612 else
1613 {
1614 lockPartsForRead(false);
1615 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1401 } 1616 }
1402 } 1617 }
1403 1618
1404 public void SetOwnerId(UUID userId) 1619 public void SetOwnerId(UUID userId)
1405 { 1620 {
1406 ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); 1621 ForEachPart(delegate(SceneObjectPart part)
1622 {
1623
1624 part.OwnerID = userId;
1625
1626 });
1407 } 1627 }
1408 1628
1409 public void ForEachPart(Action<SceneObjectPart> whatToDo) 1629 public void ForEachPart(Action<SceneObjectPart> whatToDo)
1410 { 1630 {
1411 lock (m_parts) 1631 lockPartsForRead(true);
1632 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1633 lockPartsForRead(false);
1634 foreach (SceneObjectPart part in values)
1412 { 1635 {
1413 foreach (SceneObjectPart part in m_parts.Values) 1636
1414 { 1637 whatToDo(part);
1415 whatToDo(part); 1638
1416 }
1417 } 1639 }
1418 } 1640 }
1419 1641
@@ -1511,15 +1733,17 @@ namespace OpenSim.Region.Framework.Scenes
1511 RootPart.SendFullUpdate( 1733 RootPart.SendFullUpdate(
1512 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID)); 1734 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID));
1513 1735
1514 lock (m_parts) 1736 lockPartsForRead(true);
1515 { 1737 {
1516 foreach (SceneObjectPart part in m_parts.Values) 1738 foreach (SceneObjectPart part in m_parts.Values)
1517 { 1739 {
1740
1518 if (part != RootPart) 1741 if (part != RootPart)
1519 part.SendFullUpdate( 1742 part.SendFullUpdate(
1520 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID)); 1743 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID));
1521 } 1744 }
1522 } 1745 }
1746 lockPartsForRead(false);
1523 } 1747 }
1524 1748
1525 #region Copying 1749 #region Copying
@@ -1588,10 +1812,11 @@ namespace OpenSim.Region.Framework.Scenes
1588 1812
1589 List<SceneObjectPart> partList; 1813 List<SceneObjectPart> partList;
1590 1814
1591 lock (m_parts) 1815 lockPartsForRead(true);
1592 { 1816
1593 partList = new List<SceneObjectPart>(m_parts.Values); 1817 partList = new List<SceneObjectPart>(m_parts.Values);
1594 } 1818
1819 lockPartsForRead(false);
1595 1820
1596 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) 1821 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1597 { 1822 {
@@ -1814,13 +2039,40 @@ namespace OpenSim.Region.Framework.Scenes
1814 } 2039 }
1815 } 2040 }
1816 2041
2042 public void rotLookAt(Quaternion target, float strength, float damping)
2043 {
2044 SceneObjectPart rootpart = m_rootPart;
2045 if (rootpart != null)
2046 {
2047 if (IsAttachment)
2048 {
2049 /*
2050 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
2051 if (avatar != null)
2052 {
2053 Rotate the Av?
2054 } */
2055 }
2056 else
2057 {
2058 if (rootpart.PhysActor != null)
2059 { // APID must be implemented in your physics system for this to function.
2060 rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W);
2061 rootpart.PhysActor.APIDStrength = strength;
2062 rootpart.PhysActor.APIDDamping = damping;
2063 rootpart.PhysActor.APIDActive = true;
2064 }
2065 }
2066 }
2067 }
2068
1817 public void stopLookAt() 2069 public void stopLookAt()
1818 { 2070 {
1819 SceneObjectPart rootpart = m_rootPart; 2071 SceneObjectPart rootpart = m_rootPart;
1820 if (rootpart != null) 2072 if (rootpart != null)
1821 { 2073 {
1822 if (rootpart.PhysActor != null) 2074 if (rootpart.PhysActor != null)
1823 { 2075 { // APID must be implemented in your physics system for this to function.
1824 rootpart.PhysActor.APIDActive = false; 2076 rootpart.PhysActor.APIDActive = false;
1825 } 2077 }
1826 } 2078 }
@@ -1888,10 +2140,11 @@ namespace OpenSim.Region.Framework.Scenes
1888 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 2140 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
1889 newPart.SetParent(this); 2141 newPart.SetParent(this);
1890 2142
1891 lock (m_parts) 2143 lockPartsForWrite(true);
1892 { 2144 {
1893 m_parts.Add(newPart.UUID, newPart); 2145 m_parts.Add(newPart.UUID, newPart);
1894 } 2146 }
2147 lockPartsForWrite(false);
1895 2148
1896 SetPartAsNonRoot(newPart); 2149 SetPartAsNonRoot(newPart);
1897 2150
@@ -1954,7 +2207,7 @@ namespace OpenSim.Region.Framework.Scenes
1954 //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0) 2207 //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
1955 // return; 2208 // return;
1956 2209
1957 lock (m_parts) 2210 lockPartsForRead(true);
1958 { 2211 {
1959 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0); 2212 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0);
1960 2213
@@ -1974,9 +2227,12 @@ namespace OpenSim.Region.Framework.Scenes
1974 { 2227 {
1975 if (!IsSelected) 2228 if (!IsSelected)
1976 part.UpdateLookAt(); 2229 part.UpdateLookAt();
2230
1977 part.SendScheduledUpdates(); 2231 part.SendScheduledUpdates();
2232
1978 } 2233 }
1979 } 2234 }
2235 lockPartsForRead(false);
1980 } 2236 }
1981 2237
1982 public void ScheduleFullUpdateToAvatar(ScenePresence presence) 2238 public void ScheduleFullUpdateToAvatar(ScenePresence presence)
@@ -1985,27 +2241,29 @@ namespace OpenSim.Region.Framework.Scenes
1985 2241
1986 RootPart.AddFullUpdateToAvatar(presence); 2242 RootPart.AddFullUpdateToAvatar(presence);
1987 2243
1988 lock (m_parts) 2244 lockPartsForRead(true);
1989 { 2245 {
1990 foreach (SceneObjectPart part in m_parts.Values) 2246 foreach (SceneObjectPart part in m_parts.Values)
1991 { 2247 {
2248
1992 if (part != RootPart) 2249 if (part != RootPart)
1993 part.AddFullUpdateToAvatar(presence); 2250 part.AddFullUpdateToAvatar(presence);
2251
1994 } 2252 }
1995 } 2253 }
2254 lockPartsForRead(false);
1996 } 2255 }
1997 2256
1998 public void ScheduleTerseUpdateToAvatar(ScenePresence presence) 2257 public void ScheduleTerseUpdateToAvatar(ScenePresence presence)
1999 { 2258 {
2000// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1} just to avatar {2}", Name, UUID, presence.Name); 2259 lockPartsForRead(true);
2001 2260
2002 lock (m_parts) 2261 foreach (SceneObjectPart part in m_parts.Values)
2003 { 2262 {
2004 foreach (SceneObjectPart part in m_parts.Values) 2263 part.AddTerseUpdateToAvatar(presence);
2005 {
2006 part.AddTerseUpdateToAvatar(presence);
2007 }
2008 } 2264 }
2265
2266 lockPartsForRead(false);
2009 } 2267 }
2010 2268
2011 /// <summary> 2269 /// <summary>
@@ -2013,20 +2271,23 @@ namespace OpenSim.Region.Framework.Scenes
2013 /// </summary> 2271 /// </summary>
2014 public void ScheduleGroupForFullUpdate() 2272 public void ScheduleGroupForFullUpdate()
2015 { 2273 {
2016 if (IsAttachment) 2274 //if (IsAttachment)
2017 m_log.DebugFormat("[SOG]: Scheduling full update for {0} {1}", Name, LocalId); 2275 // m_log.DebugFormat("[SOG]: Scheduling full update for {0} {1}", Name, LocalId);
2018 2276
2019 checkAtTargets(); 2277 checkAtTargets();
2020 RootPart.ScheduleFullUpdate(); 2278 RootPart.ScheduleFullUpdate();
2021 2279
2022 lock (m_parts) 2280 lockPartsForRead(true);
2023 { 2281 {
2024 foreach (SceneObjectPart part in m_parts.Values) 2282 foreach (SceneObjectPart part in m_parts.Values)
2025 { 2283 {
2284
2026 if (part != RootPart) 2285 if (part != RootPart)
2027 part.ScheduleFullUpdate(); 2286 part.ScheduleFullUpdate();
2287
2028 } 2288 }
2029 } 2289 }
2290 lockPartsForRead(false);
2030 } 2291 }
2031 2292
2032 /// <summary> 2293 /// <summary>
@@ -2034,37 +2295,38 @@ namespace OpenSim.Region.Framework.Scenes
2034 /// </summary> 2295 /// </summary>
2035 public void ScheduleGroupForTerseUpdate() 2296 public void ScheduleGroupForTerseUpdate()
2036 { 2297 {
2037// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1}", Name, UUID); 2298 lockPartsForRead(true);
2038 2299 foreach (SceneObjectPart part in m_parts.Values)
2039 lock (m_parts)
2040 { 2300 {
2041 foreach (SceneObjectPart part in m_parts.Values) 2301 part.ScheduleTerseUpdate();
2042 {
2043 part.ScheduleTerseUpdate();
2044 }
2045 } 2302 }
2303
2304 lockPartsForRead(false);
2046 } 2305 }
2047 2306
2048 /// <summary> 2307 /// <summary>
2049 /// Immediately send a full update for this scene object. 2308 /// Immediately send a full update for this scene object.
2050 /// </summary> 2309 /// </summary>
2051 public void SendGroupFullUpdate() 2310 public void SendGroupFullUpdate()
2052 { 2311 {
2053 if (IsDeleted) 2312 if (IsDeleted)
2054 return; 2313 return;
2055 2314
2056// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); 2315// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID);
2057 2316
2058 RootPart.SendFullUpdateToAllClients(); 2317 RootPart.SendFullUpdateToAllClients();
2059 2318
2060 lock (m_parts) 2319 lockPartsForRead(true);
2061 { 2320 {
2062 foreach (SceneObjectPart part in m_parts.Values) 2321 foreach (SceneObjectPart part in m_parts.Values)
2063 { 2322 {
2323
2064 if (part != RootPart) 2324 if (part != RootPart)
2065 part.SendFullUpdateToAllClients(); 2325 part.SendFullUpdateToAllClients();
2326
2066 } 2327 }
2067 } 2328 }
2329 lockPartsForRead(false);
2068 } 2330 }
2069 2331
2070 /// <summary> 2332 /// <summary>
@@ -2096,14 +2358,15 @@ namespace OpenSim.Region.Framework.Scenes
2096 { 2358 {
2097 if (IsDeleted) 2359 if (IsDeleted)
2098 return; 2360 return;
2099 2361
2100 lock (m_parts) 2362 lockPartsForRead(true);
2101 { 2363 {
2102 foreach (SceneObjectPart part in m_parts.Values) 2364 foreach (SceneObjectPart part in m_parts.Values)
2103 { 2365 {
2104 part.SendTerseUpdateToAllClients(); 2366 part.SendTerseUpdateToAllClients();
2105 } 2367 }
2106 } 2368 }
2369 lockPartsForRead(false);
2107 } 2370 }
2108 2371
2109 #endregion 2372 #endregion
@@ -2117,16 +2380,18 @@ namespace OpenSim.Region.Framework.Scenes
2117 /// <returns>null if no child part with that linknum or child part</returns> 2380 /// <returns>null if no child part with that linknum or child part</returns>
2118 public SceneObjectPart GetLinkNumPart(int linknum) 2381 public SceneObjectPart GetLinkNumPart(int linknum)
2119 { 2382 {
2120 lock (m_parts) 2383 lockPartsForRead(true);
2121 { 2384 {
2122 foreach (SceneObjectPart part in m_parts.Values) 2385 foreach (SceneObjectPart part in m_parts.Values)
2123 { 2386 {
2124 if (part.LinkNum == linknum) 2387 if (part.LinkNum == linknum)
2125 { 2388 {
2389 lockPartsForRead(false);
2126 return part; 2390 return part;
2127 } 2391 }
2128 } 2392 }
2129 } 2393 }
2394 lockPartsForRead(false);
2130 2395
2131 return null; 2396 return null;
2132 } 2397 }
@@ -2154,17 +2419,19 @@ namespace OpenSim.Region.Framework.Scenes
2154 public SceneObjectPart GetChildPart(uint localID) 2419 public SceneObjectPart GetChildPart(uint localID)
2155 { 2420 {
2156 //m_log.DebugFormat("Entered looking for {0}", localID); 2421 //m_log.DebugFormat("Entered looking for {0}", localID);
2157 lock (m_parts) 2422 lockPartsForRead(true);
2158 { 2423 {
2159 foreach (SceneObjectPart part in m_parts.Values) 2424 foreach (SceneObjectPart part in m_parts.Values)
2160 { 2425 {
2161 //m_log.DebugFormat("Found {0}", part.LocalId); 2426 //m_log.DebugFormat("Found {0}", part.LocalId);
2162 if (part.LocalId == localID) 2427 if (part.LocalId == localID)
2163 { 2428 {
2429 lockPartsForRead(false);
2164 return part; 2430 return part;
2165 } 2431 }
2166 } 2432 }
2167 } 2433 }
2434 lockPartsForRead(false);
2168 2435
2169 return null; 2436 return null;
2170 } 2437 }
@@ -2194,17 +2461,19 @@ namespace OpenSim.Region.Framework.Scenes
2194 public bool HasChildPrim(uint localID) 2461 public bool HasChildPrim(uint localID)
2195 { 2462 {
2196 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID); 2463 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID);
2197 lock (m_parts) 2464 lockPartsForRead(true);
2198 { 2465 {
2199 foreach (SceneObjectPart part in m_parts.Values) 2466 foreach (SceneObjectPart part in m_parts.Values)
2200 { 2467 {
2201 //m_log.DebugFormat("Found {0}", part.LocalId); 2468 //m_log.DebugFormat("Found {0}", part.LocalId);
2202 if (part.LocalId == localID) 2469 if (part.LocalId == localID)
2203 { 2470 {
2471 lockPartsForRead(false);
2204 return true; 2472 return true;
2205 } 2473 }
2206 } 2474 }
2207 } 2475 }
2476 lockPartsForRead(false);
2208 2477
2209 return false; 2478 return false;
2210 } 2479 }
@@ -2254,53 +2523,57 @@ namespace OpenSim.Region.Framework.Scenes
2254 if (m_rootPart.LinkNum == 0) 2523 if (m_rootPart.LinkNum == 0)
2255 m_rootPart.LinkNum = 1; 2524 m_rootPart.LinkNum = 1;
2256 2525
2257 lock (m_parts) 2526 lockPartsForWrite(true);
2258 { 2527
2259 m_parts.Add(linkPart.UUID, linkPart); 2528 m_parts.Add(linkPart.UUID, linkPart);
2529
2530 lockPartsForWrite(false);
2260 2531
2261 // Insert in terms of link numbers, the new links 2532 // Insert in terms of link numbers, the new links
2262 // before the current ones (with the exception of 2533 // before the current ones (with the exception of
2263 // the root prim. Shuffle the old ones up 2534 // the root prim. Shuffle the old ones up
2264 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts) 2535 lockPartsForRead(true);
2536 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts)
2537 {
2538 if (kvp.Value.LinkNum != 1)
2265 { 2539 {
2266 if (kvp.Value.LinkNum != 1) 2540 // Don't update root prim link number
2267 { 2541 kvp.Value.LinkNum += objectGroup.PrimCount;
2268 // Don't update root prim link number
2269 kvp.Value.LinkNum += objectGroup.PrimCount;
2270 }
2271 } 2542 }
2543 }
2544 lockPartsForRead(false);
2272 2545
2273 linkPart.LinkNum = 2; 2546 linkPart.LinkNum = 2;
2274 2547
2275 linkPart.SetParent(this); 2548 linkPart.SetParent(this);
2276 linkPart.CreateSelected = true; 2549 linkPart.CreateSelected = true;
2277 2550
2278 //if (linkPart.PhysActor != null) 2551 //if (linkPart.PhysActor != null)
2279 //{ 2552 //{
2280 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); 2553 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor);
2281 2554
2282 //linkPart.PhysActor = null; 2555 //linkPart.PhysActor = null;
2283 //} 2556 //}
2284 2557
2285 //TODO: rest of parts 2558 //TODO: rest of parts
2286 int linkNum = 3; 2559 int linkNum = 3;
2287 foreach (SceneObjectPart part in objectGroup.Children.Values) 2560 foreach (SceneObjectPart part in objectGroup.Children.Values)
2561 {
2562 if (part.UUID != objectGroup.m_rootPart.UUID)
2288 { 2563 {
2289 if (part.UUID != objectGroup.m_rootPart.UUID) 2564 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2290 {
2291 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2292 }
2293 part.ClearUndoState();
2294 } 2565 }
2566 part.ClearUndoState();
2295 } 2567 }
2296 2568
2297 m_scene.UnlinkSceneObject(objectGroup.UUID, true); 2569 m_scene.UnlinkSceneObject(objectGroup.UUID, true);
2298 objectGroup.m_isDeleted = true; 2570 objectGroup.m_isDeleted = true;
2571
2572 objectGroup.lockPartsForWrite(true);
2299 2573
2300 lock (objectGroup.m_parts) 2574 objectGroup.m_parts.Clear();
2301 { 2575
2302 objectGroup.m_parts.Clear(); 2576 objectGroup.lockPartsForWrite(false);
2303 }
2304 2577
2305 // Can't do this yet since backup still makes use of the root part without any synchronization 2578 // Can't do this yet since backup still makes use of the root part without any synchronization
2306// objectGroup.m_rootPart = null; 2579// objectGroup.m_rootPart = null;
@@ -2370,11 +2643,12 @@ namespace OpenSim.Region.Framework.Scenes
2370 Quaternion worldRot = linkPart.GetWorldRotation(); 2643 Quaternion worldRot = linkPart.GetWorldRotation();
2371 2644
2372 // Remove the part from this object 2645 // Remove the part from this object
2373 lock (m_parts) 2646 lockPartsForWrite(true);
2374 { 2647 {
2375 m_parts.Remove(linkPart.UUID); 2648 m_parts.Remove(linkPart.UUID);
2376 } 2649 }
2377 2650 lockPartsForWrite(false);
2651 lockPartsForRead(true);
2378 if (m_parts.Count == 1 && RootPart != null) //Single prim is left 2652 if (m_parts.Count == 1 && RootPart != null) //Single prim is left
2379 RootPart.LinkNum = 0; 2653 RootPart.LinkNum = 0;
2380 else 2654 else
@@ -2385,6 +2659,7 @@ namespace OpenSim.Region.Framework.Scenes
2385 p.LinkNum--; 2659 p.LinkNum--;
2386 } 2660 }
2387 } 2661 }
2662 lockPartsForRead(false);
2388 2663
2389 linkPart.ParentID = 0; 2664 linkPart.ParentID = 0;
2390 linkPart.LinkNum = 0; 2665 linkPart.LinkNum = 0;
@@ -2706,9 +2981,12 @@ namespace OpenSim.Region.Framework.Scenes
2706 2981
2707 if (selectionPart != null) 2982 if (selectionPart != null)
2708 { 2983 {
2709 lock (m_parts) 2984 lockPartsForRead(true);
2985 List<SceneObjectPart> parts = new List<SceneObjectPart>(m_parts.Values);
2986 lockPartsForRead(false);
2987 foreach (SceneObjectPart part in parts)
2710 { 2988 {
2711 foreach (SceneObjectPart part in m_parts.Values) 2989 if (part.Scale.X > 10.0 || part.Scale.Y > 10.0 || part.Scale.Z > 10.0)
2712 { 2990 {
2713 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax || 2991 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax ||
2714 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax || 2992 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax ||
@@ -2718,12 +2996,13 @@ namespace OpenSim.Region.Framework.Scenes
2718 break; 2996 break;
2719 } 2997 }
2720 } 2998 }
2999 }
2721 3000
2722 foreach (SceneObjectPart part in m_parts.Values) 3001 foreach (SceneObjectPart part in parts)
2723 { 3002 {
2724 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect); 3003 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
2725 }
2726 } 3004 }
3005
2727 } 3006 }
2728 } 3007 }
2729 3008
@@ -2736,6 +3015,17 @@ namespace OpenSim.Region.Framework.Scenes
2736 } 3015 }
2737 } 3016 }
2738 3017
3018
3019
3020 /// <summary>
3021 /// Gets the number of parts
3022 /// </summary>
3023 /// <returns></returns>
3024 public int GetPartCount()
3025 {
3026 return Children.Count;
3027 }
3028
2739 /// <summary> 3029 /// <summary>
2740 /// Get the parts of this scene object 3030 /// Get the parts of this scene object
2741 /// </summary> 3031 /// </summary>
@@ -2809,11 +3099,9 @@ namespace OpenSim.Region.Framework.Scenes
2809 scale.Y = m_scene.m_maxNonphys; 3099 scale.Y = m_scene.m_maxNonphys;
2810 if (scale.Z > m_scene.m_maxNonphys) 3100 if (scale.Z > m_scene.m_maxNonphys)
2811 scale.Z = m_scene.m_maxNonphys; 3101 scale.Z = m_scene.m_maxNonphys;
2812
2813 SceneObjectPart part = GetChildPart(localID); 3102 SceneObjectPart part = GetChildPart(localID);
2814 if (part != null) 3103 if (part != null)
2815 { 3104 {
2816 part.Resize(scale);
2817 if (part.PhysActor != null) 3105 if (part.PhysActor != null)
2818 { 3106 {
2819 if (part.PhysActor.IsPhysical) 3107 if (part.PhysActor.IsPhysical)
@@ -2828,7 +3116,7 @@ namespace OpenSim.Region.Framework.Scenes
2828 part.PhysActor.Size = scale; 3116 part.PhysActor.Size = scale;
2829 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); 3117 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor);
2830 } 3118 }
2831 //if (part.UUID != m_rootPart.UUID) 3119 part.Resize(scale);
2832 3120
2833 HasGroupChanged = true; 3121 HasGroupChanged = true;
2834 ScheduleGroupForFullUpdate(); 3122 ScheduleGroupForFullUpdate();
@@ -2870,73 +3158,71 @@ namespace OpenSim.Region.Framework.Scenes
2870 float y = (scale.Y / part.Scale.Y); 3158 float y = (scale.Y / part.Scale.Y);
2871 float z = (scale.Z / part.Scale.Z); 3159 float z = (scale.Z / part.Scale.Z);
2872 3160
2873 lock (m_parts) 3161 lockPartsForRead(true);
3162 if (x > 1.0f || y > 1.0f || z > 1.0f)
2874 { 3163 {
2875 if (x > 1.0f || y > 1.0f || z > 1.0f) 3164 foreach (SceneObjectPart obPart in m_parts.Values)
2876 { 3165 {
2877 foreach (SceneObjectPart obPart in m_parts.Values) 3166 if (obPart.UUID != m_rootPart.UUID)
2878 { 3167 {
2879 if (obPart.UUID != m_rootPart.UUID) 3168 Vector3 oldSize = new Vector3(obPart.Scale);
2880 { 3169 obPart.IgnoreUndoUpdate = true;
2881 obPart.IgnoreUndoUpdate = true;
2882 Vector3 oldSize = new Vector3(obPart.Scale);
2883 3170
2884 float f = 1.0f; 3171 float f = 1.0f;
2885 float a = 1.0f; 3172 float a = 1.0f;
2886 3173
2887 if (part.PhysActor != null && part.PhysActor.IsPhysical) 3174 if (part.PhysActor != null && part.PhysActor.IsPhysical)
3175 {
3176 if (oldSize.X*x > m_scene.m_maxPhys)
2888 { 3177 {
2889 if (oldSize.X*x > m_scene.m_maxPhys) 3178 f = m_scene.m_maxPhys / oldSize.X;
2890 { 3179 a = f / x;
2891 f = m_scene.m_maxPhys / oldSize.X; 3180 x *= a;
2892 a = f / x; 3181 y *= a;
2893 x *= a; 3182 z *= a;
2894 y *= a;
2895 z *= a;
2896 }
2897 if (oldSize.Y*y > m_scene.m_maxPhys)
2898 {
2899 f = m_scene.m_maxPhys / oldSize.Y;
2900 a = f / y;
2901 x *= a;
2902 y *= a;
2903 z *= a;
2904 }
2905 if (oldSize.Z*z > m_scene.m_maxPhys)
2906 {
2907 f = m_scene.m_maxPhys / oldSize.Z;
2908 a = f / z;
2909 x *= a;
2910 y *= a;
2911 z *= a;
2912 }
2913 } 3183 }
2914 else 3184 if (oldSize.Y*y > m_scene.m_maxPhys)
3185 {
3186 f = m_scene.m_maxPhys / oldSize.Y;
3187 a = f / y;
3188 x *= a;
3189 y *= a;
3190 z *= a;
3191 }
3192 if (oldSize.Z*z > m_scene.m_maxPhys)
3193 {
3194 f = m_scene.m_maxPhys / oldSize.Z;
3195 a = f / z;
3196 x *= a;
3197 y *= a;
3198 z *= a;
3199 }
3200 }
3201 else
3202 {
3203 if (oldSize.X*x > m_scene.m_maxNonphys)
3204 {
3205 f = m_scene.m_maxNonphys / oldSize.X;
3206 a = f / x;
3207 x *= a;
3208 y *= a;
3209 z *= a;
3210 }
3211 if (oldSize.Y*y > m_scene.m_maxNonphys)
3212 {
3213 f = m_scene.m_maxNonphys / oldSize.Y;
3214 a = f / y;
3215 x *= a;
3216 y *= a;
3217 z *= a;
3218 }
3219 if (oldSize.Z*z > m_scene.m_maxNonphys)
2915 { 3220 {
2916 if (oldSize.X*x > m_scene.m_maxNonphys) 3221 f = m_scene.m_maxNonphys / oldSize.Z;
2917 { 3222 a = f / z;
2918 f = m_scene.m_maxNonphys / oldSize.X; 3223 x *= a;
2919 a = f / x; 3224 y *= a;
2920 x *= a; 3225 z *= a;
2921 y *= a;
2922 z *= a;
2923 }
2924 if (oldSize.Y*y > m_scene.m_maxNonphys)
2925 {
2926 f = m_scene.m_maxNonphys / oldSize.Y;
2927 a = f / y;
2928 x *= a;
2929 y *= a;
2930 z *= a;
2931 }
2932 if (oldSize.Z*z > m_scene.m_maxNonphys)
2933 {
2934 f = m_scene.m_maxNonphys / oldSize.Z;
2935 a = f / z;
2936 x *= a;
2937 y *= a;
2938 z *= a;
2939 }
2940 } 3226 }
2941 obPart.IgnoreUndoUpdate = false; 3227 obPart.IgnoreUndoUpdate = false;
2942 obPart.StoreUndoState(); 3228 obPart.StoreUndoState();
@@ -2944,6 +3230,7 @@ namespace OpenSim.Region.Framework.Scenes
2944 } 3230 }
2945 } 3231 }
2946 } 3232 }
3233 lockPartsForRead(false);
2947 3234
2948 Vector3 prevScale = part.Scale; 3235 Vector3 prevScale = part.Scale;
2949 prevScale.X *= x; 3236 prevScale.X *= x;
@@ -2951,7 +3238,7 @@ namespace OpenSim.Region.Framework.Scenes
2951 prevScale.Z *= z; 3238 prevScale.Z *= z;
2952 part.Resize(prevScale); 3239 part.Resize(prevScale);
2953 3240
2954 lock (m_parts) 3241 lockPartsForRead(true);
2955 { 3242 {
2956 foreach (SceneObjectPart obPart in m_parts.Values) 3243 foreach (SceneObjectPart obPart in m_parts.Values)
2957 { 3244 {
@@ -2973,6 +3260,7 @@ namespace OpenSim.Region.Framework.Scenes
2973 obPart.StoreUndoState(); 3260 obPart.StoreUndoState();
2974 } 3261 }
2975 } 3262 }
3263 lockPartsForRead(false);
2976 3264
2977 if (part.PhysActor != null) 3265 if (part.PhysActor != null)
2978 { 3266 {
@@ -3075,7 +3363,7 @@ namespace OpenSim.Region.Framework.Scenes
3075 axDiff *= Quaternion.Inverse(partRotation); 3363 axDiff *= Quaternion.Inverse(partRotation);
3076 diff = axDiff; 3364 diff = axDiff;
3077 3365
3078 lock (m_parts) 3366 lockPartsForRead(true);
3079 { 3367 {
3080 foreach (SceneObjectPart obPart in m_parts.Values) 3368 foreach (SceneObjectPart obPart in m_parts.Values)
3081 { 3369 {
@@ -3085,6 +3373,7 @@ namespace OpenSim.Region.Framework.Scenes
3085 } 3373 }
3086 } 3374 }
3087 } 3375 }
3376 lockPartsForRead(false);
3088 3377
3089 AbsolutePosition = newPos; 3378 AbsolutePosition = newPos;
3090 3379
@@ -3218,25 +3507,25 @@ namespace OpenSim.Region.Framework.Scenes
3218 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); 3507 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
3219 } 3508 }
3220 3509
3221 lock (m_parts) 3510 lockPartsForRead(true);
3511
3512 foreach (SceneObjectPart prim in m_parts.Values)
3222 { 3513 {
3223 foreach (SceneObjectPart prim in m_parts.Values) 3514 if (prim.UUID != m_rootPart.UUID)
3224 { 3515 {
3225 if (prim.UUID != m_rootPart.UUID) 3516 prim.IgnoreUndoUpdate = true;
3226 { 3517 Vector3 axPos = prim.OffsetPosition;
3227 prim.IgnoreUndoUpdate = true; 3518 axPos *= oldParentRot;
3228 Vector3 axPos = prim.OffsetPosition; 3519 axPos *= Quaternion.Inverse(axRot);
3229 axPos *= oldParentRot; 3520 prim.OffsetPosition = axPos;
3230 axPos *= Quaternion.Inverse(axRot); 3521 Quaternion primsRot = prim.RotationOffset;
3231 prim.OffsetPosition = axPos; 3522 Quaternion newRot = primsRot * oldParentRot;
3232 Quaternion primsRot = prim.RotationOffset; 3523 newRot *= Quaternion.Inverse(axRot);
3233 Quaternion newRot = primsRot * oldParentRot; 3524 prim.RotationOffset = newRot;
3234 newRot *= Quaternion.Inverse(axRot); 3525 prim.ScheduleTerseUpdate();
3235 prim.RotationOffset = newRot;
3236 prim.ScheduleTerseUpdate();
3237 }
3238 } 3526 }
3239 } 3527 }
3528
3240 foreach (SceneObjectPart childpart in Children.Values) 3529 foreach (SceneObjectPart childpart in Children.Values)
3241 { 3530 {
3242 if (childpart != m_rootPart) 3531 if (childpart != m_rootPart)
@@ -3245,6 +3534,9 @@ namespace OpenSim.Region.Framework.Scenes
3245 childpart.StoreUndoState(); 3534 childpart.StoreUndoState();
3246 } 3535 }
3247 } 3536 }
3537
3538 lockPartsForRead(false);
3539
3248 m_rootPart.ScheduleTerseUpdate(); 3540 m_rootPart.ScheduleTerseUpdate();
3249 } 3541 }
3250 3542
@@ -3366,7 +3658,7 @@ namespace OpenSim.Region.Framework.Scenes
3366 if (atTargets.Count > 0) 3658 if (atTargets.Count > 0)
3367 { 3659 {
3368 uint[] localids = new uint[0]; 3660 uint[] localids = new uint[0];
3369 lock (m_parts) 3661 lockPartsForRead(true);
3370 { 3662 {
3371 localids = new uint[m_parts.Count]; 3663 localids = new uint[m_parts.Count];
3372 int cntr = 0; 3664 int cntr = 0;
@@ -3376,6 +3668,7 @@ namespace OpenSim.Region.Framework.Scenes
3376 cntr++; 3668 cntr++;
3377 } 3669 }
3378 } 3670 }
3671 lockPartsForRead(false);
3379 3672
3380 for (int ctr = 0; ctr < localids.Length; ctr++) 3673 for (int ctr = 0; ctr < localids.Length; ctr++)
3381 { 3674 {
@@ -3394,7 +3687,7 @@ namespace OpenSim.Region.Framework.Scenes
3394 { 3687 {
3395 //trigger not_at_target 3688 //trigger not_at_target
3396 uint[] localids = new uint[0]; 3689 uint[] localids = new uint[0];
3397 lock (m_parts) 3690 lockPartsForRead(true);
3398 { 3691 {
3399 localids = new uint[m_parts.Count]; 3692 localids = new uint[m_parts.Count];
3400 int cntr = 0; 3693 int cntr = 0;
@@ -3404,7 +3697,8 @@ namespace OpenSim.Region.Framework.Scenes
3404 cntr++; 3697 cntr++;
3405 } 3698 }
3406 } 3699 }
3407 3700 lockPartsForRead(false);
3701
3408 for (int ctr = 0; ctr < localids.Length; ctr++) 3702 for (int ctr = 0; ctr < localids.Length; ctr++)
3409 { 3703 {
3410 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]); 3704 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]);
@@ -3445,7 +3739,8 @@ namespace OpenSim.Region.Framework.Scenes
3445 if (atRotTargets.Count > 0) 3739 if (atRotTargets.Count > 0)
3446 { 3740 {
3447 uint[] localids = new uint[0]; 3741 uint[] localids = new uint[0];
3448 lock (m_parts) 3742 lockPartsForRead(true);
3743 try
3449 { 3744 {
3450 localids = new uint[m_parts.Count]; 3745 localids = new uint[m_parts.Count];
3451 int cntr = 0; 3746 int cntr = 0;
@@ -3455,6 +3750,10 @@ namespace OpenSim.Region.Framework.Scenes
3455 cntr++; 3750 cntr++;
3456 } 3751 }
3457 } 3752 }
3753 finally
3754 {
3755 lockPartsForRead(false);
3756 }
3458 3757
3459 for (int ctr = 0; ctr < localids.Length; ctr++) 3758 for (int ctr = 0; ctr < localids.Length; ctr++)
3460 { 3759 {
@@ -3473,7 +3772,8 @@ namespace OpenSim.Region.Framework.Scenes
3473 { 3772 {
3474 //trigger not_at_target 3773 //trigger not_at_target
3475 uint[] localids = new uint[0]; 3774 uint[] localids = new uint[0];
3476 lock (m_parts) 3775 lockPartsForRead(true);
3776 try
3477 { 3777 {
3478 localids = new uint[m_parts.Count]; 3778 localids = new uint[m_parts.Count];
3479 int cntr = 0; 3779 int cntr = 0;
@@ -3483,6 +3783,10 @@ namespace OpenSim.Region.Framework.Scenes
3483 cntr++; 3783 cntr++;
3484 } 3784 }
3485 } 3785 }
3786 finally
3787 {
3788 lockPartsForRead(false);
3789 }
3486 3790
3487 for (int ctr = 0; ctr < localids.Length; ctr++) 3791 for (int ctr = 0; ctr < localids.Length; ctr++)
3488 { 3792 {
@@ -3496,19 +3800,20 @@ namespace OpenSim.Region.Framework.Scenes
3496 public float GetMass() 3800 public float GetMass()
3497 { 3801 {
3498 float retmass = 0f; 3802 float retmass = 0f;
3499 lock (m_parts) 3803 lockPartsForRead(true);
3500 { 3804 {
3501 foreach (SceneObjectPart part in m_parts.Values) 3805 foreach (SceneObjectPart part in m_parts.Values)
3502 { 3806 {
3503 retmass += part.GetMass(); 3807 retmass += part.GetMass();
3504 } 3808 }
3505 } 3809 }
3810 lockPartsForRead(false);
3506 return retmass; 3811 return retmass;
3507 } 3812 }
3508 3813
3509 public void CheckSculptAndLoad() 3814 public void CheckSculptAndLoad()
3510 { 3815 {
3511 lock (m_parts) 3816 lockPartsForRead(true);
3512 { 3817 {
3513 if (!IsDeleted) 3818 if (!IsDeleted)
3514 { 3819 {
@@ -3533,6 +3838,7 @@ namespace OpenSim.Region.Framework.Scenes
3533 } 3838 }
3534 } 3839 }
3535 } 3840 }
3841 lockPartsForRead(false);
3536 } 3842 }
3537 3843
3538 protected void AssetReceived(string id, Object sender, AssetBase asset) 3844 protected void AssetReceived(string id, Object sender, AssetBase asset)
@@ -3553,7 +3859,7 @@ namespace OpenSim.Region.Framework.Scenes
3553 /// <param name="client"></param> 3859 /// <param name="client"></param>
3554 public void SetGroup(UUID GroupID, IClientAPI client) 3860 public void SetGroup(UUID GroupID, IClientAPI client)
3555 { 3861 {
3556 lock (m_parts) 3862 lockPartsForRead(true);
3557 { 3863 {
3558 foreach (SceneObjectPart part in m_parts.Values) 3864 foreach (SceneObjectPart part in m_parts.Values)
3559 { 3865 {
@@ -3563,6 +3869,7 @@ namespace OpenSim.Region.Framework.Scenes
3563 3869
3564 HasGroupChanged = true; 3870 HasGroupChanged = true;
3565 } 3871 }
3872 lockPartsForRead(false);
3566 3873
3567 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled 3874 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled
3568 // for the same object with very different properties. The caller must schedule the update. 3875 // for the same object with very different properties. The caller must schedule the update.
@@ -3584,11 +3891,12 @@ namespace OpenSim.Region.Framework.Scenes
3584 3891
3585 public void SetAttachmentPoint(byte point) 3892 public void SetAttachmentPoint(byte point)
3586 { 3893 {
3587 lock (m_parts) 3894 lockPartsForRead(true);
3588 { 3895 {
3589 foreach (SceneObjectPart part in m_parts.Values) 3896 foreach (SceneObjectPart part in m_parts.Values)
3590 part.SetAttachmentPoint(point); 3897 part.SetAttachmentPoint(point);
3591 } 3898 }
3899 lockPartsForRead(false);
3592 } 3900 }
3593 3901
3594 #region ISceneObject 3902 #region ISceneObject
@@ -3622,6 +3930,14 @@ namespace OpenSim.Region.Framework.Scenes
3622 SetFromItemID(uuid); 3930 SetFromItemID(uuid);
3623 } 3931 }
3624 3932
3933 public void ResetOwnerChangeFlag()
3934 {
3935 ForEachPart(delegate(SceneObjectPart part)
3936 {
3937 part.ResetOwnerChangeFlag();
3938 });
3939 }
3940
3625 #endregion 3941 #endregion
3626 } 3942 }
3627} 3943}