diff options
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs')
-rw-r--r-- | OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 640 |
1 files changed, 434 insertions, 206 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 602b811..edaf1a0 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | |||
@@ -104,8 +104,78 @@ namespace OpenSim.Region.Framework.Scenes | |||
104 | /// since the group's last persistent backup | 104 | /// since the group's last persistent backup |
105 | /// </summary> | 105 | /// </summary> |
106 | private bool m_hasGroupChanged = false; | 106 | private bool m_hasGroupChanged = false; |
107 | private long timeFirstChanged; | 107 | private long timeFirstChanged = 0; |
108 | private long timeLastChanged; | 108 | private long timeLastChanged = 0; |
109 | private long m_maxPersistTime = 0; | ||
110 | private long m_minPersistTime = 0; | ||
111 | private Random m_rand; | ||
112 | |||
113 | private System.Threading.ReaderWriterLockSlim m_partsLock = new System.Threading.ReaderWriterLockSlim(); | ||
114 | |||
115 | public void lockPartsForRead(bool locked) | ||
116 | { | ||
117 | if (locked) | ||
118 | { | ||
119 | if (m_partsLock.RecursiveReadCount > 0) | ||
120 | { | ||
121 | m_log.Error("[SceneObjectGroup.m_parts] Recursive read lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue."); | ||
122 | m_partsLock.ExitReadLock(); | ||
123 | } | ||
124 | if (m_partsLock.RecursiveWriteCount > 0) | ||
125 | { | ||
126 | m_log.Error("[SceneObjectGroup.m_parts] Recursive read lock requested. This should not happen and means something needs to be fixed."); | ||
127 | m_partsLock.ExitWriteLock(); | ||
128 | } | ||
129 | |||
130 | while (!m_partsLock.TryEnterReadLock(60000)) | ||
131 | { | ||
132 | m_log.Error("[SceneObjectGroup.m_parts] Thread lock detected while trying to aquire READ lock of m_parts in SceneObjectGroup. I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed."); | ||
133 | if (m_partsLock.IsWriteLockHeld) | ||
134 | { | ||
135 | m_partsLock = new System.Threading.ReaderWriterLockSlim(); | ||
136 | } | ||
137 | } | ||
138 | } | ||
139 | else | ||
140 | { | ||
141 | if (m_partsLock.RecursiveReadCount > 0) | ||
142 | { | ||
143 | m_partsLock.ExitReadLock(); | ||
144 | } | ||
145 | } | ||
146 | } | ||
147 | public void lockPartsForWrite(bool locked) | ||
148 | { | ||
149 | if (locked) | ||
150 | { | ||
151 | if (m_partsLock.RecursiveReadCount > 0) | ||
152 | { | ||
153 | m_log.Error("[SceneObjectGroup.m_parts] Recursive write lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue."); | ||
154 | m_partsLock.ExitReadLock(); | ||
155 | } | ||
156 | if (m_partsLock.RecursiveWriteCount > 0) | ||
157 | { | ||
158 | m_log.Error("[SceneObjectGroup.m_parts] Recursive write lock requested. This should not happen and means something needs to be fixed."); | ||
159 | m_partsLock.ExitWriteLock(); | ||
160 | } | ||
161 | |||
162 | while (!m_partsLock.TryEnterWriteLock(60000)) | ||
163 | { | ||
164 | m_log.Error("[SceneObjectGroup.m_parts] Thread lock detected while trying to aquire WRITE lock of m_scripts in XEngine. I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed."); | ||
165 | if (m_partsLock.IsWriteLockHeld) | ||
166 | { | ||
167 | m_partsLock = new System.Threading.ReaderWriterLockSlim(); | ||
168 | } | ||
169 | } | ||
170 | } | ||
171 | else | ||
172 | { | ||
173 | if (m_partsLock.RecursiveWriteCount > 0) | ||
174 | { | ||
175 | m_partsLock.ExitWriteLock(); | ||
176 | } | ||
177 | } | ||
178 | } | ||
109 | 179 | ||
110 | public bool HasGroupChanged | 180 | public bool HasGroupChanged |
111 | { | 181 | { |
@@ -116,6 +186,32 @@ namespace OpenSim.Region.Framework.Scenes | |||
116 | timeLastChanged = DateTime.Now.Ticks; | 186 | timeLastChanged = DateTime.Now.Ticks; |
117 | if (!m_hasGroupChanged) | 187 | if (!m_hasGroupChanged) |
118 | timeFirstChanged = DateTime.Now.Ticks; | 188 | timeFirstChanged = DateTime.Now.Ticks; |
189 | if (m_rootPart != null && m_rootPart.UUID != null && m_scene != null) | ||
190 | { | ||
191 | if (m_rand == null) | ||
192 | { | ||
193 | byte[] val = new byte[16]; | ||
194 | m_rootPart.UUID.ToBytes(val, 0); | ||
195 | m_rand = new Random(BitConverter.ToInt32(val, 0)); | ||
196 | } | ||
197 | |||
198 | if (m_scene.GetRootAgentCount() == 0) | ||
199 | { | ||
200 | //If the region is empty, this change has been made by an automated process | ||
201 | //and thus we delay the persist time by a random amount between 1.5 and 2.5. | ||
202 | |||
203 | float factor = 1.5f + (float)(m_rand.NextDouble()); | ||
204 | m_maxPersistTime = (long)((float)m_scene.m_persistAfter * factor); | ||
205 | m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * factor); | ||
206 | } | ||
207 | else | ||
208 | { | ||
209 | //If the region is not empty, we want to obey the minimum and maximum persist times | ||
210 | //but add a random factor so we stagger the object persistance a little | ||
211 | m_maxPersistTime = (long)((float)m_scene.m_persistAfter * (1.0d - (m_rand.NextDouble() / 5.0d))); //Multiply by 1.0-1.5 | ||
212 | m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * (1.0d + (m_rand.NextDouble() / 2.0d))); //Multiply by 0.8-1.0 | ||
213 | } | ||
214 | } | ||
119 | } | 215 | } |
120 | m_hasGroupChanged = value; | 216 | m_hasGroupChanged = value; |
121 | } | 217 | } |
@@ -131,8 +227,19 @@ namespace OpenSim.Region.Framework.Scenes | |||
131 | return false; | 227 | return false; |
132 | if (m_scene.ShuttingDown) | 228 | if (m_scene.ShuttingDown) |
133 | return true; | 229 | return true; |
230 | |||
231 | if (m_minPersistTime == 0 || m_maxPersistTime == 0) | ||
232 | { | ||
233 | m_maxPersistTime = m_scene.m_persistAfter; | ||
234 | m_minPersistTime = m_scene.m_dontPersistBefore; | ||
235 | } | ||
236 | |||
134 | long currentTime = DateTime.Now.Ticks; | 237 | long currentTime = DateTime.Now.Ticks; |
135 | if (currentTime - timeLastChanged > m_scene.m_dontPersistBefore || currentTime - timeFirstChanged > m_scene.m_persistAfter) | 238 | |
239 | if (timeLastChanged == 0) timeLastChanged = currentTime; | ||
240 | if (timeFirstChanged == 0) timeFirstChanged = currentTime; | ||
241 | |||
242 | if (currentTime - timeLastChanged > m_minPersistTime || currentTime - timeFirstChanged > m_maxPersistTime) | ||
136 | return true; | 243 | return true; |
137 | return false; | 244 | return false; |
138 | } | 245 | } |
@@ -258,13 +365,16 @@ namespace OpenSim.Region.Framework.Scenes | |||
258 | set | 365 | set |
259 | { | 366 | { |
260 | m_regionHandle = value; | 367 | m_regionHandle = value; |
261 | lock (m_parts) | 368 | lockPartsForRead(true); |
262 | { | 369 | { |
263 | foreach (SceneObjectPart part in m_parts.Values) | 370 | foreach (SceneObjectPart part in m_parts.Values) |
264 | { | 371 | { |
372 | |||
265 | part.RegionHandle = m_regionHandle; | 373 | part.RegionHandle = m_regionHandle; |
374 | |||
266 | } | 375 | } |
267 | } | 376 | } |
377 | lockPartsForRead(false); | ||
268 | } | 378 | } |
269 | } | 379 | } |
270 | 380 | ||
@@ -298,6 +408,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
298 | { | 408 | { |
299 | m_scene.CrossPrimGroupIntoNewRegion(val, this, true); | 409 | m_scene.CrossPrimGroupIntoNewRegion(val, this, true); |
300 | } | 410 | } |
411 | |||
412 | lockPartsForRead(true); | ||
413 | |||
301 | if (RootPart.GetStatusSandbox()) | 414 | if (RootPart.GetStatusSandbox()) |
302 | { | 415 | { |
303 | if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) | 416 | if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) |
@@ -308,14 +421,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
308 | return; | 421 | return; |
309 | } | 422 | } |
310 | } | 423 | } |
311 | lock (m_parts) | 424 | |
425 | foreach (SceneObjectPart part in m_parts.Values) | ||
312 | { | 426 | { |
313 | foreach (SceneObjectPart part in m_parts.Values) | 427 | part.GroupPosition = val; |
314 | { | ||
315 | part.GroupPosition = val; | ||
316 | } | ||
317 | } | 428 | } |
318 | 429 | ||
430 | lockPartsForRead(false); | ||
431 | |||
319 | //if (m_rootPart.PhysActor != null) | 432 | //if (m_rootPart.PhysActor != null) |
320 | //{ | 433 | //{ |
321 | //m_rootPart.PhysActor.Position = | 434 | //m_rootPart.PhysActor.Position = |
@@ -457,6 +570,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
457 | /// </summary> | 570 | /// </summary> |
458 | public SceneObjectGroup() | 571 | public SceneObjectGroup() |
459 | { | 572 | { |
573 | |||
460 | } | 574 | } |
461 | 575 | ||
462 | /// <summary> | 576 | /// <summary> |
@@ -473,7 +587,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
473 | /// Constructor. This object is added to the scene later via AttachToScene() | 587 | /// Constructor. This object is added to the scene later via AttachToScene() |
474 | /// </summary> | 588 | /// </summary> |
475 | public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) | 589 | public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) |
476 | { | 590 | { |
477 | SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero)); | 591 | SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero)); |
478 | } | 592 | } |
479 | 593 | ||
@@ -504,13 +618,16 @@ namespace OpenSim.Region.Framework.Scenes | |||
504 | 618 | ||
505 | public void SetFromItemID(UUID AssetId) | 619 | public void SetFromItemID(UUID AssetId) |
506 | { | 620 | { |
507 | lock (m_parts) | 621 | lockPartsForRead(true); |
508 | { | 622 | { |
509 | foreach (SceneObjectPart part in m_parts.Values) | 623 | foreach (SceneObjectPart part in m_parts.Values) |
510 | { | 624 | { |
625 | |||
511 | part.FromItemID = AssetId; | 626 | part.FromItemID = AssetId; |
627 | |||
512 | } | 628 | } |
513 | } | 629 | } |
630 | lockPartsForRead(false); | ||
514 | } | 631 | } |
515 | 632 | ||
516 | public UUID GetFromItemID() | 633 | public UUID GetFromItemID() |
@@ -579,10 +696,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
579 | Vector3 maxScale = Vector3.Zero; | 696 | Vector3 maxScale = Vector3.Zero; |
580 | Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f); | 697 | Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f); |
581 | 698 | ||
582 | lock (m_parts) | 699 | lockPartsForRead(true); |
583 | { | 700 | { |
584 | foreach (SceneObjectPart part in m_parts.Values) | 701 | foreach (SceneObjectPart part in m_parts.Values) |
585 | { | 702 | { |
703 | |||
586 | Vector3 partscale = part.Scale; | 704 | Vector3 partscale = part.Scale; |
587 | Vector3 partoffset = part.OffsetPosition; | 705 | Vector3 partoffset = part.OffsetPosition; |
588 | 706 | ||
@@ -593,8 +711,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
593 | maxScale.X = (partscale.X + partoffset.X > maxScale.X) ? partscale.X + partoffset.X : maxScale.X; | 711 | maxScale.X = (partscale.X + partoffset.X > maxScale.X) ? partscale.X + partoffset.X : maxScale.X; |
594 | maxScale.Y = (partscale.Y + partoffset.Y > maxScale.Y) ? partscale.Y + partoffset.Y : maxScale.Y; | 712 | maxScale.Y = (partscale.Y + partoffset.Y > maxScale.Y) ? partscale.Y + partoffset.Y : maxScale.Y; |
595 | maxScale.Z = (partscale.Z + partoffset.Z > maxScale.Z) ? partscale.Z + partoffset.Z : maxScale.Z; | 713 | maxScale.Z = (partscale.Z + partoffset.Z > maxScale.Z) ? partscale.Z + partoffset.Z : maxScale.Z; |
714 | |||
596 | } | 715 | } |
597 | } | 716 | } |
717 | lockPartsForRead(false); | ||
718 | |||
598 | finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X; | 719 | finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X; |
599 | finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y; | 720 | finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y; |
600 | finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z; | 721 | finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z; |
@@ -610,10 +731,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
610 | 731 | ||
611 | EntityIntersection result = new EntityIntersection(); | 732 | EntityIntersection result = new EntityIntersection(); |
612 | 733 | ||
613 | lock (m_parts) | 734 | lockPartsForRead(true); |
614 | { | 735 | { |
615 | foreach (SceneObjectPart part in m_parts.Values) | 736 | foreach (SceneObjectPart part in m_parts.Values) |
616 | { | 737 | { |
738 | |||
617 | // Temporary commented to stop compiler warning | 739 | // Temporary commented to stop compiler warning |
618 | //Vector3 partPosition = | 740 | //Vector3 partPosition = |
619 | // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z); | 741 | // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z); |
@@ -641,8 +763,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
641 | result.distance = inter.distance; | 763 | result.distance = inter.distance; |
642 | } | 764 | } |
643 | } | 765 | } |
766 | |||
644 | } | 767 | } |
645 | } | 768 | } |
769 | lockPartsForRead(false); | ||
646 | return result; | 770 | return result; |
647 | } | 771 | } |
648 | 772 | ||
@@ -655,10 +779,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
655 | public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight) | 779 | public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight) |
656 | { | 780 | { |
657 | float maxX = -256f, maxY = -256f, maxZ = -256f, minX = 256f, minY = 256f, minZ = 256f; | 781 | float maxX = -256f, maxY = -256f, maxZ = -256f, minX = 256f, minY = 256f, minZ = 256f; |
658 | lock (m_parts) | 782 | lockPartsForRead(true); |
659 | { | 783 | { |
660 | foreach (SceneObjectPart part in m_parts.Values) | 784 | foreach (SceneObjectPart part in m_parts.Values) |
661 | { | 785 | { |
786 | |||
662 | Vector3 worldPos = part.GetWorldPosition(); | 787 | Vector3 worldPos = part.GetWorldPosition(); |
663 | Vector3 offset = worldPos - AbsolutePosition; | 788 | Vector3 offset = worldPos - AbsolutePosition; |
664 | Quaternion worldRot; | 789 | Quaternion worldRot; |
@@ -717,6 +842,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
717 | backBottomRight.Y = orig.Y + (part.Scale.Y / 2); | 842 | backBottomRight.Y = orig.Y + (part.Scale.Y / 2); |
718 | backBottomRight.Z = orig.Z - (part.Scale.Z / 2); | 843 | backBottomRight.Z = orig.Z - (part.Scale.Z / 2); |
719 | 844 | ||
845 | |||
846 | |||
720 | //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z); | 847 | //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z); |
721 | //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z); | 848 | //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z); |
722 | //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z); | 849 | //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z); |
@@ -888,6 +1015,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
888 | minZ = backBottomLeft.Z; | 1015 | minZ = backBottomLeft.Z; |
889 | } | 1016 | } |
890 | } | 1017 | } |
1018 | lockPartsForRead(false); | ||
891 | 1019 | ||
892 | Vector3 boundingBox = new Vector3(maxX - minX, maxY - minY, maxZ - minZ); | 1020 | Vector3 boundingBox = new Vector3(maxX - minX, maxY - minY, maxZ - minZ); |
893 | 1021 | ||
@@ -916,17 +1044,20 @@ namespace OpenSim.Region.Framework.Scenes | |||
916 | Dictionary<UUID,string> states = new Dictionary<UUID,string>(); | 1044 | Dictionary<UUID,string> states = new Dictionary<UUID,string>(); |
917 | 1045 | ||
918 | // Capture script state while holding the lock | 1046 | // Capture script state while holding the lock |
919 | lock (m_parts) | 1047 | lockPartsForRead(true); |
920 | { | 1048 | { |
921 | foreach (SceneObjectPart part in m_parts.Values) | 1049 | foreach (SceneObjectPart part in m_parts.Values) |
922 | { | 1050 | { |
1051 | |||
923 | Dictionary<UUID,string> pstates = part.Inventory.GetScriptStates(); | 1052 | Dictionary<UUID,string> pstates = part.Inventory.GetScriptStates(); |
924 | foreach (UUID itemid in pstates.Keys) | 1053 | foreach (UUID itemid in pstates.Keys) |
925 | { | 1054 | { |
926 | states.Add(itemid, pstates[itemid]); | 1055 | states.Add(itemid, pstates[itemid]); |
927 | } | 1056 | } |
1057 | |||
928 | } | 1058 | } |
929 | } | 1059 | } |
1060 | lockPartsForRead(false); | ||
930 | 1061 | ||
931 | if (states.Count > 0) | 1062 | if (states.Count > 0) |
932 | { | 1063 | { |
@@ -1094,13 +1225,16 @@ namespace OpenSim.Region.Framework.Scenes | |||
1094 | 1225 | ||
1095 | public override void UpdateMovement() | 1226 | public override void UpdateMovement() |
1096 | { | 1227 | { |
1097 | lock (m_parts) | 1228 | lockPartsForRead(true); |
1098 | { | 1229 | { |
1099 | foreach (SceneObjectPart part in m_parts.Values) | 1230 | foreach (SceneObjectPart part in m_parts.Values) |
1100 | { | 1231 | { |
1232 | |||
1101 | part.UpdateMovement(); | 1233 | part.UpdateMovement(); |
1234 | |||
1102 | } | 1235 | } |
1103 | } | 1236 | } |
1237 | lockPartsForRead(false); | ||
1104 | } | 1238 | } |
1105 | 1239 | ||
1106 | public ushort GetTimeDilation() | 1240 | public ushort GetTimeDilation() |
@@ -1144,7 +1278,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1144 | /// <param name="part"></param> | 1278 | /// <param name="part"></param> |
1145 | public void AddPart(SceneObjectPart part) | 1279 | public void AddPart(SceneObjectPart part) |
1146 | { | 1280 | { |
1147 | lock (m_parts) | 1281 | lockPartsForWrite(true); |
1148 | { | 1282 | { |
1149 | part.SetParent(this); | 1283 | part.SetParent(this); |
1150 | m_parts.Add(part.UUID, part); | 1284 | m_parts.Add(part.UUID, part); |
@@ -1154,6 +1288,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1154 | if (part.LinkNum == 2 && RootPart != null) | 1288 | if (part.LinkNum == 2 && RootPart != null) |
1155 | RootPart.LinkNum = 1; | 1289 | RootPart.LinkNum = 1; |
1156 | } | 1290 | } |
1291 | lockPartsForWrite(false); | ||
1157 | } | 1292 | } |
1158 | 1293 | ||
1159 | /// <summary> | 1294 | /// <summary> |
@@ -1161,28 +1296,33 @@ namespace OpenSim.Region.Framework.Scenes | |||
1161 | /// </summary> | 1296 | /// </summary> |
1162 | private void UpdateParentIDs() | 1297 | private void UpdateParentIDs() |
1163 | { | 1298 | { |
1164 | lock (m_parts) | 1299 | lockPartsForRead(true); |
1165 | { | 1300 | { |
1166 | foreach (SceneObjectPart part in m_parts.Values) | 1301 | foreach (SceneObjectPart part in m_parts.Values) |
1167 | { | 1302 | { |
1303 | |||
1168 | if (part.UUID != m_rootPart.UUID) | 1304 | if (part.UUID != m_rootPart.UUID) |
1169 | { | 1305 | { |
1170 | part.ParentID = m_rootPart.LocalId; | 1306 | part.ParentID = m_rootPart.LocalId; |
1171 | } | 1307 | } |
1308 | |||
1172 | } | 1309 | } |
1173 | } | 1310 | } |
1311 | lockPartsForRead(false); | ||
1174 | } | 1312 | } |
1175 | 1313 | ||
1176 | public void RegenerateFullIDs() | 1314 | public void RegenerateFullIDs() |
1177 | { | 1315 | { |
1178 | lock (m_parts) | 1316 | lockPartsForRead(true); |
1179 | { | 1317 | { |
1180 | foreach (SceneObjectPart part in m_parts.Values) | 1318 | foreach (SceneObjectPart part in m_parts.Values) |
1181 | { | 1319 | { |
1320 | |||
1182 | part.UUID = UUID.Random(); | 1321 | part.UUID = UUID.Random(); |
1183 | 1322 | ||
1184 | } | 1323 | } |
1185 | } | 1324 | } |
1325 | lockPartsForRead(false); | ||
1186 | } | 1326 | } |
1187 | 1327 | ||
1188 | // helper provided for parts. | 1328 | // helper provided for parts. |
@@ -1263,29 +1403,33 @@ namespace OpenSim.Region.Framework.Scenes | |||
1263 | 1403 | ||
1264 | DetachFromBackup(); | 1404 | DetachFromBackup(); |
1265 | 1405 | ||
1266 | lock (m_parts) | 1406 | lockPartsForRead(true); |
1407 | List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values); | ||
1408 | lockPartsForRead(false); | ||
1409 | |||
1410 | foreach (SceneObjectPart part in values) | ||
1267 | { | 1411 | { |
1268 | foreach (SceneObjectPart part in m_parts.Values) | ||
1269 | { | ||
1270 | // part.Inventory.RemoveScriptInstances(); | 1412 | // part.Inventory.RemoveScriptInstances(); |
1271 | 1413 | ||
1272 | ScenePresence[] avatars = Scene.GetScenePresences(); | 1414 | ScenePresence[] avatars = Scene.GetScenePresences(); |
1273 | for (int i = 0; i < avatars.Length; i++) | 1415 | for (int i = 0; i < avatars.Length; i++) |
1416 | { | ||
1417 | if (avatars[i].ParentID == LocalId) | ||
1274 | { | 1418 | { |
1275 | if (avatars[i].ParentID == LocalId) | 1419 | avatars[i].StandUp(); |
1276 | { | 1420 | } |
1277 | avatars[i].StandUp(); | ||
1278 | } | ||
1279 | 1421 | ||
1280 | if (!silent) | 1422 | if (!silent) |
1281 | { | 1423 | { |
1282 | part.UpdateFlag = 0; | 1424 | part.UpdateFlag = 0; |
1283 | if (part == m_rootPart) | 1425 | if (part == m_rootPart) |
1284 | avatars[i].ControllingClient.SendKillObject(m_regionHandle, part.LocalId); | 1426 | avatars[i].ControllingClient.SendKillObject(m_regionHandle, part.LocalId); |
1285 | } | ||
1286 | } | 1427 | } |
1287 | } | 1428 | } |
1429 | |||
1288 | } | 1430 | } |
1431 | |||
1432 | |||
1289 | } | 1433 | } |
1290 | 1434 | ||
1291 | public void AddScriptLPS(int count) | 1435 | public void AddScriptLPS(int count) |
@@ -1310,17 +1454,20 @@ namespace OpenSim.Region.Framework.Scenes | |||
1310 | 1454 | ||
1311 | scriptEvents aggregateScriptEvents=0; | 1455 | scriptEvents aggregateScriptEvents=0; |
1312 | 1456 | ||
1313 | lock (m_parts) | 1457 | lockPartsForRead(true); |
1314 | { | 1458 | { |
1315 | foreach (SceneObjectPart part in m_parts.Values) | 1459 | foreach (SceneObjectPart part in m_parts.Values) |
1316 | { | 1460 | { |
1461 | |||
1317 | if (part == null) | 1462 | if (part == null) |
1318 | continue; | 1463 | continue; |
1319 | if (part != RootPart) | 1464 | if (part != RootPart) |
1320 | part.ObjectFlags = objectflagupdate; | 1465 | part.ObjectFlags = objectflagupdate; |
1321 | aggregateScriptEvents |= part.AggregateScriptEvents; | 1466 | aggregateScriptEvents |= part.AggregateScriptEvents; |
1467 | |||
1322 | } | 1468 | } |
1323 | } | 1469 | } |
1470 | lockPartsForRead(false); | ||
1324 | 1471 | ||
1325 | m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0); | 1472 | m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0); |
1326 | m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0); | 1473 | m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0); |
@@ -1362,42 +1509,52 @@ namespace OpenSim.Region.Framework.Scenes | |||
1362 | /// <param name="m_physicalPrim"></param> | 1509 | /// <param name="m_physicalPrim"></param> |
1363 | public void ApplyPhysics(bool m_physicalPrim) | 1510 | public void ApplyPhysics(bool m_physicalPrim) |
1364 | { | 1511 | { |
1365 | lock (m_parts) | 1512 | lockPartsForRead(true); |
1513 | |||
1514 | if (m_parts.Count > 1) | ||
1366 | { | 1515 | { |
1367 | if (m_parts.Count > 1) | 1516 | List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values); |
1517 | lockPartsForRead(false); | ||
1518 | m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim); | ||
1519 | foreach (SceneObjectPart part in values) | ||
1368 | { | 1520 | { |
1369 | m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim); | 1521 | |
1370 | foreach (SceneObjectPart part in m_parts.Values) | 1522 | if (part.LocalId != m_rootPart.LocalId) |
1371 | { | 1523 | { |
1372 | if (part.LocalId != m_rootPart.LocalId) | 1524 | part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim); |
1373 | { | ||
1374 | part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim); | ||
1375 | } | ||
1376 | } | 1525 | } |
1377 | 1526 | ||
1378 | // Hack to get the physics scene geometries in the right spot | ||
1379 | ResetChildPrimPhysicsPositions(); | ||
1380 | } | ||
1381 | else | ||
1382 | { | ||
1383 | m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim); | ||
1384 | } | 1527 | } |
1528 | // Hack to get the physics scene geometries in the right spot | ||
1529 | ResetChildPrimPhysicsPositions(); | ||
1530 | } | ||
1531 | else | ||
1532 | { | ||
1533 | lockPartsForRead(false); | ||
1534 | m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim); | ||
1385 | } | 1535 | } |
1386 | } | 1536 | } |
1387 | 1537 | ||
1388 | public void SetOwnerId(UUID userId) | 1538 | public void SetOwnerId(UUID userId) |
1389 | { | 1539 | { |
1390 | ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); | 1540 | ForEachPart(delegate(SceneObjectPart part) |
1541 | { | ||
1542 | |||
1543 | part.OwnerID = userId; | ||
1544 | |||
1545 | }); | ||
1391 | } | 1546 | } |
1392 | 1547 | ||
1393 | public void ForEachPart(Action<SceneObjectPart> whatToDo) | 1548 | public void ForEachPart(Action<SceneObjectPart> whatToDo) |
1394 | { | 1549 | { |
1395 | lock (m_parts) | 1550 | lockPartsForRead(true); |
1551 | List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values); | ||
1552 | lockPartsForRead(false); | ||
1553 | foreach (SceneObjectPart part in values) | ||
1396 | { | 1554 | { |
1397 | foreach (SceneObjectPart part in m_parts.Values) | 1555 | |
1398 | { | 1556 | whatToDo(part); |
1399 | whatToDo(part); | 1557 | |
1400 | } | ||
1401 | } | 1558 | } |
1402 | } | 1559 | } |
1403 | 1560 | ||
@@ -1496,14 +1653,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
1496 | { | 1653 | { |
1497 | SendPartFullUpdate(remoteClient, RootPart, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID)); | 1654 | SendPartFullUpdate(remoteClient, RootPart, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID)); |
1498 | 1655 | ||
1499 | lock (m_parts) | 1656 | lockPartsForRead(true); |
1500 | { | 1657 | { |
1501 | foreach (SceneObjectPart part in m_parts.Values) | 1658 | foreach (SceneObjectPart part in m_parts.Values) |
1502 | { | 1659 | { |
1660 | |||
1503 | if (part != RootPart) | 1661 | if (part != RootPart) |
1504 | SendPartFullUpdate(remoteClient, part, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID)); | 1662 | SendPartFullUpdate(remoteClient, part, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID)); |
1663 | |||
1505 | } | 1664 | } |
1506 | } | 1665 | } |
1666 | lockPartsForRead(false); | ||
1507 | } | 1667 | } |
1508 | 1668 | ||
1509 | /// <summary> | 1669 | /// <summary> |
@@ -1601,10 +1761,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
1601 | 1761 | ||
1602 | List<SceneObjectPart> partList; | 1762 | List<SceneObjectPart> partList; |
1603 | 1763 | ||
1604 | lock (m_parts) | 1764 | lockPartsForRead(true); |
1605 | { | 1765 | |
1606 | partList = new List<SceneObjectPart>(m_parts.Values); | 1766 | partList = new List<SceneObjectPart>(m_parts.Values); |
1607 | } | 1767 | |
1768 | lockPartsForRead(false); | ||
1608 | 1769 | ||
1609 | partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) | 1770 | partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) |
1610 | { | 1771 | { |
@@ -1827,13 +1988,40 @@ namespace OpenSim.Region.Framework.Scenes | |||
1827 | } | 1988 | } |
1828 | } | 1989 | } |
1829 | 1990 | ||
1991 | public void rotLookAt(Quaternion target, float strength, float damping) | ||
1992 | { | ||
1993 | SceneObjectPart rootpart = m_rootPart; | ||
1994 | if (rootpart != null) | ||
1995 | { | ||
1996 | if (IsAttachment) | ||
1997 | { | ||
1998 | /* | ||
1999 | ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar); | ||
2000 | if (avatar != null) | ||
2001 | { | ||
2002 | Rotate the Av? | ||
2003 | } */ | ||
2004 | } | ||
2005 | else | ||
2006 | { | ||
2007 | if (rootpart.PhysActor != null) | ||
2008 | { // APID must be implemented in your physics system for this to function. | ||
2009 | rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W); | ||
2010 | rootpart.PhysActor.APIDStrength = strength; | ||
2011 | rootpart.PhysActor.APIDDamping = damping; | ||
2012 | rootpart.PhysActor.APIDActive = true; | ||
2013 | } | ||
2014 | } | ||
2015 | } | ||
2016 | } | ||
2017 | |||
1830 | public void stopLookAt() | 2018 | public void stopLookAt() |
1831 | { | 2019 | { |
1832 | SceneObjectPart rootpart = m_rootPart; | 2020 | SceneObjectPart rootpart = m_rootPart; |
1833 | if (rootpart != null) | 2021 | if (rootpart != null) |
1834 | { | 2022 | { |
1835 | if (rootpart.PhysActor != null) | 2023 | if (rootpart.PhysActor != null) |
1836 | { | 2024 | { // APID must be implemented in your physics system for this to function. |
1837 | rootpart.PhysActor.APIDActive = false; | 2025 | rootpart.PhysActor.APIDActive = false; |
1838 | } | 2026 | } |
1839 | } | 2027 | } |
@@ -1901,10 +2089,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
1901 | SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); | 2089 | SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); |
1902 | newPart.SetParent(this); | 2090 | newPart.SetParent(this); |
1903 | 2091 | ||
1904 | lock (m_parts) | 2092 | lockPartsForWrite(true); |
1905 | { | 2093 | { |
1906 | m_parts.Add(newPart.UUID, newPart); | 2094 | m_parts.Add(newPart.UUID, newPart); |
1907 | } | 2095 | } |
2096 | lockPartsForWrite(false); | ||
1908 | 2097 | ||
1909 | SetPartAsNonRoot(newPart); | 2098 | SetPartAsNonRoot(newPart); |
1910 | 2099 | ||
@@ -1967,7 +2156,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1967 | //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0) | 2156 | //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0) |
1968 | // return; | 2157 | // return; |
1969 | 2158 | ||
1970 | lock (m_parts) | 2159 | lockPartsForRead(true); |
1971 | { | 2160 | { |
1972 | bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0); | 2161 | bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0); |
1973 | 2162 | ||
@@ -1987,9 +2176,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
1987 | { | 2176 | { |
1988 | if (!IsSelected) | 2177 | if (!IsSelected) |
1989 | part.UpdateLookAt(); | 2178 | part.UpdateLookAt(); |
2179 | |||
1990 | part.SendScheduledUpdates(); | 2180 | part.SendScheduledUpdates(); |
2181 | |||
1991 | } | 2182 | } |
1992 | } | 2183 | } |
2184 | lockPartsForRead(false); | ||
1993 | } | 2185 | } |
1994 | 2186 | ||
1995 | public void ScheduleFullUpdateToAvatar(ScenePresence presence) | 2187 | public void ScheduleFullUpdateToAvatar(ScenePresence presence) |
@@ -1998,27 +2190,31 @@ namespace OpenSim.Region.Framework.Scenes | |||
1998 | 2190 | ||
1999 | RootPart.AddFullUpdateToAvatar(presence); | 2191 | RootPart.AddFullUpdateToAvatar(presence); |
2000 | 2192 | ||
2001 | lock (m_parts) | 2193 | lockPartsForRead(true); |
2002 | { | 2194 | { |
2003 | foreach (SceneObjectPart part in m_parts.Values) | 2195 | foreach (SceneObjectPart part in m_parts.Values) |
2004 | { | 2196 | { |
2197 | |||
2005 | if (part != RootPart) | 2198 | if (part != RootPart) |
2006 | part.AddFullUpdateToAvatar(presence); | 2199 | part.AddFullUpdateToAvatar(presence); |
2200 | |||
2007 | } | 2201 | } |
2008 | } | 2202 | } |
2203 | lockPartsForRead(false); | ||
2009 | } | 2204 | } |
2010 | 2205 | ||
2011 | public void ScheduleTerseUpdateToAvatar(ScenePresence presence) | 2206 | public void ScheduleTerseUpdateToAvatar(ScenePresence presence) |
2012 | { | 2207 | { |
2013 | // m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1} just to avatar {2}", Name, UUID, presence.Name); | 2208 | lockPartsForRead(true); |
2014 | |||
2015 | lock (m_parts) | ||
2016 | { | 2209 | { |
2017 | foreach (SceneObjectPart part in m_parts.Values) | 2210 | foreach (SceneObjectPart part in m_parts.Values) |
2018 | { | 2211 | { |
2212 | |||
2019 | part.AddTerseUpdateToAvatar(presence); | 2213 | part.AddTerseUpdateToAvatar(presence); |
2214 | |||
2020 | } | 2215 | } |
2021 | } | 2216 | } |
2217 | lockPartsForRead(false); | ||
2022 | } | 2218 | } |
2023 | 2219 | ||
2024 | /// <summary> | 2220 | /// <summary> |
@@ -2031,14 +2227,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
2031 | checkAtTargets(); | 2227 | checkAtTargets(); |
2032 | RootPart.ScheduleFullUpdate(); | 2228 | RootPart.ScheduleFullUpdate(); |
2033 | 2229 | ||
2034 | lock (m_parts) | 2230 | lockPartsForRead(true); |
2035 | { | 2231 | { |
2036 | foreach (SceneObjectPart part in m_parts.Values) | 2232 | foreach (SceneObjectPart part in m_parts.Values) |
2037 | { | 2233 | { |
2234 | |||
2038 | if (part != RootPart) | 2235 | if (part != RootPart) |
2039 | part.ScheduleFullUpdate(); | 2236 | part.ScheduleFullUpdate(); |
2237 | |||
2040 | } | 2238 | } |
2041 | } | 2239 | } |
2240 | lockPartsForRead(false); | ||
2042 | } | 2241 | } |
2043 | 2242 | ||
2044 | /// <summary> | 2243 | /// <summary> |
@@ -2046,15 +2245,16 @@ namespace OpenSim.Region.Framework.Scenes | |||
2046 | /// </summary> | 2245 | /// </summary> |
2047 | public void ScheduleGroupForTerseUpdate() | 2246 | public void ScheduleGroupForTerseUpdate() |
2048 | { | 2247 | { |
2049 | // m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1}", Name, UUID); | 2248 | lockPartsForRead(true); |
2050 | |||
2051 | lock (m_parts) | ||
2052 | { | 2249 | { |
2053 | foreach (SceneObjectPart part in m_parts.Values) | 2250 | foreach (SceneObjectPart part in m_parts.Values) |
2054 | { | 2251 | { |
2252 | |||
2055 | part.ScheduleTerseUpdate(); | 2253 | part.ScheduleTerseUpdate(); |
2254 | |||
2056 | } | 2255 | } |
2057 | } | 2256 | } |
2257 | lockPartsForRead(false); | ||
2058 | } | 2258 | } |
2059 | 2259 | ||
2060 | /// <summary> | 2260 | /// <summary> |
@@ -2069,14 +2269,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
2069 | 2269 | ||
2070 | RootPart.SendFullUpdateToAllClients(); | 2270 | RootPart.SendFullUpdateToAllClients(); |
2071 | 2271 | ||
2072 | lock (m_parts) | 2272 | lockPartsForRead(true); |
2073 | { | 2273 | { |
2074 | foreach (SceneObjectPart part in m_parts.Values) | 2274 | foreach (SceneObjectPart part in m_parts.Values) |
2075 | { | 2275 | { |
2276 | |||
2076 | if (part != RootPart) | 2277 | if (part != RootPart) |
2077 | part.SendFullUpdateToAllClients(); | 2278 | part.SendFullUpdateToAllClients(); |
2279 | |||
2078 | } | 2280 | } |
2079 | } | 2281 | } |
2282 | lockPartsForRead(false); | ||
2080 | } | 2283 | } |
2081 | 2284 | ||
2082 | /// <summary> | 2285 | /// <summary> |
@@ -2108,14 +2311,15 @@ namespace OpenSim.Region.Framework.Scenes | |||
2108 | { | 2311 | { |
2109 | if (IsDeleted) | 2312 | if (IsDeleted) |
2110 | return; | 2313 | return; |
2111 | 2314 | ||
2112 | lock (m_parts) | 2315 | lockPartsForRead(true); |
2113 | { | 2316 | { |
2114 | foreach (SceneObjectPart part in m_parts.Values) | 2317 | foreach (SceneObjectPart part in m_parts.Values) |
2115 | { | 2318 | { |
2116 | part.SendTerseUpdateToAllClients(); | 2319 | part.SendTerseUpdateToAllClients(); |
2117 | } | 2320 | } |
2118 | } | 2321 | } |
2322 | lockPartsForRead(false); | ||
2119 | } | 2323 | } |
2120 | 2324 | ||
2121 | #endregion | 2325 | #endregion |
@@ -2129,16 +2333,18 @@ namespace OpenSim.Region.Framework.Scenes | |||
2129 | /// <returns>null if no child part with that linknum or child part</returns> | 2333 | /// <returns>null if no child part with that linknum or child part</returns> |
2130 | public SceneObjectPart GetLinkNumPart(int linknum) | 2334 | public SceneObjectPart GetLinkNumPart(int linknum) |
2131 | { | 2335 | { |
2132 | lock (m_parts) | 2336 | lockPartsForRead(true); |
2133 | { | 2337 | { |
2134 | foreach (SceneObjectPart part in m_parts.Values) | 2338 | foreach (SceneObjectPart part in m_parts.Values) |
2135 | { | 2339 | { |
2136 | if (part.LinkNum == linknum) | 2340 | if (part.LinkNum == linknum) |
2137 | { | 2341 | { |
2342 | lockPartsForRead(false); | ||
2138 | return part; | 2343 | return part; |
2139 | } | 2344 | } |
2140 | } | 2345 | } |
2141 | } | 2346 | } |
2347 | lockPartsForRead(false); | ||
2142 | 2348 | ||
2143 | return null; | 2349 | return null; |
2144 | } | 2350 | } |
@@ -2166,17 +2372,19 @@ namespace OpenSim.Region.Framework.Scenes | |||
2166 | public SceneObjectPart GetChildPart(uint localID) | 2372 | public SceneObjectPart GetChildPart(uint localID) |
2167 | { | 2373 | { |
2168 | //m_log.DebugFormat("Entered looking for {0}", localID); | 2374 | //m_log.DebugFormat("Entered looking for {0}", localID); |
2169 | lock (m_parts) | 2375 | lockPartsForRead(true); |
2170 | { | 2376 | { |
2171 | foreach (SceneObjectPart part in m_parts.Values) | 2377 | foreach (SceneObjectPart part in m_parts.Values) |
2172 | { | 2378 | { |
2173 | //m_log.DebugFormat("Found {0}", part.LocalId); | 2379 | //m_log.DebugFormat("Found {0}", part.LocalId); |
2174 | if (part.LocalId == localID) | 2380 | if (part.LocalId == localID) |
2175 | { | 2381 | { |
2382 | lockPartsForRead(false); | ||
2176 | return part; | 2383 | return part; |
2177 | } | 2384 | } |
2178 | } | 2385 | } |
2179 | } | 2386 | } |
2387 | lockPartsForRead(false); | ||
2180 | 2388 | ||
2181 | return null; | 2389 | return null; |
2182 | } | 2390 | } |
@@ -2206,17 +2414,19 @@ namespace OpenSim.Region.Framework.Scenes | |||
2206 | public bool HasChildPrim(uint localID) | 2414 | public bool HasChildPrim(uint localID) |
2207 | { | 2415 | { |
2208 | //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID); | 2416 | //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID); |
2209 | lock (m_parts) | 2417 | lockPartsForRead(true); |
2210 | { | 2418 | { |
2211 | foreach (SceneObjectPart part in m_parts.Values) | 2419 | foreach (SceneObjectPart part in m_parts.Values) |
2212 | { | 2420 | { |
2213 | //m_log.DebugFormat("Found {0}", part.LocalId); | 2421 | //m_log.DebugFormat("Found {0}", part.LocalId); |
2214 | if (part.LocalId == localID) | 2422 | if (part.LocalId == localID) |
2215 | { | 2423 | { |
2424 | lockPartsForRead(false); | ||
2216 | return true; | 2425 | return true; |
2217 | } | 2426 | } |
2218 | } | 2427 | } |
2219 | } | 2428 | } |
2429 | lockPartsForRead(false); | ||
2220 | 2430 | ||
2221 | return false; | 2431 | return false; |
2222 | } | 2432 | } |
@@ -2266,53 +2476,57 @@ namespace OpenSim.Region.Framework.Scenes | |||
2266 | if (m_rootPart.LinkNum == 0) | 2476 | if (m_rootPart.LinkNum == 0) |
2267 | m_rootPart.LinkNum = 1; | 2477 | m_rootPart.LinkNum = 1; |
2268 | 2478 | ||
2269 | lock (m_parts) | 2479 | lockPartsForWrite(true); |
2270 | { | 2480 | |
2271 | m_parts.Add(linkPart.UUID, linkPart); | 2481 | m_parts.Add(linkPart.UUID, linkPart); |
2482 | |||
2483 | lockPartsForWrite(false); | ||
2272 | 2484 | ||
2273 | // Insert in terms of link numbers, the new links | 2485 | // Insert in terms of link numbers, the new links |
2274 | // before the current ones (with the exception of | 2486 | // before the current ones (with the exception of |
2275 | // the root prim. Shuffle the old ones up | 2487 | // the root prim. Shuffle the old ones up |
2276 | foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts) | 2488 | lockPartsForRead(true); |
2489 | foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts) | ||
2490 | { | ||
2491 | if (kvp.Value.LinkNum != 1) | ||
2277 | { | 2492 | { |
2278 | if (kvp.Value.LinkNum != 1) | 2493 | // Don't update root prim link number |
2279 | { | 2494 | kvp.Value.LinkNum += objectGroup.PrimCount; |
2280 | // Don't update root prim link number | ||
2281 | kvp.Value.LinkNum += objectGroup.PrimCount; | ||
2282 | } | ||
2283 | } | 2495 | } |
2496 | } | ||
2497 | lockPartsForRead(false); | ||
2284 | 2498 | ||
2285 | linkPart.LinkNum = 2; | 2499 | linkPart.LinkNum = 2; |
2286 | 2500 | ||
2287 | linkPart.SetParent(this); | 2501 | linkPart.SetParent(this); |
2288 | linkPart.AddFlag(PrimFlags.CreateSelected); | 2502 | linkPart.AddFlag(PrimFlags.CreateSelected); |
2289 | 2503 | ||
2290 | //if (linkPart.PhysActor != null) | 2504 | //if (linkPart.PhysActor != null) |
2291 | //{ | 2505 | //{ |
2292 | // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); | 2506 | // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); |
2293 | 2507 | ||
2294 | //linkPart.PhysActor = null; | 2508 | //linkPart.PhysActor = null; |
2295 | //} | 2509 | //} |
2296 | 2510 | ||
2297 | //TODO: rest of parts | 2511 | //TODO: rest of parts |
2298 | int linkNum = 3; | 2512 | int linkNum = 3; |
2299 | foreach (SceneObjectPart part in objectGroup.Children.Values) | 2513 | foreach (SceneObjectPart part in objectGroup.Children.Values) |
2514 | { | ||
2515 | if (part.UUID != objectGroup.m_rootPart.UUID) | ||
2300 | { | 2516 | { |
2301 | if (part.UUID != objectGroup.m_rootPart.UUID) | 2517 | LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++); |
2302 | { | ||
2303 | LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++); | ||
2304 | } | ||
2305 | part.ClearUndoState(); | ||
2306 | } | 2518 | } |
2519 | part.ClearUndoState(); | ||
2307 | } | 2520 | } |
2308 | 2521 | ||
2309 | m_scene.UnlinkSceneObject(objectGroup.UUID, true); | 2522 | m_scene.UnlinkSceneObject(objectGroup.UUID, true); |
2310 | objectGroup.m_isDeleted = true; | 2523 | objectGroup.m_isDeleted = true; |
2524 | |||
2525 | objectGroup.lockPartsForWrite(true); | ||
2311 | 2526 | ||
2312 | lock (objectGroup.m_parts) | 2527 | objectGroup.m_parts.Clear(); |
2313 | { | 2528 | |
2314 | objectGroup.m_parts.Clear(); | 2529 | objectGroup.lockPartsForWrite(false); |
2315 | } | ||
2316 | 2530 | ||
2317 | // Can't do this yet since backup still makes use of the root part without any synchronization | 2531 | // Can't do this yet since backup still makes use of the root part without any synchronization |
2318 | // objectGroup.m_rootPart = null; | 2532 | // objectGroup.m_rootPart = null; |
@@ -2382,11 +2596,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
2382 | Quaternion worldRot = linkPart.GetWorldRotation(); | 2596 | Quaternion worldRot = linkPart.GetWorldRotation(); |
2383 | 2597 | ||
2384 | // Remove the part from this object | 2598 | // Remove the part from this object |
2385 | lock (m_parts) | 2599 | lockPartsForWrite(true); |
2386 | { | 2600 | { |
2387 | m_parts.Remove(linkPart.UUID); | 2601 | m_parts.Remove(linkPart.UUID); |
2388 | } | 2602 | } |
2389 | 2603 | lockPartsForWrite(false); | |
2604 | lockPartsForRead(true); | ||
2390 | if (m_parts.Count == 1 && RootPart != null) //Single prim is left | 2605 | if (m_parts.Count == 1 && RootPart != null) //Single prim is left |
2391 | RootPart.LinkNum = 0; | 2606 | RootPart.LinkNum = 0; |
2392 | else | 2607 | else |
@@ -2397,6 +2612,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2397 | p.LinkNum--; | 2612 | p.LinkNum--; |
2398 | } | 2613 | } |
2399 | } | 2614 | } |
2615 | lockPartsForRead(false); | ||
2400 | 2616 | ||
2401 | linkPart.ParentID = 0; | 2617 | linkPart.ParentID = 0; |
2402 | linkPart.LinkNum = 0; | 2618 | linkPart.LinkNum = 0; |
@@ -2718,9 +2934,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
2718 | 2934 | ||
2719 | if (selectionPart != null) | 2935 | if (selectionPart != null) |
2720 | { | 2936 | { |
2721 | lock (m_parts) | 2937 | lockPartsForRead(true); |
2938 | List<SceneObjectPart> parts = new List<SceneObjectPart>(m_parts.Values); | ||
2939 | lockPartsForRead(false); | ||
2940 | foreach (SceneObjectPart part in parts) | ||
2722 | { | 2941 | { |
2723 | foreach (SceneObjectPart part in m_parts.Values) | 2942 | if (part.Scale.X > 10.0 || part.Scale.Y > 10.0 || part.Scale.Z > 10.0) |
2724 | { | 2943 | { |
2725 | if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax || | 2944 | if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax || |
2726 | part.Scale.Y > m_scene.RegionInfo.PhysPrimMax || | 2945 | part.Scale.Y > m_scene.RegionInfo.PhysPrimMax || |
@@ -2730,12 +2949,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
2730 | break; | 2949 | break; |
2731 | } | 2950 | } |
2732 | } | 2951 | } |
2952 | } | ||
2733 | 2953 | ||
2734 | foreach (SceneObjectPart part in m_parts.Values) | 2954 | foreach (SceneObjectPart part in parts) |
2735 | { | 2955 | { |
2736 | part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect); | 2956 | part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect); |
2737 | } | ||
2738 | } | 2957 | } |
2958 | |||
2739 | } | 2959 | } |
2740 | } | 2960 | } |
2741 | 2961 | ||
@@ -2821,11 +3041,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
2821 | scale.Y = m_scene.m_maxNonphys; | 3041 | scale.Y = m_scene.m_maxNonphys; |
2822 | if (scale.Z > m_scene.m_maxNonphys) | 3042 | if (scale.Z > m_scene.m_maxNonphys) |
2823 | scale.Z = m_scene.m_maxNonphys; | 3043 | scale.Z = m_scene.m_maxNonphys; |
2824 | |||
2825 | SceneObjectPart part = GetChildPart(localID); | 3044 | SceneObjectPart part = GetChildPart(localID); |
2826 | if (part != null) | 3045 | if (part != null) |
2827 | { | 3046 | { |
2828 | part.Resize(scale); | ||
2829 | if (part.PhysActor != null) | 3047 | if (part.PhysActor != null) |
2830 | { | 3048 | { |
2831 | if (part.PhysActor.IsPhysical) | 3049 | if (part.PhysActor.IsPhysical) |
@@ -2840,7 +3058,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2840 | part.PhysActor.Size = scale; | 3058 | part.PhysActor.Size = scale; |
2841 | m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); | 3059 | m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); |
2842 | } | 3060 | } |
2843 | //if (part.UUID != m_rootPart.UUID) | 3061 | part.Resize(scale); |
2844 | 3062 | ||
2845 | HasGroupChanged = true; | 3063 | HasGroupChanged = true; |
2846 | ScheduleGroupForFullUpdate(); | 3064 | ScheduleGroupForFullUpdate(); |
@@ -2882,73 +3100,71 @@ namespace OpenSim.Region.Framework.Scenes | |||
2882 | float y = (scale.Y / part.Scale.Y); | 3100 | float y = (scale.Y / part.Scale.Y); |
2883 | float z = (scale.Z / part.Scale.Z); | 3101 | float z = (scale.Z / part.Scale.Z); |
2884 | 3102 | ||
2885 | lock (m_parts) | 3103 | lockPartsForRead(true); |
3104 | if (x > 1.0f || y > 1.0f || z > 1.0f) | ||
2886 | { | 3105 | { |
2887 | if (x > 1.0f || y > 1.0f || z > 1.0f) | 3106 | foreach (SceneObjectPart obPart in m_parts.Values) |
2888 | { | 3107 | { |
2889 | foreach (SceneObjectPart obPart in m_parts.Values) | 3108 | if (obPart.UUID != m_rootPart.UUID) |
2890 | { | 3109 | { |
2891 | if (obPart.UUID != m_rootPart.UUID) | 3110 | obPart.IgnoreUndoUpdate = true; |
2892 | { | 3111 | Vector3 oldSize = new Vector3(obPart.Scale); |
2893 | obPart.IgnoreUndoUpdate = true; | ||
2894 | Vector3 oldSize = new Vector3(obPart.Scale); | ||
2895 | 3112 | ||
2896 | float f = 1.0f; | 3113 | float f = 1.0f; |
2897 | float a = 1.0f; | 3114 | float a = 1.0f; |
2898 | 3115 | ||
2899 | if (part.PhysActor != null && part.PhysActor.IsPhysical) | 3116 | if (part.PhysActor != null && part.PhysActor.IsPhysical) |
3117 | { | ||
3118 | if (oldSize.X*x > m_scene.m_maxPhys) | ||
2900 | { | 3119 | { |
2901 | if (oldSize.X*x > m_scene.m_maxPhys) | 3120 | f = m_scene.m_maxPhys / oldSize.X; |
2902 | { | 3121 | a = f / x; |
2903 | f = m_scene.m_maxPhys / oldSize.X; | 3122 | x *= a; |
2904 | a = f / x; | 3123 | y *= a; |
2905 | x *= a; | 3124 | z *= a; |
2906 | y *= a; | ||
2907 | z *= a; | ||
2908 | } | ||
2909 | if (oldSize.Y*y > m_scene.m_maxPhys) | ||
2910 | { | ||
2911 | f = m_scene.m_maxPhys / oldSize.Y; | ||
2912 | a = f / y; | ||
2913 | x *= a; | ||
2914 | y *= a; | ||
2915 | z *= a; | ||
2916 | } | ||
2917 | if (oldSize.Z*z > m_scene.m_maxPhys) | ||
2918 | { | ||
2919 | f = m_scene.m_maxPhys / oldSize.Z; | ||
2920 | a = f / z; | ||
2921 | x *= a; | ||
2922 | y *= a; | ||
2923 | z *= a; | ||
2924 | } | ||
2925 | } | 3125 | } |
2926 | else | 3126 | if (oldSize.Y*y > m_scene.m_maxPhys) |
2927 | { | 3127 | { |
2928 | if (oldSize.X*x > m_scene.m_maxNonphys) | 3128 | f = m_scene.m_maxPhys / oldSize.Y; |
2929 | { | 3129 | a = f / y; |
2930 | f = m_scene.m_maxNonphys / oldSize.X; | 3130 | x *= a; |
2931 | a = f / x; | 3131 | y *= a; |
2932 | x *= a; | 3132 | z *= a; |
2933 | y *= a; | 3133 | } |
2934 | z *= a; | 3134 | if (oldSize.Z*z > m_scene.m_maxPhys) |
2935 | } | 3135 | { |
2936 | if (oldSize.Y*y > m_scene.m_maxNonphys) | 3136 | f = m_scene.m_maxPhys / oldSize.Z; |
2937 | { | 3137 | a = f / z; |
2938 | f = m_scene.m_maxNonphys / oldSize.Y; | 3138 | x *= a; |
2939 | a = f / y; | 3139 | y *= a; |
2940 | x *= a; | 3140 | z *= a; |
2941 | y *= a; | 3141 | } |
2942 | z *= a; | 3142 | } |
2943 | } | 3143 | else |
2944 | if (oldSize.Z*z > m_scene.m_maxNonphys) | 3144 | { |
2945 | { | 3145 | if (oldSize.X*x > m_scene.m_maxNonphys) |
2946 | f = m_scene.m_maxNonphys / oldSize.Z; | 3146 | { |
2947 | a = f / z; | 3147 | f = m_scene.m_maxNonphys / oldSize.X; |
2948 | x *= a; | 3148 | a = f / x; |
2949 | y *= a; | 3149 | x *= a; |
2950 | z *= a; | 3150 | y *= a; |
2951 | } | 3151 | z *= a; |
3152 | } | ||
3153 | if (oldSize.Y*y > m_scene.m_maxNonphys) | ||
3154 | { | ||
3155 | f = m_scene.m_maxNonphys / oldSize.Y; | ||
3156 | a = f / y; | ||
3157 | x *= a; | ||
3158 | y *= a; | ||
3159 | z *= a; | ||
3160 | } | ||
3161 | if (oldSize.Z*z > m_scene.m_maxNonphys) | ||
3162 | { | ||
3163 | f = m_scene.m_maxNonphys / oldSize.Z; | ||
3164 | a = f / z; | ||
3165 | x *= a; | ||
3166 | y *= a; | ||
3167 | z *= a; | ||
2952 | } | 3168 | } |
2953 | obPart.IgnoreUndoUpdate = false; | 3169 | obPart.IgnoreUndoUpdate = false; |
2954 | obPart.StoreUndoState(); | 3170 | obPart.StoreUndoState(); |
@@ -2956,6 +3172,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2956 | } | 3172 | } |
2957 | } | 3173 | } |
2958 | } | 3174 | } |
3175 | lockPartsForRead(false); | ||
2959 | 3176 | ||
2960 | Vector3 prevScale = part.Scale; | 3177 | Vector3 prevScale = part.Scale; |
2961 | prevScale.X *= x; | 3178 | prevScale.X *= x; |
@@ -2963,7 +3180,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2963 | prevScale.Z *= z; | 3180 | prevScale.Z *= z; |
2964 | part.Resize(prevScale); | 3181 | part.Resize(prevScale); |
2965 | 3182 | ||
2966 | lock (m_parts) | 3183 | lockPartsForRead(true); |
2967 | { | 3184 | { |
2968 | foreach (SceneObjectPart obPart in m_parts.Values) | 3185 | foreach (SceneObjectPart obPart in m_parts.Values) |
2969 | { | 3186 | { |
@@ -2985,6 +3202,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2985 | obPart.StoreUndoState(); | 3202 | obPart.StoreUndoState(); |
2986 | } | 3203 | } |
2987 | } | 3204 | } |
3205 | lockPartsForRead(false); | ||
2988 | 3206 | ||
2989 | if (part.PhysActor != null) | 3207 | if (part.PhysActor != null) |
2990 | { | 3208 | { |
@@ -3087,7 +3305,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3087 | axDiff *= Quaternion.Inverse(partRotation); | 3305 | axDiff *= Quaternion.Inverse(partRotation); |
3088 | diff = axDiff; | 3306 | diff = axDiff; |
3089 | 3307 | ||
3090 | lock (m_parts) | 3308 | lockPartsForRead(true); |
3091 | { | 3309 | { |
3092 | foreach (SceneObjectPart obPart in m_parts.Values) | 3310 | foreach (SceneObjectPart obPart in m_parts.Values) |
3093 | { | 3311 | { |
@@ -3097,6 +3315,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3097 | } | 3315 | } |
3098 | } | 3316 | } |
3099 | } | 3317 | } |
3318 | lockPartsForRead(false); | ||
3100 | 3319 | ||
3101 | AbsolutePosition = newPos; | 3320 | AbsolutePosition = newPos; |
3102 | 3321 | ||
@@ -3230,25 +3449,25 @@ namespace OpenSim.Region.Framework.Scenes | |||
3230 | m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); | 3449 | m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); |
3231 | } | 3450 | } |
3232 | 3451 | ||
3233 | lock (m_parts) | 3452 | lockPartsForRead(true); |
3453 | |||
3454 | foreach (SceneObjectPart prim in m_parts.Values) | ||
3234 | { | 3455 | { |
3235 | foreach (SceneObjectPart prim in m_parts.Values) | 3456 | if (prim.UUID != m_rootPart.UUID) |
3236 | { | 3457 | { |
3237 | if (prim.UUID != m_rootPart.UUID) | 3458 | prim.IgnoreUndoUpdate = true; |
3238 | { | 3459 | Vector3 axPos = prim.OffsetPosition; |
3239 | prim.IgnoreUndoUpdate = true; | 3460 | axPos *= oldParentRot; |
3240 | Vector3 axPos = prim.OffsetPosition; | 3461 | axPos *= Quaternion.Inverse(axRot); |
3241 | axPos *= oldParentRot; | 3462 | prim.OffsetPosition = axPos; |
3242 | axPos *= Quaternion.Inverse(axRot); | 3463 | Quaternion primsRot = prim.RotationOffset; |
3243 | prim.OffsetPosition = axPos; | 3464 | Quaternion newRot = primsRot * oldParentRot; |
3244 | Quaternion primsRot = prim.RotationOffset; | 3465 | newRot *= Quaternion.Inverse(axRot); |
3245 | Quaternion newRot = primsRot * oldParentRot; | 3466 | prim.RotationOffset = newRot; |
3246 | newRot *= Quaternion.Inverse(axRot); | 3467 | prim.ScheduleTerseUpdate(); |
3247 | prim.RotationOffset = newRot; | ||
3248 | prim.ScheduleTerseUpdate(); | ||
3249 | } | ||
3250 | } | 3468 | } |
3251 | } | 3469 | } |
3470 | |||
3252 | foreach (SceneObjectPart childpart in Children.Values) | 3471 | foreach (SceneObjectPart childpart in Children.Values) |
3253 | { | 3472 | { |
3254 | if (childpart != m_rootPart) | 3473 | if (childpart != m_rootPart) |
@@ -3257,6 +3476,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
3257 | childpart.StoreUndoState(); | 3476 | childpart.StoreUndoState(); |
3258 | } | 3477 | } |
3259 | } | 3478 | } |
3479 | |||
3480 | lockPartsForRead(false); | ||
3481 | |||
3260 | m_rootPart.ScheduleTerseUpdate(); | 3482 | m_rootPart.ScheduleTerseUpdate(); |
3261 | } | 3483 | } |
3262 | 3484 | ||
@@ -3378,7 +3600,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3378 | if (atTargets.Count > 0) | 3600 | if (atTargets.Count > 0) |
3379 | { | 3601 | { |
3380 | uint[] localids = new uint[0]; | 3602 | uint[] localids = new uint[0]; |
3381 | lock (m_parts) | 3603 | lockPartsForRead(true); |
3382 | { | 3604 | { |
3383 | localids = new uint[m_parts.Count]; | 3605 | localids = new uint[m_parts.Count]; |
3384 | int cntr = 0; | 3606 | int cntr = 0; |
@@ -3388,6 +3610,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3388 | cntr++; | 3610 | cntr++; |
3389 | } | 3611 | } |
3390 | } | 3612 | } |
3613 | lockPartsForRead(false); | ||
3391 | 3614 | ||
3392 | for (int ctr = 0; ctr < localids.Length; ctr++) | 3615 | for (int ctr = 0; ctr < localids.Length; ctr++) |
3393 | { | 3616 | { |
@@ -3406,7 +3629,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3406 | { | 3629 | { |
3407 | //trigger not_at_target | 3630 | //trigger not_at_target |
3408 | uint[] localids = new uint[0]; | 3631 | uint[] localids = new uint[0]; |
3409 | lock (m_parts) | 3632 | lockPartsForRead(true); |
3410 | { | 3633 | { |
3411 | localids = new uint[m_parts.Count]; | 3634 | localids = new uint[m_parts.Count]; |
3412 | int cntr = 0; | 3635 | int cntr = 0; |
@@ -3416,7 +3639,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
3416 | cntr++; | 3639 | cntr++; |
3417 | } | 3640 | } |
3418 | } | 3641 | } |
3419 | 3642 | lockPartsForRead(false); | |
3643 | |||
3420 | for (int ctr = 0; ctr < localids.Length; ctr++) | 3644 | for (int ctr = 0; ctr < localids.Length; ctr++) |
3421 | { | 3645 | { |
3422 | m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]); | 3646 | m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]); |
@@ -3508,19 +3732,20 @@ namespace OpenSim.Region.Framework.Scenes | |||
3508 | public float GetMass() | 3732 | public float GetMass() |
3509 | { | 3733 | { |
3510 | float retmass = 0f; | 3734 | float retmass = 0f; |
3511 | lock (m_parts) | 3735 | lockPartsForRead(true); |
3512 | { | 3736 | { |
3513 | foreach (SceneObjectPart part in m_parts.Values) | 3737 | foreach (SceneObjectPart part in m_parts.Values) |
3514 | { | 3738 | { |
3515 | retmass += part.GetMass(); | 3739 | retmass += part.GetMass(); |
3516 | } | 3740 | } |
3517 | } | 3741 | } |
3742 | lockPartsForRead(false); | ||
3518 | return retmass; | 3743 | return retmass; |
3519 | } | 3744 | } |
3520 | 3745 | ||
3521 | public void CheckSculptAndLoad() | 3746 | public void CheckSculptAndLoad() |
3522 | { | 3747 | { |
3523 | lock (m_parts) | 3748 | lockPartsForRead(true); |
3524 | { | 3749 | { |
3525 | if (!IsDeleted) | 3750 | if (!IsDeleted) |
3526 | { | 3751 | { |
@@ -3545,6 +3770,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3545 | } | 3770 | } |
3546 | } | 3771 | } |
3547 | } | 3772 | } |
3773 | lockPartsForRead(false); | ||
3548 | } | 3774 | } |
3549 | 3775 | ||
3550 | protected void AssetReceived(string id, Object sender, AssetBase asset) | 3776 | protected void AssetReceived(string id, Object sender, AssetBase asset) |
@@ -3565,7 +3791,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3565 | /// <param name="client"></param> | 3791 | /// <param name="client"></param> |
3566 | public void SetGroup(UUID GroupID, IClientAPI client) | 3792 | public void SetGroup(UUID GroupID, IClientAPI client) |
3567 | { | 3793 | { |
3568 | lock (m_parts) | 3794 | lockPartsForRead(true); |
3569 | { | 3795 | { |
3570 | foreach (SceneObjectPart part in m_parts.Values) | 3796 | foreach (SceneObjectPart part in m_parts.Values) |
3571 | { | 3797 | { |
@@ -3575,6 +3801,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3575 | 3801 | ||
3576 | HasGroupChanged = true; | 3802 | HasGroupChanged = true; |
3577 | } | 3803 | } |
3804 | lockPartsForRead(false); | ||
3578 | 3805 | ||
3579 | // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled | 3806 | // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled |
3580 | // for the same object with very different properties. The caller must schedule the update. | 3807 | // for the same object with very different properties. The caller must schedule the update. |
@@ -3596,11 +3823,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
3596 | 3823 | ||
3597 | public void SetAttachmentPoint(byte point) | 3824 | public void SetAttachmentPoint(byte point) |
3598 | { | 3825 | { |
3599 | lock (m_parts) | 3826 | lockPartsForRead(true); |
3600 | { | 3827 | { |
3601 | foreach (SceneObjectPart part in m_parts.Values) | 3828 | foreach (SceneObjectPart part in m_parts.Values) |
3602 | part.SetAttachmentPoint(point); | 3829 | part.SetAttachmentPoint(point); |
3603 | } | 3830 | } |
3831 | lockPartsForRead(false); | ||
3604 | } | 3832 | } |
3605 | 3833 | ||
3606 | #region ISceneObject | 3834 | #region ISceneObject |