diff options
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs')
-rw-r--r-- | OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 662 |
1 files changed, 445 insertions, 217 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 8aefd50..1c6f2d1 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) |
@@ -305,17 +418,18 @@ namespace OpenSim.Region.Framework.Scenes | |||
305 | RootPart.ScriptSetPhysicsStatus(false); | 418 | RootPart.ScriptSetPhysicsStatus(false); |
306 | Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"), | 419 | Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"), |
307 | ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false); | 420 | ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false); |
421 | lockPartsForRead(false); | ||
308 | return; | 422 | return; |
309 | } | 423 | } |
310 | } | 424 | } |
311 | lock (m_parts) | 425 | |
426 | foreach (SceneObjectPart part in m_parts.Values) | ||
312 | { | 427 | { |
313 | foreach (SceneObjectPart part in m_parts.Values) | 428 | part.GroupPosition = val; |
314 | { | ||
315 | part.GroupPosition = val; | ||
316 | } | ||
317 | } | 429 | } |
318 | 430 | ||
431 | lockPartsForRead(false); | ||
432 | |||
319 | //if (m_rootPart.PhysActor != null) | 433 | //if (m_rootPart.PhysActor != null) |
320 | //{ | 434 | //{ |
321 | //m_rootPart.PhysActor.Position = | 435 | //m_rootPart.PhysActor.Position = |
@@ -457,6 +571,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
457 | /// </summary> | 571 | /// </summary> |
458 | public SceneObjectGroup() | 572 | public SceneObjectGroup() |
459 | { | 573 | { |
574 | |||
460 | } | 575 | } |
461 | 576 | ||
462 | /// <summary> | 577 | /// <summary> |
@@ -473,7 +588,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
473 | /// Constructor. This object is added to the scene later via AttachToScene() | 588 | /// Constructor. This object is added to the scene later via AttachToScene() |
474 | /// </summary> | 589 | /// </summary> |
475 | public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) | 590 | public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) |
476 | { | 591 | { |
477 | SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero)); | 592 | SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero)); |
478 | } | 593 | } |
479 | 594 | ||
@@ -504,13 +619,16 @@ namespace OpenSim.Region.Framework.Scenes | |||
504 | 619 | ||
505 | public void SetFromItemID(UUID AssetId) | 620 | public void SetFromItemID(UUID AssetId) |
506 | { | 621 | { |
507 | lock (m_parts) | 622 | lockPartsForRead(true); |
508 | { | 623 | { |
509 | foreach (SceneObjectPart part in m_parts.Values) | 624 | foreach (SceneObjectPart part in m_parts.Values) |
510 | { | 625 | { |
626 | |||
511 | part.FromItemID = AssetId; | 627 | part.FromItemID = AssetId; |
628 | |||
512 | } | 629 | } |
513 | } | 630 | } |
631 | lockPartsForRead(false); | ||
514 | } | 632 | } |
515 | 633 | ||
516 | public UUID GetFromItemID() | 634 | public UUID GetFromItemID() |
@@ -579,10 +697,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
579 | Vector3 maxScale = Vector3.Zero; | 697 | Vector3 maxScale = Vector3.Zero; |
580 | Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f); | 698 | Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f); |
581 | 699 | ||
582 | lock (m_parts) | 700 | lockPartsForRead(true); |
583 | { | 701 | { |
584 | foreach (SceneObjectPart part in m_parts.Values) | 702 | foreach (SceneObjectPart part in m_parts.Values) |
585 | { | 703 | { |
704 | |||
586 | Vector3 partscale = part.Scale; | 705 | Vector3 partscale = part.Scale; |
587 | Vector3 partoffset = part.OffsetPosition; | 706 | Vector3 partoffset = part.OffsetPosition; |
588 | 707 | ||
@@ -593,8 +712,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
593 | maxScale.X = (partscale.X + partoffset.X > maxScale.X) ? partscale.X + partoffset.X : maxScale.X; | 712 | 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; | 713 | 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; | 714 | maxScale.Z = (partscale.Z + partoffset.Z > maxScale.Z) ? partscale.Z + partoffset.Z : maxScale.Z; |
715 | |||
596 | } | 716 | } |
597 | } | 717 | } |
718 | lockPartsForRead(false); | ||
719 | |||
598 | finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X; | 720 | finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X; |
599 | finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y; | 721 | finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y; |
600 | finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z; | 722 | finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z; |
@@ -610,10 +732,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
610 | 732 | ||
611 | EntityIntersection result = new EntityIntersection(); | 733 | EntityIntersection result = new EntityIntersection(); |
612 | 734 | ||
613 | lock (m_parts) | 735 | lockPartsForRead(true); |
614 | { | 736 | { |
615 | foreach (SceneObjectPart part in m_parts.Values) | 737 | foreach (SceneObjectPart part in m_parts.Values) |
616 | { | 738 | { |
739 | |||
617 | // Temporary commented to stop compiler warning | 740 | // Temporary commented to stop compiler warning |
618 | //Vector3 partPosition = | 741 | //Vector3 partPosition = |
619 | // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z); | 742 | // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z); |
@@ -641,8 +764,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
641 | result.distance = inter.distance; | 764 | result.distance = inter.distance; |
642 | } | 765 | } |
643 | } | 766 | } |
767 | |||
644 | } | 768 | } |
645 | } | 769 | } |
770 | lockPartsForRead(false); | ||
646 | return result; | 771 | return result; |
647 | } | 772 | } |
648 | 773 | ||
@@ -655,10 +780,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
655 | public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight) | 780 | public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight) |
656 | { | 781 | { |
657 | float maxX = -256f, maxY = -256f, maxZ = -256f, minX = 256f, minY = 256f, minZ = 256f; | 782 | float maxX = -256f, maxY = -256f, maxZ = -256f, minX = 256f, minY = 256f, minZ = 256f; |
658 | lock (m_parts) | 783 | lockPartsForRead(true); |
659 | { | 784 | { |
660 | foreach (SceneObjectPart part in m_parts.Values) | 785 | foreach (SceneObjectPart part in m_parts.Values) |
661 | { | 786 | { |
787 | |||
662 | Vector3 worldPos = part.GetWorldPosition(); | 788 | Vector3 worldPos = part.GetWorldPosition(); |
663 | Vector3 offset = worldPos - AbsolutePosition; | 789 | Vector3 offset = worldPos - AbsolutePosition; |
664 | Quaternion worldRot; | 790 | Quaternion worldRot; |
@@ -717,6 +843,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
717 | backBottomRight.Y = orig.Y + (part.Scale.Y / 2); | 843 | backBottomRight.Y = orig.Y + (part.Scale.Y / 2); |
718 | backBottomRight.Z = orig.Z - (part.Scale.Z / 2); | 844 | backBottomRight.Z = orig.Z - (part.Scale.Z / 2); |
719 | 845 | ||
846 | |||
847 | |||
720 | //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z); | 848 | //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); | 849 | //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); | 850 | //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z); |
@@ -888,6 +1016,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
888 | minZ = backBottomLeft.Z; | 1016 | minZ = backBottomLeft.Z; |
889 | } | 1017 | } |
890 | } | 1018 | } |
1019 | lockPartsForRead(false); | ||
891 | 1020 | ||
892 | Vector3 boundingBox = new Vector3(maxX - minX, maxY - minY, maxZ - minZ); | 1021 | Vector3 boundingBox = new Vector3(maxX - minX, maxY - minY, maxZ - minZ); |
893 | 1022 | ||
@@ -912,21 +1041,29 @@ namespace OpenSim.Region.Framework.Scenes | |||
912 | 1041 | ||
913 | public void SaveScriptedState(XmlTextWriter writer) | 1042 | public void SaveScriptedState(XmlTextWriter writer) |
914 | { | 1043 | { |
1044 | SaveScriptedState(writer, false); | ||
1045 | } | ||
1046 | |||
1047 | public void SaveScriptedState(XmlTextWriter writer, bool oldIDs) | ||
1048 | { | ||
915 | XmlDocument doc = new XmlDocument(); | 1049 | XmlDocument doc = new XmlDocument(); |
916 | Dictionary<UUID,string> states = new Dictionary<UUID,string>(); | 1050 | Dictionary<UUID,string> states = new Dictionary<UUID,string>(); |
917 | 1051 | ||
918 | // Capture script state while holding the lock | 1052 | // Capture script state while holding the lock |
919 | lock (m_parts) | 1053 | lockPartsForRead(true); |
920 | { | 1054 | { |
921 | foreach (SceneObjectPart part in m_parts.Values) | 1055 | foreach (SceneObjectPart part in m_parts.Values) |
922 | { | 1056 | { |
923 | Dictionary<UUID,string> pstates = part.Inventory.GetScriptStates(); | 1057 | |
1058 | Dictionary<UUID,string> pstates = part.Inventory.GetScriptStates(oldIDs); | ||
924 | foreach (UUID itemid in pstates.Keys) | 1059 | foreach (UUID itemid in pstates.Keys) |
925 | { | 1060 | { |
926 | states.Add(itemid, pstates[itemid]); | 1061 | states.Add(itemid, pstates[itemid]); |
927 | } | 1062 | } |
1063 | |||
928 | } | 1064 | } |
929 | } | 1065 | } |
1066 | lockPartsForRead(false); | ||
930 | 1067 | ||
931 | if (states.Count > 0) | 1068 | if (states.Count > 0) |
932 | { | 1069 | { |
@@ -1094,13 +1231,16 @@ namespace OpenSim.Region.Framework.Scenes | |||
1094 | 1231 | ||
1095 | public override void UpdateMovement() | 1232 | public override void UpdateMovement() |
1096 | { | 1233 | { |
1097 | lock (m_parts) | 1234 | lockPartsForRead(true); |
1098 | { | 1235 | { |
1099 | foreach (SceneObjectPart part in m_parts.Values) | 1236 | foreach (SceneObjectPart part in m_parts.Values) |
1100 | { | 1237 | { |
1238 | |||
1101 | part.UpdateMovement(); | 1239 | part.UpdateMovement(); |
1240 | |||
1102 | } | 1241 | } |
1103 | } | 1242 | } |
1243 | lockPartsForRead(false); | ||
1104 | } | 1244 | } |
1105 | 1245 | ||
1106 | public ushort GetTimeDilation() | 1246 | public ushort GetTimeDilation() |
@@ -1144,7 +1284,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1144 | /// <param name="part"></param> | 1284 | /// <param name="part"></param> |
1145 | public void AddPart(SceneObjectPart part) | 1285 | public void AddPart(SceneObjectPart part) |
1146 | { | 1286 | { |
1147 | lock (m_parts) | 1287 | lockPartsForWrite(true); |
1148 | { | 1288 | { |
1149 | part.SetParent(this); | 1289 | part.SetParent(this); |
1150 | m_parts.Add(part.UUID, part); | 1290 | m_parts.Add(part.UUID, part); |
@@ -1154,6 +1294,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1154 | if (part.LinkNum == 2 && RootPart != null) | 1294 | if (part.LinkNum == 2 && RootPart != null) |
1155 | RootPart.LinkNum = 1; | 1295 | RootPart.LinkNum = 1; |
1156 | } | 1296 | } |
1297 | lockPartsForWrite(false); | ||
1157 | } | 1298 | } |
1158 | 1299 | ||
1159 | /// <summary> | 1300 | /// <summary> |
@@ -1161,28 +1302,33 @@ namespace OpenSim.Region.Framework.Scenes | |||
1161 | /// </summary> | 1302 | /// </summary> |
1162 | private void UpdateParentIDs() | 1303 | private void UpdateParentIDs() |
1163 | { | 1304 | { |
1164 | lock (m_parts) | 1305 | lockPartsForRead(true); |
1165 | { | 1306 | { |
1166 | foreach (SceneObjectPart part in m_parts.Values) | 1307 | foreach (SceneObjectPart part in m_parts.Values) |
1167 | { | 1308 | { |
1309 | |||
1168 | if (part.UUID != m_rootPart.UUID) | 1310 | if (part.UUID != m_rootPart.UUID) |
1169 | { | 1311 | { |
1170 | part.ParentID = m_rootPart.LocalId; | 1312 | part.ParentID = m_rootPart.LocalId; |
1171 | } | 1313 | } |
1314 | |||
1172 | } | 1315 | } |
1173 | } | 1316 | } |
1317 | lockPartsForRead(false); | ||
1174 | } | 1318 | } |
1175 | 1319 | ||
1176 | public void RegenerateFullIDs() | 1320 | public void RegenerateFullIDs() |
1177 | { | 1321 | { |
1178 | lock (m_parts) | 1322 | lockPartsForRead(true); |
1179 | { | 1323 | { |
1180 | foreach (SceneObjectPart part in m_parts.Values) | 1324 | foreach (SceneObjectPart part in m_parts.Values) |
1181 | { | 1325 | { |
1326 | |||
1182 | part.UUID = UUID.Random(); | 1327 | part.UUID = UUID.Random(); |
1183 | 1328 | ||
1184 | } | 1329 | } |
1185 | } | 1330 | } |
1331 | lockPartsForRead(false); | ||
1186 | } | 1332 | } |
1187 | 1333 | ||
1188 | // helper provided for parts. | 1334 | // helper provided for parts. |
@@ -1263,27 +1409,32 @@ namespace OpenSim.Region.Framework.Scenes | |||
1263 | 1409 | ||
1264 | DetachFromBackup(); | 1410 | DetachFromBackup(); |
1265 | 1411 | ||
1266 | lock (m_parts) | 1412 | lockPartsForRead(true); |
1413 | List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values); | ||
1414 | lockPartsForRead(false); | ||
1415 | |||
1416 | foreach (SceneObjectPart part in values) | ||
1267 | { | 1417 | { |
1268 | foreach (SceneObjectPart part in m_parts.Values) | ||
1269 | { | ||
1270 | // part.Inventory.RemoveScriptInstances(); | 1418 | // part.Inventory.RemoveScriptInstances(); |
1271 | Scene.ForEachScenePresence(delegate(ScenePresence avatar) | 1419 | |
1420 | Scene.ForEachScenePresence(delegate (ScenePresence sp) | ||
1421 | { | ||
1422 | if (sp.ParentID == LocalId) | ||
1272 | { | 1423 | { |
1273 | if (avatar.ParentID == LocalId) | 1424 | sp.StandUp(); |
1274 | { | 1425 | } |
1275 | avatar.StandUp(); | ||
1276 | } | ||
1277 | 1426 | ||
1278 | if (!silent) | 1427 | if (!silent) |
1279 | { | 1428 | { |
1280 | part.UpdateFlag = 0; | 1429 | part.UpdateFlag = 0; |
1281 | if (part == m_rootPart) | 1430 | if (part == m_rootPart) |
1282 | avatar.ControllingClient.SendKillObject(m_regionHandle, part.LocalId); | 1431 | sp.ControllingClient.SendKillObject(m_regionHandle, part.LocalId); |
1283 | } | 1432 | } |
1284 | }); | 1433 | }); |
1285 | } | 1434 | |
1286 | } | 1435 | } |
1436 | |||
1437 | |||
1287 | } | 1438 | } |
1288 | 1439 | ||
1289 | public void AddScriptLPS(int count) | 1440 | public void AddScriptLPS(int count) |
@@ -1308,17 +1459,20 @@ namespace OpenSim.Region.Framework.Scenes | |||
1308 | 1459 | ||
1309 | scriptEvents aggregateScriptEvents=0; | 1460 | scriptEvents aggregateScriptEvents=0; |
1310 | 1461 | ||
1311 | lock (m_parts) | 1462 | lockPartsForRead(true); |
1312 | { | 1463 | { |
1313 | foreach (SceneObjectPart part in m_parts.Values) | 1464 | foreach (SceneObjectPart part in m_parts.Values) |
1314 | { | 1465 | { |
1466 | |||
1315 | if (part == null) | 1467 | if (part == null) |
1316 | continue; | 1468 | continue; |
1317 | if (part != RootPart) | 1469 | if (part != RootPart) |
1318 | part.ObjectFlags = objectflagupdate; | 1470 | part.ObjectFlags = objectflagupdate; |
1319 | aggregateScriptEvents |= part.AggregateScriptEvents; | 1471 | aggregateScriptEvents |= part.AggregateScriptEvents; |
1472 | |||
1320 | } | 1473 | } |
1321 | } | 1474 | } |
1475 | lockPartsForRead(false); | ||
1322 | 1476 | ||
1323 | m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0); | 1477 | m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0); |
1324 | m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0); | 1478 | m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0); |
@@ -1360,42 +1514,52 @@ namespace OpenSim.Region.Framework.Scenes | |||
1360 | /// <param name="m_physicalPrim"></param> | 1514 | /// <param name="m_physicalPrim"></param> |
1361 | public void ApplyPhysics(bool m_physicalPrim) | 1515 | public void ApplyPhysics(bool m_physicalPrim) |
1362 | { | 1516 | { |
1363 | lock (m_parts) | 1517 | lockPartsForRead(true); |
1518 | |||
1519 | if (m_parts.Count > 1) | ||
1364 | { | 1520 | { |
1365 | if (m_parts.Count > 1) | 1521 | List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values); |
1522 | lockPartsForRead(false); | ||
1523 | m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim); | ||
1524 | foreach (SceneObjectPart part in values) | ||
1366 | { | 1525 | { |
1367 | m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim); | 1526 | |
1368 | foreach (SceneObjectPart part in m_parts.Values) | 1527 | if (part.LocalId != m_rootPart.LocalId) |
1369 | { | 1528 | { |
1370 | if (part.LocalId != m_rootPart.LocalId) | 1529 | part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim); |
1371 | { | ||
1372 | part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim); | ||
1373 | } | ||
1374 | } | 1530 | } |
1375 | 1531 | ||
1376 | // Hack to get the physics scene geometries in the right spot | ||
1377 | ResetChildPrimPhysicsPositions(); | ||
1378 | } | ||
1379 | else | ||
1380 | { | ||
1381 | m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim); | ||
1382 | } | 1532 | } |
1533 | // Hack to get the physics scene geometries in the right spot | ||
1534 | ResetChildPrimPhysicsPositions(); | ||
1535 | } | ||
1536 | else | ||
1537 | { | ||
1538 | lockPartsForRead(false); | ||
1539 | m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim); | ||
1383 | } | 1540 | } |
1384 | } | 1541 | } |
1385 | 1542 | ||
1386 | public void SetOwnerId(UUID userId) | 1543 | public void SetOwnerId(UUID userId) |
1387 | { | 1544 | { |
1388 | ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); | 1545 | ForEachPart(delegate(SceneObjectPart part) |
1546 | { | ||
1547 | |||
1548 | part.OwnerID = userId; | ||
1549 | |||
1550 | }); | ||
1389 | } | 1551 | } |
1390 | 1552 | ||
1391 | public void ForEachPart(Action<SceneObjectPart> whatToDo) | 1553 | public void ForEachPart(Action<SceneObjectPart> whatToDo) |
1392 | { | 1554 | { |
1393 | lock (m_parts) | 1555 | lockPartsForRead(true); |
1556 | List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values); | ||
1557 | lockPartsForRead(false); | ||
1558 | foreach (SceneObjectPart part in values) | ||
1394 | { | 1559 | { |
1395 | foreach (SceneObjectPart part in m_parts.Values) | 1560 | |
1396 | { | 1561 | whatToDo(part); |
1397 | whatToDo(part); | 1562 | |
1398 | } | ||
1399 | } | 1563 | } |
1400 | } | 1564 | } |
1401 | 1565 | ||
@@ -1493,10 +1657,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
1493 | RootPart.SendFullUpdate( | 1657 | RootPart.SendFullUpdate( |
1494 | remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID)); | 1658 | remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID)); |
1495 | 1659 | ||
1496 | lock (m_parts) | 1660 | lockPartsForRead(true); |
1497 | { | 1661 | { |
1498 | foreach (SceneObjectPart part in m_parts.Values) | 1662 | foreach (SceneObjectPart part in m_parts.Values) |
1499 | { | 1663 | { |
1664 | |||
1500 | if (part != RootPart) | 1665 | if (part != RootPart) |
1501 | part.SendFullUpdate( | 1666 | part.SendFullUpdate( |
1502 | remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID)); | 1667 | remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID)); |
@@ -1570,10 +1735,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
1570 | 1735 | ||
1571 | List<SceneObjectPart> partList; | 1736 | List<SceneObjectPart> partList; |
1572 | 1737 | ||
1573 | lock (m_parts) | 1738 | lockPartsForRead(true); |
1574 | { | 1739 | |
1575 | partList = new List<SceneObjectPart>(m_parts.Values); | 1740 | partList = new List<SceneObjectPart>(m_parts.Values); |
1576 | } | 1741 | |
1742 | lockPartsForRead(false); | ||
1577 | 1743 | ||
1578 | partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) | 1744 | partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) |
1579 | { | 1745 | { |
@@ -1796,13 +1962,40 @@ namespace OpenSim.Region.Framework.Scenes | |||
1796 | } | 1962 | } |
1797 | } | 1963 | } |
1798 | 1964 | ||
1965 | public void rotLookAt(Quaternion target, float strength, float damping) | ||
1966 | { | ||
1967 | SceneObjectPart rootpart = m_rootPart; | ||
1968 | if (rootpart != null) | ||
1969 | { | ||
1970 | if (IsAttachment) | ||
1971 | { | ||
1972 | /* | ||
1973 | ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar); | ||
1974 | if (avatar != null) | ||
1975 | { | ||
1976 | Rotate the Av? | ||
1977 | } */ | ||
1978 | } | ||
1979 | else | ||
1980 | { | ||
1981 | if (rootpart.PhysActor != null) | ||
1982 | { // APID must be implemented in your physics system for this to function. | ||
1983 | rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W); | ||
1984 | rootpart.PhysActor.APIDStrength = strength; | ||
1985 | rootpart.PhysActor.APIDDamping = damping; | ||
1986 | rootpart.PhysActor.APIDActive = true; | ||
1987 | } | ||
1988 | } | ||
1989 | } | ||
1990 | } | ||
1991 | |||
1799 | public void stopLookAt() | 1992 | public void stopLookAt() |
1800 | { | 1993 | { |
1801 | SceneObjectPart rootpart = m_rootPart; | 1994 | SceneObjectPart rootpart = m_rootPart; |
1802 | if (rootpart != null) | 1995 | if (rootpart != null) |
1803 | { | 1996 | { |
1804 | if (rootpart.PhysActor != null) | 1997 | if (rootpart.PhysActor != null) |
1805 | { | 1998 | { // APID must be implemented in your physics system for this to function. |
1806 | rootpart.PhysActor.APIDActive = false; | 1999 | rootpart.PhysActor.APIDActive = false; |
1807 | } | 2000 | } |
1808 | } | 2001 | } |
@@ -1870,10 +2063,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
1870 | SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); | 2063 | SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); |
1871 | newPart.SetParent(this); | 2064 | newPart.SetParent(this); |
1872 | 2065 | ||
1873 | lock (m_parts) | 2066 | lockPartsForWrite(true); |
1874 | { | 2067 | { |
1875 | m_parts.Add(newPart.UUID, newPart); | 2068 | m_parts.Add(newPart.UUID, newPart); |
1876 | } | 2069 | } |
2070 | lockPartsForWrite(false); | ||
1877 | 2071 | ||
1878 | SetPartAsNonRoot(newPart); | 2072 | SetPartAsNonRoot(newPart); |
1879 | 2073 | ||
@@ -1936,7 +2130,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1936 | //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0) | 2130 | //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0) |
1937 | // return; | 2131 | // return; |
1938 | 2132 | ||
1939 | lock (m_parts) | 2133 | lockPartsForRead(true); |
1940 | { | 2134 | { |
1941 | bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0); | 2135 | bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0); |
1942 | 2136 | ||
@@ -1956,9 +2150,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
1956 | { | 2150 | { |
1957 | if (!IsSelected) | 2151 | if (!IsSelected) |
1958 | part.UpdateLookAt(); | 2152 | part.UpdateLookAt(); |
2153 | |||
1959 | part.SendScheduledUpdates(); | 2154 | part.SendScheduledUpdates(); |
2155 | |||
1960 | } | 2156 | } |
1961 | } | 2157 | } |
2158 | lockPartsForRead(false); | ||
1962 | } | 2159 | } |
1963 | 2160 | ||
1964 | public void ScheduleFullUpdateToAvatar(ScenePresence presence) | 2161 | public void ScheduleFullUpdateToAvatar(ScenePresence presence) |
@@ -1967,27 +2164,29 @@ namespace OpenSim.Region.Framework.Scenes | |||
1967 | 2164 | ||
1968 | RootPart.AddFullUpdateToAvatar(presence); | 2165 | RootPart.AddFullUpdateToAvatar(presence); |
1969 | 2166 | ||
1970 | lock (m_parts) | 2167 | lockPartsForRead(true); |
1971 | { | 2168 | { |
1972 | foreach (SceneObjectPart part in m_parts.Values) | 2169 | foreach (SceneObjectPart part in m_parts.Values) |
1973 | { | 2170 | { |
2171 | |||
1974 | if (part != RootPart) | 2172 | if (part != RootPart) |
1975 | part.AddFullUpdateToAvatar(presence); | 2173 | part.AddFullUpdateToAvatar(presence); |
2174 | |||
1976 | } | 2175 | } |
1977 | } | 2176 | } |
2177 | lockPartsForRead(false); | ||
1978 | } | 2178 | } |
1979 | 2179 | ||
1980 | public void ScheduleTerseUpdateToAvatar(ScenePresence presence) | 2180 | public void ScheduleTerseUpdateToAvatar(ScenePresence presence) |
1981 | { | 2181 | { |
1982 | // m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1} just to avatar {2}", Name, UUID, presence.Name); | 2182 | lockPartsForRead(true); |
1983 | 2183 | ||
1984 | lock (m_parts) | 2184 | foreach (SceneObjectPart part in m_parts.Values) |
1985 | { | 2185 | { |
1986 | foreach (SceneObjectPart part in m_parts.Values) | 2186 | part.AddTerseUpdateToAvatar(presence); |
1987 | { | ||
1988 | part.AddTerseUpdateToAvatar(presence); | ||
1989 | } | ||
1990 | } | 2187 | } |
2188 | |||
2189 | lockPartsForRead(false); | ||
1991 | } | 2190 | } |
1992 | 2191 | ||
1993 | /// <summary> | 2192 | /// <summary> |
@@ -2000,14 +2199,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
2000 | checkAtTargets(); | 2199 | checkAtTargets(); |
2001 | RootPart.ScheduleFullUpdate(); | 2200 | RootPart.ScheduleFullUpdate(); |
2002 | 2201 | ||
2003 | lock (m_parts) | 2202 | lockPartsForRead(true); |
2004 | { | 2203 | { |
2005 | foreach (SceneObjectPart part in m_parts.Values) | 2204 | foreach (SceneObjectPart part in m_parts.Values) |
2006 | { | 2205 | { |
2206 | |||
2007 | if (part != RootPart) | 2207 | if (part != RootPart) |
2008 | part.ScheduleFullUpdate(); | 2208 | part.ScheduleFullUpdate(); |
2209 | |||
2009 | } | 2210 | } |
2010 | } | 2211 | } |
2212 | lockPartsForRead(false); | ||
2011 | } | 2213 | } |
2012 | 2214 | ||
2013 | /// <summary> | 2215 | /// <summary> |
@@ -2015,37 +2217,38 @@ namespace OpenSim.Region.Framework.Scenes | |||
2015 | /// </summary> | 2217 | /// </summary> |
2016 | public void ScheduleGroupForTerseUpdate() | 2218 | public void ScheduleGroupForTerseUpdate() |
2017 | { | 2219 | { |
2018 | // m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1}", Name, UUID); | 2220 | lockPartsForRead(true); |
2019 | 2221 | foreach (SceneObjectPart part in m_parts.Values) | |
2020 | lock (m_parts) | ||
2021 | { | 2222 | { |
2022 | foreach (SceneObjectPart part in m_parts.Values) | 2223 | part.ScheduleTerseUpdate(); |
2023 | { | ||
2024 | part.ScheduleTerseUpdate(); | ||
2025 | } | ||
2026 | } | 2224 | } |
2225 | |||
2226 | lockPartsForRead(false); | ||
2027 | } | 2227 | } |
2028 | 2228 | ||
2029 | /// <summary> | 2229 | /// <summary> |
2030 | /// Immediately send a full update for this scene object. | 2230 | /// Immediately send a full update for this scene object. |
2031 | /// </summary> | 2231 | /// </summary> |
2032 | public void SendGroupFullUpdate() | 2232 | public void SendGroupFullUpdate() |
2033 | { | 2233 | { |
2034 | if (IsDeleted) | 2234 | if (IsDeleted) |
2035 | return; | 2235 | return; |
2036 | 2236 | ||
2037 | // m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); | 2237 | // m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); |
2038 | 2238 | ||
2039 | RootPart.SendFullUpdateToAllClients(); | 2239 | RootPart.SendFullUpdateToAllClients(); |
2040 | 2240 | ||
2041 | lock (m_parts) | 2241 | lockPartsForRead(true); |
2042 | { | 2242 | { |
2043 | foreach (SceneObjectPart part in m_parts.Values) | 2243 | foreach (SceneObjectPart part in m_parts.Values) |
2044 | { | 2244 | { |
2245 | |||
2045 | if (part != RootPart) | 2246 | if (part != RootPart) |
2046 | part.SendFullUpdateToAllClients(); | 2247 | part.SendFullUpdateToAllClients(); |
2248 | |||
2047 | } | 2249 | } |
2048 | } | 2250 | } |
2251 | lockPartsForRead(false); | ||
2049 | } | 2252 | } |
2050 | 2253 | ||
2051 | /// <summary> | 2254 | /// <summary> |
@@ -2077,14 +2280,15 @@ namespace OpenSim.Region.Framework.Scenes | |||
2077 | { | 2280 | { |
2078 | if (IsDeleted) | 2281 | if (IsDeleted) |
2079 | return; | 2282 | return; |
2080 | 2283 | ||
2081 | lock (m_parts) | 2284 | lockPartsForRead(true); |
2082 | { | 2285 | { |
2083 | foreach (SceneObjectPart part in m_parts.Values) | 2286 | foreach (SceneObjectPart part in m_parts.Values) |
2084 | { | 2287 | { |
2085 | part.SendTerseUpdateToAllClients(); | 2288 | part.SendTerseUpdateToAllClients(); |
2086 | } | 2289 | } |
2087 | } | 2290 | } |
2291 | lockPartsForRead(false); | ||
2088 | } | 2292 | } |
2089 | 2293 | ||
2090 | #endregion | 2294 | #endregion |
@@ -2098,16 +2302,18 @@ namespace OpenSim.Region.Framework.Scenes | |||
2098 | /// <returns>null if no child part with that linknum or child part</returns> | 2302 | /// <returns>null if no child part with that linknum or child part</returns> |
2099 | public SceneObjectPart GetLinkNumPart(int linknum) | 2303 | public SceneObjectPart GetLinkNumPart(int linknum) |
2100 | { | 2304 | { |
2101 | lock (m_parts) | 2305 | lockPartsForRead(true); |
2102 | { | 2306 | { |
2103 | foreach (SceneObjectPart part in m_parts.Values) | 2307 | foreach (SceneObjectPart part in m_parts.Values) |
2104 | { | 2308 | { |
2105 | if (part.LinkNum == linknum) | 2309 | if (part.LinkNum == linknum) |
2106 | { | 2310 | { |
2311 | lockPartsForRead(false); | ||
2107 | return part; | 2312 | return part; |
2108 | } | 2313 | } |
2109 | } | 2314 | } |
2110 | } | 2315 | } |
2316 | lockPartsForRead(false); | ||
2111 | 2317 | ||
2112 | return null; | 2318 | return null; |
2113 | } | 2319 | } |
@@ -2135,17 +2341,19 @@ namespace OpenSim.Region.Framework.Scenes | |||
2135 | public SceneObjectPart GetChildPart(uint localID) | 2341 | public SceneObjectPart GetChildPart(uint localID) |
2136 | { | 2342 | { |
2137 | //m_log.DebugFormat("Entered looking for {0}", localID); | 2343 | //m_log.DebugFormat("Entered looking for {0}", localID); |
2138 | lock (m_parts) | 2344 | lockPartsForRead(true); |
2139 | { | 2345 | { |
2140 | foreach (SceneObjectPart part in m_parts.Values) | 2346 | foreach (SceneObjectPart part in m_parts.Values) |
2141 | { | 2347 | { |
2142 | //m_log.DebugFormat("Found {0}", part.LocalId); | 2348 | //m_log.DebugFormat("Found {0}", part.LocalId); |
2143 | if (part.LocalId == localID) | 2349 | if (part.LocalId == localID) |
2144 | { | 2350 | { |
2351 | lockPartsForRead(false); | ||
2145 | return part; | 2352 | return part; |
2146 | } | 2353 | } |
2147 | } | 2354 | } |
2148 | } | 2355 | } |
2356 | lockPartsForRead(false); | ||
2149 | 2357 | ||
2150 | return null; | 2358 | return null; |
2151 | } | 2359 | } |
@@ -2175,17 +2383,19 @@ namespace OpenSim.Region.Framework.Scenes | |||
2175 | public bool HasChildPrim(uint localID) | 2383 | public bool HasChildPrim(uint localID) |
2176 | { | 2384 | { |
2177 | //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID); | 2385 | //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID); |
2178 | lock (m_parts) | 2386 | lockPartsForRead(true); |
2179 | { | 2387 | { |
2180 | foreach (SceneObjectPart part in m_parts.Values) | 2388 | foreach (SceneObjectPart part in m_parts.Values) |
2181 | { | 2389 | { |
2182 | //m_log.DebugFormat("Found {0}", part.LocalId); | 2390 | //m_log.DebugFormat("Found {0}", part.LocalId); |
2183 | if (part.LocalId == localID) | 2391 | if (part.LocalId == localID) |
2184 | { | 2392 | { |
2393 | lockPartsForRead(false); | ||
2185 | return true; | 2394 | return true; |
2186 | } | 2395 | } |
2187 | } | 2396 | } |
2188 | } | 2397 | } |
2398 | lockPartsForRead(false); | ||
2189 | 2399 | ||
2190 | return false; | 2400 | return false; |
2191 | } | 2401 | } |
@@ -2235,53 +2445,57 @@ namespace OpenSim.Region.Framework.Scenes | |||
2235 | if (m_rootPart.LinkNum == 0) | 2445 | if (m_rootPart.LinkNum == 0) |
2236 | m_rootPart.LinkNum = 1; | 2446 | m_rootPart.LinkNum = 1; |
2237 | 2447 | ||
2238 | lock (m_parts) | 2448 | lockPartsForWrite(true); |
2239 | { | 2449 | |
2240 | m_parts.Add(linkPart.UUID, linkPart); | 2450 | m_parts.Add(linkPart.UUID, linkPart); |
2241 | 2451 | ||
2242 | // Insert in terms of link numbers, the new links | 2452 | lockPartsForWrite(false); |
2243 | // before the current ones (with the exception of | 2453 | |
2244 | // the root prim. Shuffle the old ones up | 2454 | // Insert in terms of link numbers, the new links |
2245 | foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts) | 2455 | // before the current ones (with the exception of |
2456 | // the root prim. Shuffle the old ones up | ||
2457 | lockPartsForRead(true); | ||
2458 | foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts) | ||
2459 | { | ||
2460 | if (kvp.Value.LinkNum != 1) | ||
2246 | { | 2461 | { |
2247 | if (kvp.Value.LinkNum != 1) | 2462 | // Don't update root prim link number |
2248 | { | 2463 | kvp.Value.LinkNum += objectGroup.PrimCount; |
2249 | // Don't update root prim link number | ||
2250 | kvp.Value.LinkNum += objectGroup.PrimCount; | ||
2251 | } | ||
2252 | } | 2464 | } |
2465 | } | ||
2466 | lockPartsForRead(false); | ||
2253 | 2467 | ||
2254 | linkPart.LinkNum = 2; | 2468 | linkPart.LinkNum = 2; |
2255 | 2469 | ||
2256 | linkPart.SetParent(this); | 2470 | linkPart.SetParent(this); |
2257 | linkPart.AddFlag(PrimFlags.CreateSelected); | 2471 | linkPart.AddFlag(PrimFlags.CreateSelected); |
2258 | 2472 | ||
2259 | //if (linkPart.PhysActor != null) | 2473 | //if (linkPart.PhysActor != null) |
2260 | //{ | 2474 | //{ |
2261 | // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); | 2475 | // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); |
2262 | 2476 | ||
2263 | //linkPart.PhysActor = null; | 2477 | //linkPart.PhysActor = null; |
2264 | //} | 2478 | //} |
2265 | 2479 | ||
2266 | //TODO: rest of parts | 2480 | //TODO: rest of parts |
2267 | int linkNum = 3; | 2481 | int linkNum = 3; |
2268 | foreach (SceneObjectPart part in objectGroup.Children.Values) | 2482 | foreach (SceneObjectPart part in objectGroup.Children.Values) |
2483 | { | ||
2484 | if (part.UUID != objectGroup.m_rootPart.UUID) | ||
2269 | { | 2485 | { |
2270 | if (part.UUID != objectGroup.m_rootPart.UUID) | 2486 | LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++); |
2271 | { | ||
2272 | LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++); | ||
2273 | } | ||
2274 | part.ClearUndoState(); | ||
2275 | } | 2487 | } |
2488 | part.ClearUndoState(); | ||
2276 | } | 2489 | } |
2277 | 2490 | ||
2278 | m_scene.UnlinkSceneObject(objectGroup.UUID, true); | 2491 | m_scene.UnlinkSceneObject(objectGroup.UUID, true); |
2279 | objectGroup.m_isDeleted = true; | 2492 | objectGroup.m_isDeleted = true; |
2493 | |||
2494 | objectGroup.lockPartsForWrite(true); | ||
2280 | 2495 | ||
2281 | lock (objectGroup.m_parts) | 2496 | objectGroup.m_parts.Clear(); |
2282 | { | 2497 | |
2283 | objectGroup.m_parts.Clear(); | 2498 | objectGroup.lockPartsForWrite(false); |
2284 | } | ||
2285 | 2499 | ||
2286 | // Can't do this yet since backup still makes use of the root part without any synchronization | 2500 | // Can't do this yet since backup still makes use of the root part without any synchronization |
2287 | // objectGroup.m_rootPart = null; | 2501 | // objectGroup.m_rootPart = null; |
@@ -2351,11 +2565,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
2351 | Quaternion worldRot = linkPart.GetWorldRotation(); | 2565 | Quaternion worldRot = linkPart.GetWorldRotation(); |
2352 | 2566 | ||
2353 | // Remove the part from this object | 2567 | // Remove the part from this object |
2354 | lock (m_parts) | 2568 | lockPartsForWrite(true); |
2355 | { | 2569 | { |
2356 | m_parts.Remove(linkPart.UUID); | 2570 | m_parts.Remove(linkPart.UUID); |
2357 | } | 2571 | } |
2358 | 2572 | lockPartsForWrite(false); | |
2573 | lockPartsForRead(true); | ||
2359 | if (m_parts.Count == 1 && RootPart != null) //Single prim is left | 2574 | if (m_parts.Count == 1 && RootPart != null) //Single prim is left |
2360 | RootPart.LinkNum = 0; | 2575 | RootPart.LinkNum = 0; |
2361 | else | 2576 | else |
@@ -2366,6 +2581,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2366 | p.LinkNum--; | 2581 | p.LinkNum--; |
2367 | } | 2582 | } |
2368 | } | 2583 | } |
2584 | lockPartsForRead(false); | ||
2369 | 2585 | ||
2370 | linkPart.ParentID = 0; | 2586 | linkPart.ParentID = 0; |
2371 | linkPart.LinkNum = 0; | 2587 | linkPart.LinkNum = 0; |
@@ -2687,9 +2903,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
2687 | 2903 | ||
2688 | if (selectionPart != null) | 2904 | if (selectionPart != null) |
2689 | { | 2905 | { |
2690 | lock (m_parts) | 2906 | lockPartsForRead(true); |
2907 | List<SceneObjectPart> parts = new List<SceneObjectPart>(m_parts.Values); | ||
2908 | lockPartsForRead(false); | ||
2909 | foreach (SceneObjectPart part in parts) | ||
2691 | { | 2910 | { |
2692 | foreach (SceneObjectPart part in m_parts.Values) | 2911 | if (part.Scale.X > 10.0 || part.Scale.Y > 10.0 || part.Scale.Z > 10.0) |
2693 | { | 2912 | { |
2694 | if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax || | 2913 | if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax || |
2695 | part.Scale.Y > m_scene.RegionInfo.PhysPrimMax || | 2914 | part.Scale.Y > m_scene.RegionInfo.PhysPrimMax || |
@@ -2699,12 +2918,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
2699 | break; | 2918 | break; |
2700 | } | 2919 | } |
2701 | } | 2920 | } |
2921 | } | ||
2702 | 2922 | ||
2703 | foreach (SceneObjectPart part in m_parts.Values) | 2923 | foreach (SceneObjectPart part in parts) |
2704 | { | 2924 | { |
2705 | part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect); | 2925 | part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect); |
2706 | } | ||
2707 | } | 2926 | } |
2927 | |||
2708 | } | 2928 | } |
2709 | } | 2929 | } |
2710 | 2930 | ||
@@ -2790,11 +3010,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
2790 | scale.Y = m_scene.m_maxNonphys; | 3010 | scale.Y = m_scene.m_maxNonphys; |
2791 | if (scale.Z > m_scene.m_maxNonphys) | 3011 | if (scale.Z > m_scene.m_maxNonphys) |
2792 | scale.Z = m_scene.m_maxNonphys; | 3012 | scale.Z = m_scene.m_maxNonphys; |
2793 | |||
2794 | SceneObjectPart part = GetChildPart(localID); | 3013 | SceneObjectPart part = GetChildPart(localID); |
2795 | if (part != null) | 3014 | if (part != null) |
2796 | { | 3015 | { |
2797 | part.Resize(scale); | ||
2798 | if (part.PhysActor != null) | 3016 | if (part.PhysActor != null) |
2799 | { | 3017 | { |
2800 | if (part.PhysActor.IsPhysical) | 3018 | if (part.PhysActor.IsPhysical) |
@@ -2809,7 +3027,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2809 | part.PhysActor.Size = scale; | 3027 | part.PhysActor.Size = scale; |
2810 | m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); | 3028 | m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); |
2811 | } | 3029 | } |
2812 | //if (part.UUID != m_rootPart.UUID) | 3030 | part.Resize(scale); |
2813 | 3031 | ||
2814 | HasGroupChanged = true; | 3032 | HasGroupChanged = true; |
2815 | ScheduleGroupForFullUpdate(); | 3033 | ScheduleGroupForFullUpdate(); |
@@ -2851,73 +3069,71 @@ namespace OpenSim.Region.Framework.Scenes | |||
2851 | float y = (scale.Y / part.Scale.Y); | 3069 | float y = (scale.Y / part.Scale.Y); |
2852 | float z = (scale.Z / part.Scale.Z); | 3070 | float z = (scale.Z / part.Scale.Z); |
2853 | 3071 | ||
2854 | lock (m_parts) | 3072 | lockPartsForRead(true); |
3073 | if (x > 1.0f || y > 1.0f || z > 1.0f) | ||
2855 | { | 3074 | { |
2856 | if (x > 1.0f || y > 1.0f || z > 1.0f) | 3075 | foreach (SceneObjectPart obPart in m_parts.Values) |
2857 | { | 3076 | { |
2858 | foreach (SceneObjectPart obPart in m_parts.Values) | 3077 | if (obPart.UUID != m_rootPart.UUID) |
2859 | { | 3078 | { |
2860 | if (obPart.UUID != m_rootPart.UUID) | 3079 | Vector3 oldSize = new Vector3(obPart.Scale); |
2861 | { | 3080 | obPart.IgnoreUndoUpdate = true; |
2862 | obPart.IgnoreUndoUpdate = true; | ||
2863 | Vector3 oldSize = new Vector3(obPart.Scale); | ||
2864 | 3081 | ||
2865 | float f = 1.0f; | 3082 | float f = 1.0f; |
2866 | float a = 1.0f; | 3083 | float a = 1.0f; |
2867 | 3084 | ||
2868 | if (part.PhysActor != null && part.PhysActor.IsPhysical) | 3085 | if (part.PhysActor != null && part.PhysActor.IsPhysical) |
3086 | { | ||
3087 | if (oldSize.X*x > m_scene.m_maxPhys) | ||
2869 | { | 3088 | { |
2870 | if (oldSize.X*x > m_scene.m_maxPhys) | 3089 | f = m_scene.m_maxPhys / oldSize.X; |
2871 | { | 3090 | a = f / x; |
2872 | f = m_scene.m_maxPhys / oldSize.X; | 3091 | x *= a; |
2873 | a = f / x; | 3092 | y *= a; |
2874 | x *= a; | 3093 | z *= a; |
2875 | y *= a; | ||
2876 | z *= a; | ||
2877 | } | ||
2878 | if (oldSize.Y*y > m_scene.m_maxPhys) | ||
2879 | { | ||
2880 | f = m_scene.m_maxPhys / oldSize.Y; | ||
2881 | a = f / y; | ||
2882 | x *= a; | ||
2883 | y *= a; | ||
2884 | z *= a; | ||
2885 | } | ||
2886 | if (oldSize.Z*z > m_scene.m_maxPhys) | ||
2887 | { | ||
2888 | f = m_scene.m_maxPhys / oldSize.Z; | ||
2889 | a = f / z; | ||
2890 | x *= a; | ||
2891 | y *= a; | ||
2892 | z *= a; | ||
2893 | } | ||
2894 | } | 3094 | } |
2895 | else | 3095 | if (oldSize.Y*y > m_scene.m_maxPhys) |
3096 | { | ||
3097 | f = m_scene.m_maxPhys / oldSize.Y; | ||
3098 | a = f / y; | ||
3099 | x *= a; | ||
3100 | y *= a; | ||
3101 | z *= a; | ||
3102 | } | ||
3103 | if (oldSize.Z*z > m_scene.m_maxPhys) | ||
3104 | { | ||
3105 | f = m_scene.m_maxPhys / oldSize.Z; | ||
3106 | a = f / z; | ||
3107 | x *= a; | ||
3108 | y *= a; | ||
3109 | z *= a; | ||
3110 | } | ||
3111 | } | ||
3112 | else | ||
3113 | { | ||
3114 | if (oldSize.X*x > m_scene.m_maxNonphys) | ||
2896 | { | 3115 | { |
2897 | if (oldSize.X*x > m_scene.m_maxNonphys) | 3116 | f = m_scene.m_maxNonphys / oldSize.X; |
2898 | { | 3117 | a = f / x; |
2899 | f = m_scene.m_maxNonphys / oldSize.X; | 3118 | x *= a; |
2900 | a = f / x; | 3119 | y *= a; |
2901 | x *= a; | 3120 | z *= a; |
2902 | y *= a; | 3121 | } |
2903 | z *= a; | 3122 | if (oldSize.Y*y > m_scene.m_maxNonphys) |
2904 | } | 3123 | { |
2905 | if (oldSize.Y*y > m_scene.m_maxNonphys) | 3124 | f = m_scene.m_maxNonphys / oldSize.Y; |
2906 | { | 3125 | a = f / y; |
2907 | f = m_scene.m_maxNonphys / oldSize.Y; | 3126 | x *= a; |
2908 | a = f / y; | 3127 | y *= a; |
2909 | x *= a; | 3128 | z *= a; |
2910 | y *= a; | 3129 | } |
2911 | z *= a; | 3130 | if (oldSize.Z*z > m_scene.m_maxNonphys) |
2912 | } | 3131 | { |
2913 | if (oldSize.Z*z > m_scene.m_maxNonphys) | 3132 | f = m_scene.m_maxNonphys / oldSize.Z; |
2914 | { | 3133 | a = f / z; |
2915 | f = m_scene.m_maxNonphys / oldSize.Z; | 3134 | x *= a; |
2916 | a = f / z; | 3135 | y *= a; |
2917 | x *= a; | 3136 | z *= a; |
2918 | y *= a; | ||
2919 | z *= a; | ||
2920 | } | ||
2921 | } | 3137 | } |
2922 | obPart.IgnoreUndoUpdate = false; | 3138 | obPart.IgnoreUndoUpdate = false; |
2923 | obPart.StoreUndoState(); | 3139 | obPart.StoreUndoState(); |
@@ -2925,6 +3141,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2925 | } | 3141 | } |
2926 | } | 3142 | } |
2927 | } | 3143 | } |
3144 | lockPartsForRead(false); | ||
2928 | 3145 | ||
2929 | Vector3 prevScale = part.Scale; | 3146 | Vector3 prevScale = part.Scale; |
2930 | prevScale.X *= x; | 3147 | prevScale.X *= x; |
@@ -2932,7 +3149,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2932 | prevScale.Z *= z; | 3149 | prevScale.Z *= z; |
2933 | part.Resize(prevScale); | 3150 | part.Resize(prevScale); |
2934 | 3151 | ||
2935 | lock (m_parts) | 3152 | lockPartsForRead(true); |
2936 | { | 3153 | { |
2937 | foreach (SceneObjectPart obPart in m_parts.Values) | 3154 | foreach (SceneObjectPart obPart in m_parts.Values) |
2938 | { | 3155 | { |
@@ -2954,6 +3171,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2954 | obPart.StoreUndoState(); | 3171 | obPart.StoreUndoState(); |
2955 | } | 3172 | } |
2956 | } | 3173 | } |
3174 | lockPartsForRead(false); | ||
2957 | 3175 | ||
2958 | if (part.PhysActor != null) | 3176 | if (part.PhysActor != null) |
2959 | { | 3177 | { |
@@ -3056,7 +3274,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3056 | axDiff *= Quaternion.Inverse(partRotation); | 3274 | axDiff *= Quaternion.Inverse(partRotation); |
3057 | diff = axDiff; | 3275 | diff = axDiff; |
3058 | 3276 | ||
3059 | lock (m_parts) | 3277 | lockPartsForRead(true); |
3060 | { | 3278 | { |
3061 | foreach (SceneObjectPart obPart in m_parts.Values) | 3279 | foreach (SceneObjectPart obPart in m_parts.Values) |
3062 | { | 3280 | { |
@@ -3066,6 +3284,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3066 | } | 3284 | } |
3067 | } | 3285 | } |
3068 | } | 3286 | } |
3287 | lockPartsForRead(false); | ||
3069 | 3288 | ||
3070 | AbsolutePosition = newPos; | 3289 | AbsolutePosition = newPos; |
3071 | 3290 | ||
@@ -3199,25 +3418,25 @@ namespace OpenSim.Region.Framework.Scenes | |||
3199 | m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); | 3418 | m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); |
3200 | } | 3419 | } |
3201 | 3420 | ||
3202 | lock (m_parts) | 3421 | lockPartsForRead(true); |
3422 | |||
3423 | foreach (SceneObjectPart prim in m_parts.Values) | ||
3203 | { | 3424 | { |
3204 | foreach (SceneObjectPart prim in m_parts.Values) | 3425 | if (prim.UUID != m_rootPart.UUID) |
3205 | { | 3426 | { |
3206 | if (prim.UUID != m_rootPart.UUID) | 3427 | prim.IgnoreUndoUpdate = true; |
3207 | { | 3428 | Vector3 axPos = prim.OffsetPosition; |
3208 | prim.IgnoreUndoUpdate = true; | 3429 | axPos *= oldParentRot; |
3209 | Vector3 axPos = prim.OffsetPosition; | 3430 | axPos *= Quaternion.Inverse(axRot); |
3210 | axPos *= oldParentRot; | 3431 | prim.OffsetPosition = axPos; |
3211 | axPos *= Quaternion.Inverse(axRot); | 3432 | Quaternion primsRot = prim.RotationOffset; |
3212 | prim.OffsetPosition = axPos; | 3433 | Quaternion newRot = primsRot * oldParentRot; |
3213 | Quaternion primsRot = prim.RotationOffset; | 3434 | newRot *= Quaternion.Inverse(axRot); |
3214 | Quaternion newRot = primsRot * oldParentRot; | 3435 | prim.RotationOffset = newRot; |
3215 | newRot *= Quaternion.Inverse(axRot); | 3436 | prim.ScheduleTerseUpdate(); |
3216 | prim.RotationOffset = newRot; | ||
3217 | prim.ScheduleTerseUpdate(); | ||
3218 | } | ||
3219 | } | 3437 | } |
3220 | } | 3438 | } |
3439 | |||
3221 | foreach (SceneObjectPart childpart in Children.Values) | 3440 | foreach (SceneObjectPart childpart in Children.Values) |
3222 | { | 3441 | { |
3223 | if (childpart != m_rootPart) | 3442 | if (childpart != m_rootPart) |
@@ -3226,6 +3445,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
3226 | childpart.StoreUndoState(); | 3445 | childpart.StoreUndoState(); |
3227 | } | 3446 | } |
3228 | } | 3447 | } |
3448 | |||
3449 | lockPartsForRead(false); | ||
3450 | |||
3229 | m_rootPart.ScheduleTerseUpdate(); | 3451 | m_rootPart.ScheduleTerseUpdate(); |
3230 | } | 3452 | } |
3231 | 3453 | ||
@@ -3347,7 +3569,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3347 | if (atTargets.Count > 0) | 3569 | if (atTargets.Count > 0) |
3348 | { | 3570 | { |
3349 | uint[] localids = new uint[0]; | 3571 | uint[] localids = new uint[0]; |
3350 | lock (m_parts) | 3572 | lockPartsForRead(true); |
3351 | { | 3573 | { |
3352 | localids = new uint[m_parts.Count]; | 3574 | localids = new uint[m_parts.Count]; |
3353 | int cntr = 0; | 3575 | int cntr = 0; |
@@ -3357,6 +3579,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3357 | cntr++; | 3579 | cntr++; |
3358 | } | 3580 | } |
3359 | } | 3581 | } |
3582 | lockPartsForRead(false); | ||
3360 | 3583 | ||
3361 | for (int ctr = 0; ctr < localids.Length; ctr++) | 3584 | for (int ctr = 0; ctr < localids.Length; ctr++) |
3362 | { | 3585 | { |
@@ -3375,7 +3598,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3375 | { | 3598 | { |
3376 | //trigger not_at_target | 3599 | //trigger not_at_target |
3377 | uint[] localids = new uint[0]; | 3600 | uint[] localids = new uint[0]; |
3378 | lock (m_parts) | 3601 | lockPartsForRead(true); |
3379 | { | 3602 | { |
3380 | localids = new uint[m_parts.Count]; | 3603 | localids = new uint[m_parts.Count]; |
3381 | int cntr = 0; | 3604 | int cntr = 0; |
@@ -3385,7 +3608,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
3385 | cntr++; | 3608 | cntr++; |
3386 | } | 3609 | } |
3387 | } | 3610 | } |
3388 | 3611 | lockPartsForRead(false); | |
3612 | |||
3389 | for (int ctr = 0; ctr < localids.Length; ctr++) | 3613 | for (int ctr = 0; ctr < localids.Length; ctr++) |
3390 | { | 3614 | { |
3391 | m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]); | 3615 | m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]); |
@@ -3477,19 +3701,20 @@ namespace OpenSim.Region.Framework.Scenes | |||
3477 | public float GetMass() | 3701 | public float GetMass() |
3478 | { | 3702 | { |
3479 | float retmass = 0f; | 3703 | float retmass = 0f; |
3480 | lock (m_parts) | 3704 | lockPartsForRead(true); |
3481 | { | 3705 | { |
3482 | foreach (SceneObjectPart part in m_parts.Values) | 3706 | foreach (SceneObjectPart part in m_parts.Values) |
3483 | { | 3707 | { |
3484 | retmass += part.GetMass(); | 3708 | retmass += part.GetMass(); |
3485 | } | 3709 | } |
3486 | } | 3710 | } |
3711 | lockPartsForRead(false); | ||
3487 | return retmass; | 3712 | return retmass; |
3488 | } | 3713 | } |
3489 | 3714 | ||
3490 | public void CheckSculptAndLoad() | 3715 | public void CheckSculptAndLoad() |
3491 | { | 3716 | { |
3492 | lock (m_parts) | 3717 | lockPartsForRead(true); |
3493 | { | 3718 | { |
3494 | if (!IsDeleted) | 3719 | if (!IsDeleted) |
3495 | { | 3720 | { |
@@ -3514,6 +3739,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3514 | } | 3739 | } |
3515 | } | 3740 | } |
3516 | } | 3741 | } |
3742 | lockPartsForRead(false); | ||
3517 | } | 3743 | } |
3518 | 3744 | ||
3519 | protected void AssetReceived(string id, Object sender, AssetBase asset) | 3745 | protected void AssetReceived(string id, Object sender, AssetBase asset) |
@@ -3534,7 +3760,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3534 | /// <param name="client"></param> | 3760 | /// <param name="client"></param> |
3535 | public void SetGroup(UUID GroupID, IClientAPI client) | 3761 | public void SetGroup(UUID GroupID, IClientAPI client) |
3536 | { | 3762 | { |
3537 | lock (m_parts) | 3763 | lockPartsForRead(true); |
3538 | { | 3764 | { |
3539 | foreach (SceneObjectPart part in m_parts.Values) | 3765 | foreach (SceneObjectPart part in m_parts.Values) |
3540 | { | 3766 | { |
@@ -3544,6 +3770,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3544 | 3770 | ||
3545 | HasGroupChanged = true; | 3771 | HasGroupChanged = true; |
3546 | } | 3772 | } |
3773 | lockPartsForRead(false); | ||
3547 | 3774 | ||
3548 | // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled | 3775 | // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled |
3549 | // for the same object with very different properties. The caller must schedule the update. | 3776 | // for the same object with very different properties. The caller must schedule the update. |
@@ -3565,11 +3792,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
3565 | 3792 | ||
3566 | public void SetAttachmentPoint(byte point) | 3793 | public void SetAttachmentPoint(byte point) |
3567 | { | 3794 | { |
3568 | lock (m_parts) | 3795 | lockPartsForRead(true); |
3569 | { | 3796 | { |
3570 | foreach (SceneObjectPart part in m_parts.Values) | 3797 | foreach (SceneObjectPart part in m_parts.Values) |
3571 | part.SetAttachmentPoint(point); | 3798 | part.SetAttachmentPoint(point); |
3572 | } | 3799 | } |
3800 | lockPartsForRead(false); | ||
3573 | } | 3801 | } |
3574 | 3802 | ||
3575 | #region ISceneObject | 3803 | #region ISceneObject |