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 aa41354..54b27b2 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 | ||
@@ -1500,14 +1657,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
1500 | 1657 | ||
1501 | SendPartFullUpdate(remoteClient, RootPart, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID)); | 1658 | SendPartFullUpdate(remoteClient, RootPart, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID)); |
1502 | 1659 | ||
1503 | lock (m_parts) | 1660 | lockPartsForRead(true); |
1504 | { | 1661 | { |
1505 | foreach (SceneObjectPart part in m_parts.Values) | 1662 | foreach (SceneObjectPart part in m_parts.Values) |
1506 | { | 1663 | { |
1664 | |||
1507 | if (part != RootPart) | 1665 | if (part != RootPart) |
1508 | SendPartFullUpdate(remoteClient, part, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID)); | 1666 | SendPartFullUpdate(remoteClient, part, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID)); |
1667 | |||
1509 | } | 1668 | } |
1510 | } | 1669 | } |
1670 | lockPartsForRead(false); | ||
1511 | } | 1671 | } |
1512 | 1672 | ||
1513 | /// <summary> | 1673 | /// <summary> |
@@ -1606,10 +1766,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
1606 | 1766 | ||
1607 | List<SceneObjectPart> partList; | 1767 | List<SceneObjectPart> partList; |
1608 | 1768 | ||
1609 | lock (m_parts) | 1769 | lockPartsForRead(true); |
1610 | { | 1770 | |
1611 | partList = new List<SceneObjectPart>(m_parts.Values); | 1771 | partList = new List<SceneObjectPart>(m_parts.Values); |
1612 | } | 1772 | |
1773 | lockPartsForRead(false); | ||
1613 | 1774 | ||
1614 | partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) | 1775 | partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) |
1615 | { | 1776 | { |
@@ -1832,13 +1993,40 @@ namespace OpenSim.Region.Framework.Scenes | |||
1832 | } | 1993 | } |
1833 | } | 1994 | } |
1834 | 1995 | ||
1996 | public void rotLookAt(Quaternion target, float strength, float damping) | ||
1997 | { | ||
1998 | SceneObjectPart rootpart = m_rootPart; | ||
1999 | if (rootpart != null) | ||
2000 | { | ||
2001 | if (IsAttachment) | ||
2002 | { | ||
2003 | /* | ||
2004 | ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar); | ||
2005 | if (avatar != null) | ||
2006 | { | ||
2007 | Rotate the Av? | ||
2008 | } */ | ||
2009 | } | ||
2010 | else | ||
2011 | { | ||
2012 | if (rootpart.PhysActor != null) | ||
2013 | { // APID must be implemented in your physics system for this to function. | ||
2014 | rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W); | ||
2015 | rootpart.PhysActor.APIDStrength = strength; | ||
2016 | rootpart.PhysActor.APIDDamping = damping; | ||
2017 | rootpart.PhysActor.APIDActive = true; | ||
2018 | } | ||
2019 | } | ||
2020 | } | ||
2021 | } | ||
2022 | |||
1835 | public void stopLookAt() | 2023 | public void stopLookAt() |
1836 | { | 2024 | { |
1837 | SceneObjectPart rootpart = m_rootPart; | 2025 | SceneObjectPart rootpart = m_rootPart; |
1838 | if (rootpart != null) | 2026 | if (rootpart != null) |
1839 | { | 2027 | { |
1840 | if (rootpart.PhysActor != null) | 2028 | if (rootpart.PhysActor != null) |
1841 | { | 2029 | { // APID must be implemented in your physics system for this to function. |
1842 | rootpart.PhysActor.APIDActive = false; | 2030 | rootpart.PhysActor.APIDActive = false; |
1843 | } | 2031 | } |
1844 | } | 2032 | } |
@@ -1906,10 +2094,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
1906 | SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); | 2094 | SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); |
1907 | newPart.SetParent(this); | 2095 | newPart.SetParent(this); |
1908 | 2096 | ||
1909 | lock (m_parts) | 2097 | lockPartsForWrite(true); |
1910 | { | 2098 | { |
1911 | m_parts.Add(newPart.UUID, newPart); | 2099 | m_parts.Add(newPart.UUID, newPart); |
1912 | } | 2100 | } |
2101 | lockPartsForWrite(false); | ||
1913 | 2102 | ||
1914 | SetPartAsNonRoot(newPart); | 2103 | SetPartAsNonRoot(newPart); |
1915 | 2104 | ||
@@ -1972,7 +2161,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1972 | //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0) | 2161 | //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0) |
1973 | // return; | 2162 | // return; |
1974 | 2163 | ||
1975 | lock (m_parts) | 2164 | lockPartsForRead(true); |
1976 | { | 2165 | { |
1977 | bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0); | 2166 | bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0); |
1978 | 2167 | ||
@@ -1992,9 +2181,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
1992 | { | 2181 | { |
1993 | if (!IsSelected) | 2182 | if (!IsSelected) |
1994 | part.UpdateLookAt(); | 2183 | part.UpdateLookAt(); |
2184 | |||
1995 | part.SendScheduledUpdates(); | 2185 | part.SendScheduledUpdates(); |
2186 | |||
1996 | } | 2187 | } |
1997 | } | 2188 | } |
2189 | lockPartsForRead(false); | ||
1998 | } | 2190 | } |
1999 | 2191 | ||
2000 | public void ScheduleFullUpdateToAvatar(ScenePresence presence) | 2192 | public void ScheduleFullUpdateToAvatar(ScenePresence presence) |
@@ -2004,27 +2196,31 @@ namespace OpenSim.Region.Framework.Scenes | |||
2004 | 2196 | ||
2005 | RootPart.AddFullUpdateToAvatar(presence); | 2197 | RootPart.AddFullUpdateToAvatar(presence); |
2006 | 2198 | ||
2007 | lock (m_parts) | 2199 | lockPartsForRead(true); |
2008 | { | 2200 | { |
2009 | foreach (SceneObjectPart part in m_parts.Values) | 2201 | foreach (SceneObjectPart part in m_parts.Values) |
2010 | { | 2202 | { |
2203 | |||
2011 | if (part != RootPart) | 2204 | if (part != RootPart) |
2012 | part.AddFullUpdateToAvatar(presence); | 2205 | part.AddFullUpdateToAvatar(presence); |
2206 | |||
2013 | } | 2207 | } |
2014 | } | 2208 | } |
2209 | lockPartsForRead(false); | ||
2015 | } | 2210 | } |
2016 | 2211 | ||
2017 | public void ScheduleTerseUpdateToAvatar(ScenePresence presence) | 2212 | public void ScheduleTerseUpdateToAvatar(ScenePresence presence) |
2018 | { | 2213 | { |
2019 | // m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1} just to avatar {2}", Name, UUID, presence.Name); | 2214 | lockPartsForRead(true); |
2020 | |||
2021 | lock (m_parts) | ||
2022 | { | 2215 | { |
2023 | foreach (SceneObjectPart part in m_parts.Values) | 2216 | foreach (SceneObjectPart part in m_parts.Values) |
2024 | { | 2217 | { |
2218 | |||
2025 | part.AddTerseUpdateToAvatar(presence); | 2219 | part.AddTerseUpdateToAvatar(presence); |
2220 | |||
2026 | } | 2221 | } |
2027 | } | 2222 | } |
2223 | lockPartsForRead(false); | ||
2028 | } | 2224 | } |
2029 | 2225 | ||
2030 | /// <summary> | 2226 | /// <summary> |
@@ -2038,14 +2234,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
2038 | checkAtTargets(); | 2234 | checkAtTargets(); |
2039 | RootPart.ScheduleFullUpdate(); | 2235 | RootPart.ScheduleFullUpdate(); |
2040 | 2236 | ||
2041 | lock (m_parts) | 2237 | lockPartsForRead(true); |
2042 | { | 2238 | { |
2043 | foreach (SceneObjectPart part in m_parts.Values) | 2239 | foreach (SceneObjectPart part in m_parts.Values) |
2044 | { | 2240 | { |
2241 | |||
2045 | if (part != RootPart) | 2242 | if (part != RootPart) |
2046 | part.ScheduleFullUpdate(); | 2243 | part.ScheduleFullUpdate(); |
2244 | |||
2047 | } | 2245 | } |
2048 | } | 2246 | } |
2247 | lockPartsForRead(false); | ||
2049 | } | 2248 | } |
2050 | 2249 | ||
2051 | /// <summary> | 2250 | /// <summary> |
@@ -2053,15 +2252,16 @@ namespace OpenSim.Region.Framework.Scenes | |||
2053 | /// </summary> | 2252 | /// </summary> |
2054 | public void ScheduleGroupForTerseUpdate() | 2253 | public void ScheduleGroupForTerseUpdate() |
2055 | { | 2254 | { |
2056 | // m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1}", Name, UUID); | 2255 | lockPartsForRead(true); |
2057 | |||
2058 | lock (m_parts) | ||
2059 | { | 2256 | { |
2060 | foreach (SceneObjectPart part in m_parts.Values) | 2257 | foreach (SceneObjectPart part in m_parts.Values) |
2061 | { | 2258 | { |
2259 | |||
2062 | part.ScheduleTerseUpdate(); | 2260 | part.ScheduleTerseUpdate(); |
2261 | |||
2063 | } | 2262 | } |
2064 | } | 2263 | } |
2264 | lockPartsForRead(false); | ||
2065 | } | 2265 | } |
2066 | 2266 | ||
2067 | /// <summary> | 2267 | /// <summary> |
@@ -2076,14 +2276,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
2076 | 2276 | ||
2077 | RootPart.SendFullUpdateToAllClients(); | 2277 | RootPart.SendFullUpdateToAllClients(); |
2078 | 2278 | ||
2079 | lock (m_parts) | 2279 | lockPartsForRead(true); |
2080 | { | 2280 | { |
2081 | foreach (SceneObjectPart part in m_parts.Values) | 2281 | foreach (SceneObjectPart part in m_parts.Values) |
2082 | { | 2282 | { |
2283 | |||
2083 | if (part != RootPart) | 2284 | if (part != RootPart) |
2084 | part.SendFullUpdateToAllClients(); | 2285 | part.SendFullUpdateToAllClients(); |
2286 | |||
2085 | } | 2287 | } |
2086 | } | 2288 | } |
2289 | lockPartsForRead(false); | ||
2087 | } | 2290 | } |
2088 | 2291 | ||
2089 | /// <summary> | 2292 | /// <summary> |
@@ -2115,14 +2318,15 @@ namespace OpenSim.Region.Framework.Scenes | |||
2115 | { | 2318 | { |
2116 | if (IsDeleted) | 2319 | if (IsDeleted) |
2117 | return; | 2320 | return; |
2118 | 2321 | ||
2119 | lock (m_parts) | 2322 | lockPartsForRead(true); |
2120 | { | 2323 | { |
2121 | foreach (SceneObjectPart part in m_parts.Values) | 2324 | foreach (SceneObjectPart part in m_parts.Values) |
2122 | { | 2325 | { |
2123 | part.SendTerseUpdateToAllClients(); | 2326 | part.SendTerseUpdateToAllClients(); |
2124 | } | 2327 | } |
2125 | } | 2328 | } |
2329 | lockPartsForRead(false); | ||
2126 | } | 2330 | } |
2127 | 2331 | ||
2128 | #endregion | 2332 | #endregion |
@@ -2136,16 +2340,18 @@ namespace OpenSim.Region.Framework.Scenes | |||
2136 | /// <returns>null if no child part with that linknum or child part</returns> | 2340 | /// <returns>null if no child part with that linknum or child part</returns> |
2137 | public SceneObjectPart GetLinkNumPart(int linknum) | 2341 | public SceneObjectPart GetLinkNumPart(int linknum) |
2138 | { | 2342 | { |
2139 | lock (m_parts) | 2343 | lockPartsForRead(true); |
2140 | { | 2344 | { |
2141 | foreach (SceneObjectPart part in m_parts.Values) | 2345 | foreach (SceneObjectPart part in m_parts.Values) |
2142 | { | 2346 | { |
2143 | if (part.LinkNum == linknum) | 2347 | if (part.LinkNum == linknum) |
2144 | { | 2348 | { |
2349 | lockPartsForRead(false); | ||
2145 | return part; | 2350 | return part; |
2146 | } | 2351 | } |
2147 | } | 2352 | } |
2148 | } | 2353 | } |
2354 | lockPartsForRead(false); | ||
2149 | 2355 | ||
2150 | return null; | 2356 | return null; |
2151 | } | 2357 | } |
@@ -2173,17 +2379,19 @@ namespace OpenSim.Region.Framework.Scenes | |||
2173 | public SceneObjectPart GetChildPart(uint localID) | 2379 | public SceneObjectPart GetChildPart(uint localID) |
2174 | { | 2380 | { |
2175 | //m_log.DebugFormat("Entered looking for {0}", localID); | 2381 | //m_log.DebugFormat("Entered looking for {0}", localID); |
2176 | lock (m_parts) | 2382 | lockPartsForRead(true); |
2177 | { | 2383 | { |
2178 | foreach (SceneObjectPart part in m_parts.Values) | 2384 | foreach (SceneObjectPart part in m_parts.Values) |
2179 | { | 2385 | { |
2180 | //m_log.DebugFormat("Found {0}", part.LocalId); | 2386 | //m_log.DebugFormat("Found {0}", part.LocalId); |
2181 | if (part.LocalId == localID) | 2387 | if (part.LocalId == localID) |
2182 | { | 2388 | { |
2389 | lockPartsForRead(false); | ||
2183 | return part; | 2390 | return part; |
2184 | } | 2391 | } |
2185 | } | 2392 | } |
2186 | } | 2393 | } |
2394 | lockPartsForRead(false); | ||
2187 | 2395 | ||
2188 | return null; | 2396 | return null; |
2189 | } | 2397 | } |
@@ -2213,17 +2421,19 @@ namespace OpenSim.Region.Framework.Scenes | |||
2213 | public bool HasChildPrim(uint localID) | 2421 | public bool HasChildPrim(uint localID) |
2214 | { | 2422 | { |
2215 | //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID); | 2423 | //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID); |
2216 | lock (m_parts) | 2424 | lockPartsForRead(true); |
2217 | { | 2425 | { |
2218 | foreach (SceneObjectPart part in m_parts.Values) | 2426 | foreach (SceneObjectPart part in m_parts.Values) |
2219 | { | 2427 | { |
2220 | //m_log.DebugFormat("Found {0}", part.LocalId); | 2428 | //m_log.DebugFormat("Found {0}", part.LocalId); |
2221 | if (part.LocalId == localID) | 2429 | if (part.LocalId == localID) |
2222 | { | 2430 | { |
2431 | lockPartsForRead(false); | ||
2223 | return true; | 2432 | return true; |
2224 | } | 2433 | } |
2225 | } | 2434 | } |
2226 | } | 2435 | } |
2436 | lockPartsForRead(false); | ||
2227 | 2437 | ||
2228 | return false; | 2438 | return false; |
2229 | } | 2439 | } |
@@ -2273,53 +2483,57 @@ namespace OpenSim.Region.Framework.Scenes | |||
2273 | if (m_rootPart.LinkNum == 0) | 2483 | if (m_rootPart.LinkNum == 0) |
2274 | m_rootPart.LinkNum = 1; | 2484 | m_rootPart.LinkNum = 1; |
2275 | 2485 | ||
2276 | lock (m_parts) | 2486 | lockPartsForWrite(true); |
2277 | { | 2487 | |
2278 | m_parts.Add(linkPart.UUID, linkPart); | 2488 | m_parts.Add(linkPart.UUID, linkPart); |
2489 | |||
2490 | lockPartsForWrite(false); | ||
2279 | 2491 | ||
2280 | // Insert in terms of link numbers, the new links | 2492 | // Insert in terms of link numbers, the new links |
2281 | // before the current ones (with the exception of | 2493 | // before the current ones (with the exception of |
2282 | // the root prim. Shuffle the old ones up | 2494 | // the root prim. Shuffle the old ones up |
2283 | foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts) | 2495 | lockPartsForRead(true); |
2496 | foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts) | ||
2497 | { | ||
2498 | if (kvp.Value.LinkNum != 1) | ||
2284 | { | 2499 | { |
2285 | if (kvp.Value.LinkNum != 1) | 2500 | // Don't update root prim link number |
2286 | { | 2501 | kvp.Value.LinkNum += objectGroup.PrimCount; |
2287 | // Don't update root prim link number | ||
2288 | kvp.Value.LinkNum += objectGroup.PrimCount; | ||
2289 | } | ||
2290 | } | 2502 | } |
2503 | } | ||
2504 | lockPartsForRead(false); | ||
2291 | 2505 | ||
2292 | linkPart.LinkNum = 2; | 2506 | linkPart.LinkNum = 2; |
2293 | 2507 | ||
2294 | linkPart.SetParent(this); | 2508 | linkPart.SetParent(this); |
2295 | linkPart.AddFlag(PrimFlags.CreateSelected); | 2509 | linkPart.AddFlag(PrimFlags.CreateSelected); |
2296 | 2510 | ||
2297 | //if (linkPart.PhysActor != null) | 2511 | //if (linkPart.PhysActor != null) |
2298 | //{ | 2512 | //{ |
2299 | // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); | 2513 | // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); |
2300 | 2514 | ||
2301 | //linkPart.PhysActor = null; | 2515 | //linkPart.PhysActor = null; |
2302 | //} | 2516 | //} |
2303 | 2517 | ||
2304 | //TODO: rest of parts | 2518 | //TODO: rest of parts |
2305 | int linkNum = 3; | 2519 | int linkNum = 3; |
2306 | foreach (SceneObjectPart part in objectGroup.Children.Values) | 2520 | foreach (SceneObjectPart part in objectGroup.Children.Values) |
2521 | { | ||
2522 | if (part.UUID != objectGroup.m_rootPart.UUID) | ||
2307 | { | 2523 | { |
2308 | if (part.UUID != objectGroup.m_rootPart.UUID) | 2524 | LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++); |
2309 | { | ||
2310 | LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++); | ||
2311 | } | ||
2312 | part.ClearUndoState(); | ||
2313 | } | 2525 | } |
2526 | part.ClearUndoState(); | ||
2314 | } | 2527 | } |
2315 | 2528 | ||
2316 | m_scene.UnlinkSceneObject(objectGroup.UUID, true); | 2529 | m_scene.UnlinkSceneObject(objectGroup.UUID, true); |
2317 | objectGroup.m_isDeleted = true; | 2530 | objectGroup.m_isDeleted = true; |
2531 | |||
2532 | objectGroup.lockPartsForWrite(true); | ||
2318 | 2533 | ||
2319 | lock (objectGroup.m_parts) | 2534 | objectGroup.m_parts.Clear(); |
2320 | { | 2535 | |
2321 | objectGroup.m_parts.Clear(); | 2536 | objectGroup.lockPartsForWrite(false); |
2322 | } | ||
2323 | 2537 | ||
2324 | // Can't do this yet since backup still makes use of the root part without any synchronization | 2538 | // Can't do this yet since backup still makes use of the root part without any synchronization |
2325 | // objectGroup.m_rootPart = null; | 2539 | // objectGroup.m_rootPart = null; |
@@ -2389,11 +2603,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
2389 | Quaternion worldRot = linkPart.GetWorldRotation(); | 2603 | Quaternion worldRot = linkPart.GetWorldRotation(); |
2390 | 2604 | ||
2391 | // Remove the part from this object | 2605 | // Remove the part from this object |
2392 | lock (m_parts) | 2606 | lockPartsForWrite(true); |
2393 | { | 2607 | { |
2394 | m_parts.Remove(linkPart.UUID); | 2608 | m_parts.Remove(linkPart.UUID); |
2395 | } | 2609 | } |
2396 | 2610 | lockPartsForWrite(false); | |
2611 | lockPartsForRead(true); | ||
2397 | if (m_parts.Count == 1 && RootPart != null) //Single prim is left | 2612 | if (m_parts.Count == 1 && RootPart != null) //Single prim is left |
2398 | RootPart.LinkNum = 0; | 2613 | RootPart.LinkNum = 0; |
2399 | else | 2614 | else |
@@ -2404,6 +2619,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2404 | p.LinkNum--; | 2619 | p.LinkNum--; |
2405 | } | 2620 | } |
2406 | } | 2621 | } |
2622 | lockPartsForRead(false); | ||
2407 | 2623 | ||
2408 | linkPart.ParentID = 0; | 2624 | linkPart.ParentID = 0; |
2409 | linkPart.LinkNum = 0; | 2625 | linkPart.LinkNum = 0; |
@@ -2725,9 +2941,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
2725 | 2941 | ||
2726 | if (selectionPart != null) | 2942 | if (selectionPart != null) |
2727 | { | 2943 | { |
2728 | lock (m_parts) | 2944 | lockPartsForRead(true); |
2945 | List<SceneObjectPart> parts = new List<SceneObjectPart>(m_parts.Values); | ||
2946 | lockPartsForRead(false); | ||
2947 | foreach (SceneObjectPart part in parts) | ||
2729 | { | 2948 | { |
2730 | foreach (SceneObjectPart part in m_parts.Values) | 2949 | if (part.Scale.X > 10.0 || part.Scale.Y > 10.0 || part.Scale.Z > 10.0) |
2731 | { | 2950 | { |
2732 | if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax || | 2951 | if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax || |
2733 | part.Scale.Y > m_scene.RegionInfo.PhysPrimMax || | 2952 | part.Scale.Y > m_scene.RegionInfo.PhysPrimMax || |
@@ -2737,12 +2956,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
2737 | break; | 2956 | break; |
2738 | } | 2957 | } |
2739 | } | 2958 | } |
2959 | } | ||
2740 | 2960 | ||
2741 | foreach (SceneObjectPart part in m_parts.Values) | 2961 | foreach (SceneObjectPart part in parts) |
2742 | { | 2962 | { |
2743 | part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect); | 2963 | part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect); |
2744 | } | ||
2745 | } | 2964 | } |
2965 | |||
2746 | } | 2966 | } |
2747 | } | 2967 | } |
2748 | 2968 | ||
@@ -2828,11 +3048,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
2828 | scale.Y = m_scene.m_maxNonphys; | 3048 | scale.Y = m_scene.m_maxNonphys; |
2829 | if (scale.Z > m_scene.m_maxNonphys) | 3049 | if (scale.Z > m_scene.m_maxNonphys) |
2830 | scale.Z = m_scene.m_maxNonphys; | 3050 | scale.Z = m_scene.m_maxNonphys; |
2831 | |||
2832 | SceneObjectPart part = GetChildPart(localID); | 3051 | SceneObjectPart part = GetChildPart(localID); |
2833 | if (part != null) | 3052 | if (part != null) |
2834 | { | 3053 | { |
2835 | part.Resize(scale); | ||
2836 | if (part.PhysActor != null) | 3054 | if (part.PhysActor != null) |
2837 | { | 3055 | { |
2838 | if (part.PhysActor.IsPhysical) | 3056 | if (part.PhysActor.IsPhysical) |
@@ -2847,7 +3065,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2847 | part.PhysActor.Size = scale; | 3065 | part.PhysActor.Size = scale; |
2848 | m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); | 3066 | m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); |
2849 | } | 3067 | } |
2850 | //if (part.UUID != m_rootPart.UUID) | 3068 | part.Resize(scale); |
2851 | 3069 | ||
2852 | HasGroupChanged = true; | 3070 | HasGroupChanged = true; |
2853 | ScheduleGroupForFullUpdate(); | 3071 | ScheduleGroupForFullUpdate(); |
@@ -2889,73 +3107,71 @@ namespace OpenSim.Region.Framework.Scenes | |||
2889 | float y = (scale.Y / part.Scale.Y); | 3107 | float y = (scale.Y / part.Scale.Y); |
2890 | float z = (scale.Z / part.Scale.Z); | 3108 | float z = (scale.Z / part.Scale.Z); |
2891 | 3109 | ||
2892 | lock (m_parts) | 3110 | lockPartsForRead(true); |
3111 | if (x > 1.0f || y > 1.0f || z > 1.0f) | ||
2893 | { | 3112 | { |
2894 | if (x > 1.0f || y > 1.0f || z > 1.0f) | 3113 | foreach (SceneObjectPart obPart in m_parts.Values) |
2895 | { | 3114 | { |
2896 | foreach (SceneObjectPart obPart in m_parts.Values) | 3115 | if (obPart.UUID != m_rootPart.UUID) |
2897 | { | 3116 | { |
2898 | if (obPart.UUID != m_rootPart.UUID) | 3117 | obPart.IgnoreUndoUpdate = true; |
2899 | { | 3118 | Vector3 oldSize = new Vector3(obPart.Scale); |
2900 | obPart.IgnoreUndoUpdate = true; | ||
2901 | Vector3 oldSize = new Vector3(obPart.Scale); | ||
2902 | 3119 | ||
2903 | float f = 1.0f; | 3120 | float f = 1.0f; |
2904 | float a = 1.0f; | 3121 | float a = 1.0f; |
2905 | 3122 | ||
2906 | if (part.PhysActor != null && part.PhysActor.IsPhysical) | 3123 | if (part.PhysActor != null && part.PhysActor.IsPhysical) |
3124 | { | ||
3125 | if (oldSize.X*x > m_scene.m_maxPhys) | ||
2907 | { | 3126 | { |
2908 | if (oldSize.X*x > m_scene.m_maxPhys) | 3127 | f = m_scene.m_maxPhys / oldSize.X; |
2909 | { | 3128 | a = f / x; |
2910 | f = m_scene.m_maxPhys / oldSize.X; | 3129 | x *= a; |
2911 | a = f / x; | 3130 | y *= a; |
2912 | x *= a; | 3131 | z *= a; |
2913 | y *= a; | ||
2914 | z *= a; | ||
2915 | } | ||
2916 | if (oldSize.Y*y > m_scene.m_maxPhys) | ||
2917 | { | ||
2918 | f = m_scene.m_maxPhys / oldSize.Y; | ||
2919 | a = f / y; | ||
2920 | x *= a; | ||
2921 | y *= a; | ||
2922 | z *= a; | ||
2923 | } | ||
2924 | if (oldSize.Z*z > m_scene.m_maxPhys) | ||
2925 | { | ||
2926 | f = m_scene.m_maxPhys / oldSize.Z; | ||
2927 | a = f / z; | ||
2928 | x *= a; | ||
2929 | y *= a; | ||
2930 | z *= a; | ||
2931 | } | ||
2932 | } | 3132 | } |
2933 | else | 3133 | if (oldSize.Y*y > m_scene.m_maxPhys) |
2934 | { | 3134 | { |
2935 | if (oldSize.X*x > m_scene.m_maxNonphys) | 3135 | f = m_scene.m_maxPhys / oldSize.Y; |
2936 | { | 3136 | a = f / y; |
2937 | f = m_scene.m_maxNonphys / oldSize.X; | 3137 | x *= a; |
2938 | a = f / x; | 3138 | y *= a; |
2939 | x *= a; | 3139 | z *= a; |
2940 | y *= a; | 3140 | } |
2941 | z *= a; | 3141 | if (oldSize.Z*z > m_scene.m_maxPhys) |
2942 | } | 3142 | { |
2943 | if (oldSize.Y*y > m_scene.m_maxNonphys) | 3143 | f = m_scene.m_maxPhys / oldSize.Z; |
2944 | { | 3144 | a = f / z; |
2945 | f = m_scene.m_maxNonphys / oldSize.Y; | 3145 | x *= a; |
2946 | a = f / y; | 3146 | y *= a; |
2947 | x *= a; | 3147 | z *= a; |
2948 | y *= a; | 3148 | } |
2949 | z *= a; | 3149 | } |
2950 | } | 3150 | else |
2951 | if (oldSize.Z*z > m_scene.m_maxNonphys) | 3151 | { |
2952 | { | 3152 | if (oldSize.X*x > m_scene.m_maxNonphys) |
2953 | f = m_scene.m_maxNonphys / oldSize.Z; | 3153 | { |
2954 | a = f / z; | 3154 | f = m_scene.m_maxNonphys / oldSize.X; |
2955 | x *= a; | 3155 | a = f / x; |
2956 | y *= a; | 3156 | x *= a; |
2957 | z *= a; | 3157 | y *= a; |
2958 | } | 3158 | z *= a; |
3159 | } | ||
3160 | if (oldSize.Y*y > m_scene.m_maxNonphys) | ||
3161 | { | ||
3162 | f = m_scene.m_maxNonphys / oldSize.Y; | ||
3163 | a = f / y; | ||
3164 | x *= a; | ||
3165 | y *= a; | ||
3166 | z *= a; | ||
3167 | } | ||
3168 | if (oldSize.Z*z > m_scene.m_maxNonphys) | ||
3169 | { | ||
3170 | f = m_scene.m_maxNonphys / oldSize.Z; | ||
3171 | a = f / z; | ||
3172 | x *= a; | ||
3173 | y *= a; | ||
3174 | z *= a; | ||
2959 | } | 3175 | } |
2960 | obPart.IgnoreUndoUpdate = false; | 3176 | obPart.IgnoreUndoUpdate = false; |
2961 | obPart.StoreUndoState(); | 3177 | obPart.StoreUndoState(); |
@@ -2963,6 +3179,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2963 | } | 3179 | } |
2964 | } | 3180 | } |
2965 | } | 3181 | } |
3182 | lockPartsForRead(false); | ||
2966 | 3183 | ||
2967 | Vector3 prevScale = part.Scale; | 3184 | Vector3 prevScale = part.Scale; |
2968 | prevScale.X *= x; | 3185 | prevScale.X *= x; |
@@ -2970,7 +3187,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2970 | prevScale.Z *= z; | 3187 | prevScale.Z *= z; |
2971 | part.Resize(prevScale); | 3188 | part.Resize(prevScale); |
2972 | 3189 | ||
2973 | lock (m_parts) | 3190 | lockPartsForRead(true); |
2974 | { | 3191 | { |
2975 | foreach (SceneObjectPart obPart in m_parts.Values) | 3192 | foreach (SceneObjectPart obPart in m_parts.Values) |
2976 | { | 3193 | { |
@@ -2992,6 +3209,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2992 | obPart.StoreUndoState(); | 3209 | obPart.StoreUndoState(); |
2993 | } | 3210 | } |
2994 | } | 3211 | } |
3212 | lockPartsForRead(false); | ||
2995 | 3213 | ||
2996 | if (part.PhysActor != null) | 3214 | if (part.PhysActor != null) |
2997 | { | 3215 | { |
@@ -3094,7 +3312,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3094 | axDiff *= Quaternion.Inverse(partRotation); | 3312 | axDiff *= Quaternion.Inverse(partRotation); |
3095 | diff = axDiff; | 3313 | diff = axDiff; |
3096 | 3314 | ||
3097 | lock (m_parts) | 3315 | lockPartsForRead(true); |
3098 | { | 3316 | { |
3099 | foreach (SceneObjectPart obPart in m_parts.Values) | 3317 | foreach (SceneObjectPart obPart in m_parts.Values) |
3100 | { | 3318 | { |
@@ -3104,6 +3322,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3104 | } | 3322 | } |
3105 | } | 3323 | } |
3106 | } | 3324 | } |
3325 | lockPartsForRead(false); | ||
3107 | 3326 | ||
3108 | AbsolutePosition = newPos; | 3327 | AbsolutePosition = newPos; |
3109 | 3328 | ||
@@ -3237,25 +3456,25 @@ namespace OpenSim.Region.Framework.Scenes | |||
3237 | m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); | 3456 | m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); |
3238 | } | 3457 | } |
3239 | 3458 | ||
3240 | lock (m_parts) | 3459 | lockPartsForRead(true); |
3460 | |||
3461 | foreach (SceneObjectPart prim in m_parts.Values) | ||
3241 | { | 3462 | { |
3242 | foreach (SceneObjectPart prim in m_parts.Values) | 3463 | if (prim.UUID != m_rootPart.UUID) |
3243 | { | 3464 | { |
3244 | if (prim.UUID != m_rootPart.UUID) | 3465 | prim.IgnoreUndoUpdate = true; |
3245 | { | 3466 | Vector3 axPos = prim.OffsetPosition; |
3246 | prim.IgnoreUndoUpdate = true; | 3467 | axPos *= oldParentRot; |
3247 | Vector3 axPos = prim.OffsetPosition; | 3468 | axPos *= Quaternion.Inverse(axRot); |
3248 | axPos *= oldParentRot; | 3469 | prim.OffsetPosition = axPos; |
3249 | axPos *= Quaternion.Inverse(axRot); | 3470 | Quaternion primsRot = prim.RotationOffset; |
3250 | prim.OffsetPosition = axPos; | 3471 | Quaternion newRot = primsRot * oldParentRot; |
3251 | Quaternion primsRot = prim.RotationOffset; | 3472 | newRot *= Quaternion.Inverse(axRot); |
3252 | Quaternion newRot = primsRot * oldParentRot; | 3473 | prim.RotationOffset = newRot; |
3253 | newRot *= Quaternion.Inverse(axRot); | 3474 | prim.ScheduleTerseUpdate(); |
3254 | prim.RotationOffset = newRot; | ||
3255 | prim.ScheduleTerseUpdate(); | ||
3256 | } | ||
3257 | } | 3475 | } |
3258 | } | 3476 | } |
3477 | |||
3259 | foreach (SceneObjectPart childpart in Children.Values) | 3478 | foreach (SceneObjectPart childpart in Children.Values) |
3260 | { | 3479 | { |
3261 | if (childpart != m_rootPart) | 3480 | if (childpart != m_rootPart) |
@@ -3264,6 +3483,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
3264 | childpart.StoreUndoState(); | 3483 | childpart.StoreUndoState(); |
3265 | } | 3484 | } |
3266 | } | 3485 | } |
3486 | |||
3487 | lockPartsForRead(false); | ||
3488 | |||
3267 | m_rootPart.ScheduleTerseUpdate(); | 3489 | m_rootPart.ScheduleTerseUpdate(); |
3268 | } | 3490 | } |
3269 | 3491 | ||
@@ -3385,7 +3607,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3385 | if (atTargets.Count > 0) | 3607 | if (atTargets.Count > 0) |
3386 | { | 3608 | { |
3387 | uint[] localids = new uint[0]; | 3609 | uint[] localids = new uint[0]; |
3388 | lock (m_parts) | 3610 | lockPartsForRead(true); |
3389 | { | 3611 | { |
3390 | localids = new uint[m_parts.Count]; | 3612 | localids = new uint[m_parts.Count]; |
3391 | int cntr = 0; | 3613 | int cntr = 0; |
@@ -3395,6 +3617,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3395 | cntr++; | 3617 | cntr++; |
3396 | } | 3618 | } |
3397 | } | 3619 | } |
3620 | lockPartsForRead(false); | ||
3398 | 3621 | ||
3399 | for (int ctr = 0; ctr < localids.Length; ctr++) | 3622 | for (int ctr = 0; ctr < localids.Length; ctr++) |
3400 | { | 3623 | { |
@@ -3413,7 +3636,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3413 | { | 3636 | { |
3414 | //trigger not_at_target | 3637 | //trigger not_at_target |
3415 | uint[] localids = new uint[0]; | 3638 | uint[] localids = new uint[0]; |
3416 | lock (m_parts) | 3639 | lockPartsForRead(true); |
3417 | { | 3640 | { |
3418 | localids = new uint[m_parts.Count]; | 3641 | localids = new uint[m_parts.Count]; |
3419 | int cntr = 0; | 3642 | int cntr = 0; |
@@ -3423,7 +3646,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
3423 | cntr++; | 3646 | cntr++; |
3424 | } | 3647 | } |
3425 | } | 3648 | } |
3426 | 3649 | lockPartsForRead(false); | |
3650 | |||
3427 | for (int ctr = 0; ctr < localids.Length; ctr++) | 3651 | for (int ctr = 0; ctr < localids.Length; ctr++) |
3428 | { | 3652 | { |
3429 | m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]); | 3653 | m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]); |
@@ -3515,19 +3739,20 @@ namespace OpenSim.Region.Framework.Scenes | |||
3515 | public float GetMass() | 3739 | public float GetMass() |
3516 | { | 3740 | { |
3517 | float retmass = 0f; | 3741 | float retmass = 0f; |
3518 | lock (m_parts) | 3742 | lockPartsForRead(true); |
3519 | { | 3743 | { |
3520 | foreach (SceneObjectPart part in m_parts.Values) | 3744 | foreach (SceneObjectPart part in m_parts.Values) |
3521 | { | 3745 | { |
3522 | retmass += part.GetMass(); | 3746 | retmass += part.GetMass(); |
3523 | } | 3747 | } |
3524 | } | 3748 | } |
3749 | lockPartsForRead(false); | ||
3525 | return retmass; | 3750 | return retmass; |
3526 | } | 3751 | } |
3527 | 3752 | ||
3528 | public void CheckSculptAndLoad() | 3753 | public void CheckSculptAndLoad() |
3529 | { | 3754 | { |
3530 | lock (m_parts) | 3755 | lockPartsForRead(true); |
3531 | { | 3756 | { |
3532 | if (!IsDeleted) | 3757 | if (!IsDeleted) |
3533 | { | 3758 | { |
@@ -3552,6 +3777,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3552 | } | 3777 | } |
3553 | } | 3778 | } |
3554 | } | 3779 | } |
3780 | lockPartsForRead(false); | ||
3555 | } | 3781 | } |
3556 | 3782 | ||
3557 | protected void AssetReceived(string id, Object sender, AssetBase asset) | 3783 | protected void AssetReceived(string id, Object sender, AssetBase asset) |
@@ -3572,7 +3798,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3572 | /// <param name="client"></param> | 3798 | /// <param name="client"></param> |
3573 | public void SetGroup(UUID GroupID, IClientAPI client) | 3799 | public void SetGroup(UUID GroupID, IClientAPI client) |
3574 | { | 3800 | { |
3575 | lock (m_parts) | 3801 | lockPartsForRead(true); |
3576 | { | 3802 | { |
3577 | foreach (SceneObjectPart part in m_parts.Values) | 3803 | foreach (SceneObjectPart part in m_parts.Values) |
3578 | { | 3804 | { |
@@ -3582,6 +3808,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3582 | 3808 | ||
3583 | HasGroupChanged = true; | 3809 | HasGroupChanged = true; |
3584 | } | 3810 | } |
3811 | lockPartsForRead(false); | ||
3585 | 3812 | ||
3586 | // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled | 3813 | // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled |
3587 | // for the same object with very different properties. The caller must schedule the update. | 3814 | // for the same object with very different properties. The caller must schedule the update. |
@@ -3603,11 +3830,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
3603 | 3830 | ||
3604 | public void SetAttachmentPoint(byte point) | 3831 | public void SetAttachmentPoint(byte point) |
3605 | { | 3832 | { |
3606 | lock (m_parts) | 3833 | lockPartsForRead(true); |
3607 | { | 3834 | { |
3608 | foreach (SceneObjectPart part in m_parts.Values) | 3835 | foreach (SceneObjectPart part in m_parts.Values) |
3609 | part.SetAttachmentPoint(point); | 3836 | part.SetAttachmentPoint(point); |
3610 | } | 3837 | } |
3838 | lockPartsForRead(false); | ||
3611 | } | 3839 | } |
3612 | 3840 | ||
3613 | #region ISceneObject | 3841 | #region ISceneObject |