diff options
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs')
-rw-r--r-- | OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 601 |
1 files changed, 392 insertions, 209 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 8aefd50..3895d93 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | |||
@@ -106,6 +106,72 @@ namespace OpenSim.Region.Framework.Scenes | |||
106 | private bool m_hasGroupChanged = false; | 106 | private bool m_hasGroupChanged = false; |
107 | private long timeFirstChanged; | 107 | private long timeFirstChanged; |
108 | private long timeLastChanged; | 108 | private long timeLastChanged; |
109 | private System.Threading.ReaderWriterLockSlim m_partsLock = new System.Threading.ReaderWriterLockSlim(); | ||
110 | |||
111 | public void lockPartsForRead(bool locked) | ||
112 | { | ||
113 | if (locked) | ||
114 | { | ||
115 | if (m_partsLock.RecursiveReadCount > 0) | ||
116 | { | ||
117 | 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."); | ||
118 | m_partsLock.ExitReadLock(); | ||
119 | } | ||
120 | if (m_partsLock.RecursiveWriteCount > 0) | ||
121 | { | ||
122 | m_log.Error("[SceneObjectGroup.m_parts] Recursive read lock requested. This should not happen and means something needs to be fixed."); | ||
123 | m_partsLock.ExitWriteLock(); | ||
124 | } | ||
125 | |||
126 | while (!m_partsLock.TryEnterReadLock(60000)) | ||
127 | { | ||
128 | 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."); | ||
129 | if (m_partsLock.IsWriteLockHeld) | ||
130 | { | ||
131 | m_partsLock = new System.Threading.ReaderWriterLockSlim(); | ||
132 | } | ||
133 | } | ||
134 | } | ||
135 | else | ||
136 | { | ||
137 | if (m_partsLock.RecursiveReadCount > 0) | ||
138 | { | ||
139 | m_partsLock.ExitReadLock(); | ||
140 | } | ||
141 | } | ||
142 | } | ||
143 | public void lockPartsForWrite(bool locked) | ||
144 | { | ||
145 | if (locked) | ||
146 | { | ||
147 | if (m_partsLock.RecursiveReadCount > 0) | ||
148 | { | ||
149 | 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."); | ||
150 | m_partsLock.ExitReadLock(); | ||
151 | } | ||
152 | if (m_partsLock.RecursiveWriteCount > 0) | ||
153 | { | ||
154 | m_log.Error("[SceneObjectGroup.m_parts] Recursive write lock requested. This should not happen and means something needs to be fixed."); | ||
155 | m_partsLock.ExitWriteLock(); | ||
156 | } | ||
157 | |||
158 | while (!m_partsLock.TryEnterWriteLock(60000)) | ||
159 | { | ||
160 | 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."); | ||
161 | if (m_partsLock.IsWriteLockHeld) | ||
162 | { | ||
163 | m_partsLock = new System.Threading.ReaderWriterLockSlim(); | ||
164 | } | ||
165 | } | ||
166 | } | ||
167 | else | ||
168 | { | ||
169 | if (m_partsLock.RecursiveWriteCount > 0) | ||
170 | { | ||
171 | m_partsLock.ExitWriteLock(); | ||
172 | } | ||
173 | } | ||
174 | } | ||
109 | 175 | ||
110 | public bool HasGroupChanged | 176 | public bool HasGroupChanged |
111 | { | 177 | { |
@@ -258,13 +324,16 @@ namespace OpenSim.Region.Framework.Scenes | |||
258 | set | 324 | set |
259 | { | 325 | { |
260 | m_regionHandle = value; | 326 | m_regionHandle = value; |
261 | lock (m_parts) | 327 | lockPartsForRead(true); |
262 | { | 328 | { |
263 | foreach (SceneObjectPart part in m_parts.Values) | 329 | foreach (SceneObjectPart part in m_parts.Values) |
264 | { | 330 | { |
331 | |||
265 | part.RegionHandle = m_regionHandle; | 332 | part.RegionHandle = m_regionHandle; |
333 | |||
266 | } | 334 | } |
267 | } | 335 | } |
336 | lockPartsForRead(false); | ||
268 | } | 337 | } |
269 | } | 338 | } |
270 | 339 | ||
@@ -298,6 +367,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
298 | { | 367 | { |
299 | m_scene.CrossPrimGroupIntoNewRegion(val, this, true); | 368 | m_scene.CrossPrimGroupIntoNewRegion(val, this, true); |
300 | } | 369 | } |
370 | |||
371 | lockPartsForRead(true); | ||
372 | |||
301 | if (RootPart.GetStatusSandbox()) | 373 | if (RootPart.GetStatusSandbox()) |
302 | { | 374 | { |
303 | if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) | 375 | if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) |
@@ -305,17 +377,18 @@ namespace OpenSim.Region.Framework.Scenes | |||
305 | RootPart.ScriptSetPhysicsStatus(false); | 377 | RootPart.ScriptSetPhysicsStatus(false); |
306 | Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"), | 378 | Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"), |
307 | ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false); | 379 | ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false); |
380 | lockPartsForRead(false); | ||
308 | return; | 381 | return; |
309 | } | 382 | } |
310 | } | 383 | } |
311 | lock (m_parts) | 384 | |
385 | foreach (SceneObjectPart part in m_parts.Values) | ||
312 | { | 386 | { |
313 | foreach (SceneObjectPart part in m_parts.Values) | 387 | part.GroupPosition = val; |
314 | { | ||
315 | part.GroupPosition = val; | ||
316 | } | ||
317 | } | 388 | } |
318 | 389 | ||
390 | lockPartsForRead(false); | ||
391 | |||
319 | //if (m_rootPart.PhysActor != null) | 392 | //if (m_rootPart.PhysActor != null) |
320 | //{ | 393 | //{ |
321 | //m_rootPart.PhysActor.Position = | 394 | //m_rootPart.PhysActor.Position = |
@@ -504,13 +577,16 @@ namespace OpenSim.Region.Framework.Scenes | |||
504 | 577 | ||
505 | public void SetFromItemID(UUID AssetId) | 578 | public void SetFromItemID(UUID AssetId) |
506 | { | 579 | { |
507 | lock (m_parts) | 580 | lockPartsForRead(true); |
508 | { | 581 | { |
509 | foreach (SceneObjectPart part in m_parts.Values) | 582 | foreach (SceneObjectPart part in m_parts.Values) |
510 | { | 583 | { |
584 | |||
511 | part.FromItemID = AssetId; | 585 | part.FromItemID = AssetId; |
586 | |||
512 | } | 587 | } |
513 | } | 588 | } |
589 | lockPartsForRead(false); | ||
514 | } | 590 | } |
515 | 591 | ||
516 | public UUID GetFromItemID() | 592 | public UUID GetFromItemID() |
@@ -579,10 +655,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
579 | Vector3 maxScale = Vector3.Zero; | 655 | Vector3 maxScale = Vector3.Zero; |
580 | Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f); | 656 | Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f); |
581 | 657 | ||
582 | lock (m_parts) | 658 | lockPartsForRead(true); |
583 | { | 659 | { |
584 | foreach (SceneObjectPart part in m_parts.Values) | 660 | foreach (SceneObjectPart part in m_parts.Values) |
585 | { | 661 | { |
662 | |||
586 | Vector3 partscale = part.Scale; | 663 | Vector3 partscale = part.Scale; |
587 | Vector3 partoffset = part.OffsetPosition; | 664 | Vector3 partoffset = part.OffsetPosition; |
588 | 665 | ||
@@ -593,8 +670,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
593 | maxScale.X = (partscale.X + partoffset.X > maxScale.X) ? partscale.X + partoffset.X : maxScale.X; | 670 | 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; | 671 | 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; | 672 | maxScale.Z = (partscale.Z + partoffset.Z > maxScale.Z) ? partscale.Z + partoffset.Z : maxScale.Z; |
673 | |||
596 | } | 674 | } |
597 | } | 675 | } |
676 | lockPartsForRead(false); | ||
677 | |||
598 | finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X; | 678 | finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X; |
599 | finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y; | 679 | finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y; |
600 | finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z; | 680 | finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z; |
@@ -610,10 +690,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
610 | 690 | ||
611 | EntityIntersection result = new EntityIntersection(); | 691 | EntityIntersection result = new EntityIntersection(); |
612 | 692 | ||
613 | lock (m_parts) | 693 | lockPartsForRead(true); |
614 | { | 694 | { |
615 | foreach (SceneObjectPart part in m_parts.Values) | 695 | foreach (SceneObjectPart part in m_parts.Values) |
616 | { | 696 | { |
697 | |||
617 | // Temporary commented to stop compiler warning | 698 | // Temporary commented to stop compiler warning |
618 | //Vector3 partPosition = | 699 | //Vector3 partPosition = |
619 | // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z); | 700 | // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z); |
@@ -641,8 +722,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
641 | result.distance = inter.distance; | 722 | result.distance = inter.distance; |
642 | } | 723 | } |
643 | } | 724 | } |
725 | |||
644 | } | 726 | } |
645 | } | 727 | } |
728 | lockPartsForRead(false); | ||
646 | return result; | 729 | return result; |
647 | } | 730 | } |
648 | 731 | ||
@@ -655,10 +738,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
655 | public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight) | 738 | public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight) |
656 | { | 739 | { |
657 | float maxX = -256f, maxY = -256f, maxZ = -256f, minX = 256f, minY = 256f, minZ = 256f; | 740 | float maxX = -256f, maxY = -256f, maxZ = -256f, minX = 256f, minY = 256f, minZ = 256f; |
658 | lock (m_parts) | 741 | lockPartsForRead(true); |
659 | { | 742 | { |
660 | foreach (SceneObjectPart part in m_parts.Values) | 743 | foreach (SceneObjectPart part in m_parts.Values) |
661 | { | 744 | { |
745 | |||
662 | Vector3 worldPos = part.GetWorldPosition(); | 746 | Vector3 worldPos = part.GetWorldPosition(); |
663 | Vector3 offset = worldPos - AbsolutePosition; | 747 | Vector3 offset = worldPos - AbsolutePosition; |
664 | Quaternion worldRot; | 748 | Quaternion worldRot; |
@@ -717,6 +801,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
717 | backBottomRight.Y = orig.Y + (part.Scale.Y / 2); | 801 | backBottomRight.Y = orig.Y + (part.Scale.Y / 2); |
718 | backBottomRight.Z = orig.Z - (part.Scale.Z / 2); | 802 | backBottomRight.Z = orig.Z - (part.Scale.Z / 2); |
719 | 803 | ||
804 | |||
805 | |||
720 | //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z); | 806 | //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); | 807 | //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); | 808 | //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z); |
@@ -888,6 +974,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
888 | minZ = backBottomLeft.Z; | 974 | minZ = backBottomLeft.Z; |
889 | } | 975 | } |
890 | } | 976 | } |
977 | lockPartsForRead(false); | ||
891 | 978 | ||
892 | Vector3 boundingBox = new Vector3(maxX - minX, maxY - minY, maxZ - minZ); | 979 | Vector3 boundingBox = new Vector3(maxX - minX, maxY - minY, maxZ - minZ); |
893 | 980 | ||
@@ -916,17 +1003,20 @@ namespace OpenSim.Region.Framework.Scenes | |||
916 | Dictionary<UUID,string> states = new Dictionary<UUID,string>(); | 1003 | Dictionary<UUID,string> states = new Dictionary<UUID,string>(); |
917 | 1004 | ||
918 | // Capture script state while holding the lock | 1005 | // Capture script state while holding the lock |
919 | lock (m_parts) | 1006 | lockPartsForRead(true); |
920 | { | 1007 | { |
921 | foreach (SceneObjectPart part in m_parts.Values) | 1008 | foreach (SceneObjectPart part in m_parts.Values) |
922 | { | 1009 | { |
1010 | |||
923 | Dictionary<UUID,string> pstates = part.Inventory.GetScriptStates(); | 1011 | Dictionary<UUID,string> pstates = part.Inventory.GetScriptStates(); |
924 | foreach (UUID itemid in pstates.Keys) | 1012 | foreach (UUID itemid in pstates.Keys) |
925 | { | 1013 | { |
926 | states.Add(itemid, pstates[itemid]); | 1014 | states.Add(itemid, pstates[itemid]); |
927 | } | 1015 | } |
1016 | |||
928 | } | 1017 | } |
929 | } | 1018 | } |
1019 | lockPartsForRead(false); | ||
930 | 1020 | ||
931 | if (states.Count > 0) | 1021 | if (states.Count > 0) |
932 | { | 1022 | { |
@@ -1094,13 +1184,16 @@ namespace OpenSim.Region.Framework.Scenes | |||
1094 | 1184 | ||
1095 | public override void UpdateMovement() | 1185 | public override void UpdateMovement() |
1096 | { | 1186 | { |
1097 | lock (m_parts) | 1187 | lockPartsForRead(true); |
1098 | { | 1188 | { |
1099 | foreach (SceneObjectPart part in m_parts.Values) | 1189 | foreach (SceneObjectPart part in m_parts.Values) |
1100 | { | 1190 | { |
1191 | |||
1101 | part.UpdateMovement(); | 1192 | part.UpdateMovement(); |
1193 | |||
1102 | } | 1194 | } |
1103 | } | 1195 | } |
1196 | lockPartsForRead(false); | ||
1104 | } | 1197 | } |
1105 | 1198 | ||
1106 | public ushort GetTimeDilation() | 1199 | public ushort GetTimeDilation() |
@@ -1144,7 +1237,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1144 | /// <param name="part"></param> | 1237 | /// <param name="part"></param> |
1145 | public void AddPart(SceneObjectPart part) | 1238 | public void AddPart(SceneObjectPart part) |
1146 | { | 1239 | { |
1147 | lock (m_parts) | 1240 | lockPartsForWrite(true); |
1148 | { | 1241 | { |
1149 | part.SetParent(this); | 1242 | part.SetParent(this); |
1150 | m_parts.Add(part.UUID, part); | 1243 | m_parts.Add(part.UUID, part); |
@@ -1154,6 +1247,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1154 | if (part.LinkNum == 2 && RootPart != null) | 1247 | if (part.LinkNum == 2 && RootPart != null) |
1155 | RootPart.LinkNum = 1; | 1248 | RootPart.LinkNum = 1; |
1156 | } | 1249 | } |
1250 | lockPartsForWrite(false); | ||
1157 | } | 1251 | } |
1158 | 1252 | ||
1159 | /// <summary> | 1253 | /// <summary> |
@@ -1161,28 +1255,33 @@ namespace OpenSim.Region.Framework.Scenes | |||
1161 | /// </summary> | 1255 | /// </summary> |
1162 | private void UpdateParentIDs() | 1256 | private void UpdateParentIDs() |
1163 | { | 1257 | { |
1164 | lock (m_parts) | 1258 | lockPartsForRead(true); |
1165 | { | 1259 | { |
1166 | foreach (SceneObjectPart part in m_parts.Values) | 1260 | foreach (SceneObjectPart part in m_parts.Values) |
1167 | { | 1261 | { |
1262 | |||
1168 | if (part.UUID != m_rootPart.UUID) | 1263 | if (part.UUID != m_rootPart.UUID) |
1169 | { | 1264 | { |
1170 | part.ParentID = m_rootPart.LocalId; | 1265 | part.ParentID = m_rootPart.LocalId; |
1171 | } | 1266 | } |
1267 | |||
1172 | } | 1268 | } |
1173 | } | 1269 | } |
1270 | lockPartsForRead(false); | ||
1174 | } | 1271 | } |
1175 | 1272 | ||
1176 | public void RegenerateFullIDs() | 1273 | public void RegenerateFullIDs() |
1177 | { | 1274 | { |
1178 | lock (m_parts) | 1275 | lockPartsForRead(true); |
1179 | { | 1276 | { |
1180 | foreach (SceneObjectPart part in m_parts.Values) | 1277 | foreach (SceneObjectPart part in m_parts.Values) |
1181 | { | 1278 | { |
1279 | |||
1182 | part.UUID = UUID.Random(); | 1280 | part.UUID = UUID.Random(); |
1183 | 1281 | ||
1184 | } | 1282 | } |
1185 | } | 1283 | } |
1284 | lockPartsForRead(false); | ||
1186 | } | 1285 | } |
1187 | 1286 | ||
1188 | // helper provided for parts. | 1287 | // helper provided for parts. |
@@ -1263,27 +1362,33 @@ namespace OpenSim.Region.Framework.Scenes | |||
1263 | 1362 | ||
1264 | DetachFromBackup(); | 1363 | DetachFromBackup(); |
1265 | 1364 | ||
1266 | lock (m_parts) | 1365 | lockPartsForRead(true); |
1366 | List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values); | ||
1367 | lockPartsForRead(false); | ||
1368 | |||
1369 | foreach (SceneObjectPart part in values) | ||
1267 | { | 1370 | { |
1268 | foreach (SceneObjectPart part in m_parts.Values) | ||
1269 | { | ||
1270 | // part.Inventory.RemoveScriptInstances(); | 1371 | // part.Inventory.RemoveScriptInstances(); |
1271 | Scene.ForEachScenePresence(delegate(ScenePresence avatar) | 1372 | |
1373 | List<ScenePresence> avatars = Scene.GetScenePresences(); | ||
1374 | for (int i = 0; i < avatars.Count; i++) | ||
1375 | { | ||
1376 | if (avatars[i].ParentID == LocalId) | ||
1272 | { | 1377 | { |
1273 | if (avatar.ParentID == LocalId) | 1378 | avatars[i].StandUp(); |
1274 | { | 1379 | } |
1275 | avatar.StandUp(); | ||
1276 | } | ||
1277 | 1380 | ||
1278 | if (!silent) | 1381 | if (!silent) |
1279 | { | 1382 | { |
1280 | part.UpdateFlag = 0; | 1383 | part.UpdateFlag = 0; |
1281 | if (part == m_rootPart) | 1384 | if (part == m_rootPart) |
1282 | avatar.ControllingClient.SendKillObject(m_regionHandle, part.LocalId); | 1385 | avatars[i].ControllingClient.SendKillObject(m_regionHandle, part.LocalId); |
1283 | } | 1386 | } |
1284 | }); | ||
1285 | } | 1387 | } |
1388 | |||
1286 | } | 1389 | } |
1390 | |||
1391 | |||
1287 | } | 1392 | } |
1288 | 1393 | ||
1289 | public void AddScriptLPS(int count) | 1394 | public void AddScriptLPS(int count) |
@@ -1308,17 +1413,20 @@ namespace OpenSim.Region.Framework.Scenes | |||
1308 | 1413 | ||
1309 | scriptEvents aggregateScriptEvents=0; | 1414 | scriptEvents aggregateScriptEvents=0; |
1310 | 1415 | ||
1311 | lock (m_parts) | 1416 | lockPartsForRead(true); |
1312 | { | 1417 | { |
1313 | foreach (SceneObjectPart part in m_parts.Values) | 1418 | foreach (SceneObjectPart part in m_parts.Values) |
1314 | { | 1419 | { |
1420 | |||
1315 | if (part == null) | 1421 | if (part == null) |
1316 | continue; | 1422 | continue; |
1317 | if (part != RootPart) | 1423 | if (part != RootPart) |
1318 | part.ObjectFlags = objectflagupdate; | 1424 | part.ObjectFlags = objectflagupdate; |
1319 | aggregateScriptEvents |= part.AggregateScriptEvents; | 1425 | aggregateScriptEvents |= part.AggregateScriptEvents; |
1426 | |||
1320 | } | 1427 | } |
1321 | } | 1428 | } |
1429 | lockPartsForRead(false); | ||
1322 | 1430 | ||
1323 | m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0); | 1431 | m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0); |
1324 | m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0); | 1432 | m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0); |
@@ -1360,42 +1468,52 @@ namespace OpenSim.Region.Framework.Scenes | |||
1360 | /// <param name="m_physicalPrim"></param> | 1468 | /// <param name="m_physicalPrim"></param> |
1361 | public void ApplyPhysics(bool m_physicalPrim) | 1469 | public void ApplyPhysics(bool m_physicalPrim) |
1362 | { | 1470 | { |
1363 | lock (m_parts) | 1471 | lockPartsForRead(true); |
1472 | |||
1473 | if (m_parts.Count > 1) | ||
1364 | { | 1474 | { |
1365 | if (m_parts.Count > 1) | 1475 | List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values); |
1476 | lockPartsForRead(false); | ||
1477 | m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim); | ||
1478 | foreach (SceneObjectPart part in values) | ||
1366 | { | 1479 | { |
1367 | m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim); | 1480 | |
1368 | foreach (SceneObjectPart part in m_parts.Values) | 1481 | if (part.LocalId != m_rootPart.LocalId) |
1369 | { | 1482 | { |
1370 | if (part.LocalId != m_rootPart.LocalId) | 1483 | part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim); |
1371 | { | ||
1372 | part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim); | ||
1373 | } | ||
1374 | } | 1484 | } |
1375 | 1485 | ||
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 | } | 1486 | } |
1487 | // Hack to get the physics scene geometries in the right spot | ||
1488 | ResetChildPrimPhysicsPositions(); | ||
1489 | } | ||
1490 | else | ||
1491 | { | ||
1492 | lockPartsForRead(false); | ||
1493 | m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim); | ||
1383 | } | 1494 | } |
1384 | } | 1495 | } |
1385 | 1496 | ||
1386 | public void SetOwnerId(UUID userId) | 1497 | public void SetOwnerId(UUID userId) |
1387 | { | 1498 | { |
1388 | ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); | 1499 | ForEachPart(delegate(SceneObjectPart part) |
1500 | { | ||
1501 | |||
1502 | part.OwnerID = userId; | ||
1503 | |||
1504 | }); | ||
1389 | } | 1505 | } |
1390 | 1506 | ||
1391 | public void ForEachPart(Action<SceneObjectPart> whatToDo) | 1507 | public void ForEachPart(Action<SceneObjectPart> whatToDo) |
1392 | { | 1508 | { |
1393 | lock (m_parts) | 1509 | lockPartsForRead(true); |
1510 | List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values); | ||
1511 | lockPartsForRead(false); | ||
1512 | foreach (SceneObjectPart part in values) | ||
1394 | { | 1513 | { |
1395 | foreach (SceneObjectPart part in m_parts.Values) | 1514 | |
1396 | { | 1515 | whatToDo(part); |
1397 | whatToDo(part); | 1516 | |
1398 | } | ||
1399 | } | 1517 | } |
1400 | } | 1518 | } |
1401 | 1519 | ||
@@ -1493,10 +1611,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
1493 | RootPart.SendFullUpdate( | 1611 | RootPart.SendFullUpdate( |
1494 | remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID)); | 1612 | remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID)); |
1495 | 1613 | ||
1496 | lock (m_parts) | 1614 | lockPartsForRead(true); |
1497 | { | 1615 | { |
1498 | foreach (SceneObjectPart part in m_parts.Values) | 1616 | foreach (SceneObjectPart part in m_parts.Values) |
1499 | { | 1617 | { |
1618 | |||
1500 | if (part != RootPart) | 1619 | if (part != RootPart) |
1501 | part.SendFullUpdate( | 1620 | part.SendFullUpdate( |
1502 | remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID)); | 1621 | remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID)); |
@@ -1570,10 +1689,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
1570 | 1689 | ||
1571 | List<SceneObjectPart> partList; | 1690 | List<SceneObjectPart> partList; |
1572 | 1691 | ||
1573 | lock (m_parts) | 1692 | lockPartsForRead(true); |
1574 | { | 1693 | |
1575 | partList = new List<SceneObjectPart>(m_parts.Values); | 1694 | partList = new List<SceneObjectPart>(m_parts.Values); |
1576 | } | 1695 | |
1696 | lockPartsForRead(false); | ||
1577 | 1697 | ||
1578 | partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) | 1698 | partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) |
1579 | { | 1699 | { |
@@ -1796,13 +1916,40 @@ namespace OpenSim.Region.Framework.Scenes | |||
1796 | } | 1916 | } |
1797 | } | 1917 | } |
1798 | 1918 | ||
1919 | public void rotLookAt(Quaternion target, float strength, float damping) | ||
1920 | { | ||
1921 | SceneObjectPart rootpart = m_rootPart; | ||
1922 | if (rootpart != null) | ||
1923 | { | ||
1924 | if (IsAttachment) | ||
1925 | { | ||
1926 | /* | ||
1927 | ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar); | ||
1928 | if (avatar != null) | ||
1929 | { | ||
1930 | Rotate the Av? | ||
1931 | } */ | ||
1932 | } | ||
1933 | else | ||
1934 | { | ||
1935 | if (rootpart.PhysActor != null) | ||
1936 | { // APID must be implemented in your physics system for this to function. | ||
1937 | rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W); | ||
1938 | rootpart.PhysActor.APIDStrength = strength; | ||
1939 | rootpart.PhysActor.APIDDamping = damping; | ||
1940 | rootpart.PhysActor.APIDActive = true; | ||
1941 | } | ||
1942 | } | ||
1943 | } | ||
1944 | } | ||
1945 | |||
1799 | public void stopLookAt() | 1946 | public void stopLookAt() |
1800 | { | 1947 | { |
1801 | SceneObjectPart rootpart = m_rootPart; | 1948 | SceneObjectPart rootpart = m_rootPart; |
1802 | if (rootpart != null) | 1949 | if (rootpart != null) |
1803 | { | 1950 | { |
1804 | if (rootpart.PhysActor != null) | 1951 | if (rootpart.PhysActor != null) |
1805 | { | 1952 | { // APID must be implemented in your physics system for this to function. |
1806 | rootpart.PhysActor.APIDActive = false; | 1953 | rootpart.PhysActor.APIDActive = false; |
1807 | } | 1954 | } |
1808 | } | 1955 | } |
@@ -1870,10 +2017,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
1870 | SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); | 2017 | SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); |
1871 | newPart.SetParent(this); | 2018 | newPart.SetParent(this); |
1872 | 2019 | ||
1873 | lock (m_parts) | 2020 | lockPartsForWrite(true); |
1874 | { | 2021 | { |
1875 | m_parts.Add(newPart.UUID, newPart); | 2022 | m_parts.Add(newPart.UUID, newPart); |
1876 | } | 2023 | } |
2024 | lockPartsForWrite(false); | ||
1877 | 2025 | ||
1878 | SetPartAsNonRoot(newPart); | 2026 | SetPartAsNonRoot(newPart); |
1879 | 2027 | ||
@@ -1936,7 +2084,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1936 | //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0) | 2084 | //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0) |
1937 | // return; | 2085 | // return; |
1938 | 2086 | ||
1939 | lock (m_parts) | 2087 | lockPartsForRead(true); |
1940 | { | 2088 | { |
1941 | bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0); | 2089 | bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0); |
1942 | 2090 | ||
@@ -1956,9 +2104,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
1956 | { | 2104 | { |
1957 | if (!IsSelected) | 2105 | if (!IsSelected) |
1958 | part.UpdateLookAt(); | 2106 | part.UpdateLookAt(); |
2107 | |||
1959 | part.SendScheduledUpdates(); | 2108 | part.SendScheduledUpdates(); |
2109 | |||
1960 | } | 2110 | } |
1961 | } | 2111 | } |
2112 | lockPartsForRead(false); | ||
1962 | } | 2113 | } |
1963 | 2114 | ||
1964 | public void ScheduleFullUpdateToAvatar(ScenePresence presence) | 2115 | public void ScheduleFullUpdateToAvatar(ScenePresence presence) |
@@ -1967,27 +2118,29 @@ namespace OpenSim.Region.Framework.Scenes | |||
1967 | 2118 | ||
1968 | RootPart.AddFullUpdateToAvatar(presence); | 2119 | RootPart.AddFullUpdateToAvatar(presence); |
1969 | 2120 | ||
1970 | lock (m_parts) | 2121 | lockPartsForRead(true); |
1971 | { | 2122 | { |
1972 | foreach (SceneObjectPart part in m_parts.Values) | 2123 | foreach (SceneObjectPart part in m_parts.Values) |
1973 | { | 2124 | { |
2125 | |||
1974 | if (part != RootPart) | 2126 | if (part != RootPart) |
1975 | part.AddFullUpdateToAvatar(presence); | 2127 | part.AddFullUpdateToAvatar(presence); |
2128 | |||
1976 | } | 2129 | } |
1977 | } | 2130 | } |
2131 | lockPartsForRead(false); | ||
1978 | } | 2132 | } |
1979 | 2133 | ||
1980 | public void ScheduleTerseUpdateToAvatar(ScenePresence presence) | 2134 | public void ScheduleTerseUpdateToAvatar(ScenePresence presence) |
1981 | { | 2135 | { |
1982 | // m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1} just to avatar {2}", Name, UUID, presence.Name); | 2136 | lockPartsForRead(true); |
1983 | 2137 | ||
1984 | lock (m_parts) | 2138 | foreach (SceneObjectPart part in m_parts.Values) |
1985 | { | 2139 | { |
1986 | foreach (SceneObjectPart part in m_parts.Values) | 2140 | part.AddTerseUpdateToAvatar(presence); |
1987 | { | ||
1988 | part.AddTerseUpdateToAvatar(presence); | ||
1989 | } | ||
1990 | } | 2141 | } |
2142 | |||
2143 | lockPartsForRead(false); | ||
1991 | } | 2144 | } |
1992 | 2145 | ||
1993 | /// <summary> | 2146 | /// <summary> |
@@ -2000,14 +2153,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
2000 | checkAtTargets(); | 2153 | checkAtTargets(); |
2001 | RootPart.ScheduleFullUpdate(); | 2154 | RootPart.ScheduleFullUpdate(); |
2002 | 2155 | ||
2003 | lock (m_parts) | 2156 | lockPartsForRead(true); |
2004 | { | 2157 | { |
2005 | foreach (SceneObjectPart part in m_parts.Values) | 2158 | foreach (SceneObjectPart part in m_parts.Values) |
2006 | { | 2159 | { |
2160 | |||
2007 | if (part != RootPart) | 2161 | if (part != RootPart) |
2008 | part.ScheduleFullUpdate(); | 2162 | part.ScheduleFullUpdate(); |
2163 | |||
2009 | } | 2164 | } |
2010 | } | 2165 | } |
2166 | lockPartsForRead(false); | ||
2011 | } | 2167 | } |
2012 | 2168 | ||
2013 | /// <summary> | 2169 | /// <summary> |
@@ -2015,15 +2171,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
2015 | /// </summary> | 2171 | /// </summary> |
2016 | public void ScheduleGroupForTerseUpdate() | 2172 | public void ScheduleGroupForTerseUpdate() |
2017 | { | 2173 | { |
2018 | // m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1}", Name, UUID); | 2174 | lockPartsForRead(true); |
2019 | 2175 | ||
2020 | lock (m_parts) | 2176 | foreach (SceneObjectPart part in m_parts.Values) |
2021 | { | 2177 | { |
2022 | foreach (SceneObjectPart part in m_parts.Values) | 2178 | part.ScheduleTerseUpdate(); |
2023 | { | ||
2024 | part.ScheduleTerseUpdate(); | ||
2025 | } | ||
2026 | } | 2179 | } |
2180 | |||
2181 | lockPartsForRead(false); | ||
2027 | } | 2182 | } |
2028 | 2183 | ||
2029 | /// <summary> | 2184 | /// <summary> |
@@ -2038,14 +2193,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
2038 | 2193 | ||
2039 | RootPart.SendFullUpdateToAllClients(); | 2194 | RootPart.SendFullUpdateToAllClients(); |
2040 | 2195 | ||
2041 | lock (m_parts) | 2196 | lockPartsForRead(true); |
2042 | { | 2197 | { |
2043 | foreach (SceneObjectPart part in m_parts.Values) | 2198 | foreach (SceneObjectPart part in m_parts.Values) |
2044 | { | 2199 | { |
2200 | |||
2045 | if (part != RootPart) | 2201 | if (part != RootPart) |
2046 | part.SendFullUpdateToAllClients(); | 2202 | part.SendFullUpdateToAllClients(); |
2203 | |||
2047 | } | 2204 | } |
2048 | } | 2205 | } |
2206 | lockPartsForRead(false); | ||
2049 | } | 2207 | } |
2050 | 2208 | ||
2051 | /// <summary> | 2209 | /// <summary> |
@@ -2077,14 +2235,15 @@ namespace OpenSim.Region.Framework.Scenes | |||
2077 | { | 2235 | { |
2078 | if (IsDeleted) | 2236 | if (IsDeleted) |
2079 | return; | 2237 | return; |
2080 | 2238 | ||
2081 | lock (m_parts) | 2239 | lockPartsForRead(true); |
2082 | { | 2240 | { |
2083 | foreach (SceneObjectPart part in m_parts.Values) | 2241 | foreach (SceneObjectPart part in m_parts.Values) |
2084 | { | 2242 | { |
2085 | part.SendTerseUpdateToAllClients(); | 2243 | part.SendTerseUpdateToAllClients(); |
2086 | } | 2244 | } |
2087 | } | 2245 | } |
2246 | lockPartsForRead(false); | ||
2088 | } | 2247 | } |
2089 | 2248 | ||
2090 | #endregion | 2249 | #endregion |
@@ -2098,16 +2257,18 @@ namespace OpenSim.Region.Framework.Scenes | |||
2098 | /// <returns>null if no child part with that linknum or child part</returns> | 2257 | /// <returns>null if no child part with that linknum or child part</returns> |
2099 | public SceneObjectPart GetLinkNumPart(int linknum) | 2258 | public SceneObjectPart GetLinkNumPart(int linknum) |
2100 | { | 2259 | { |
2101 | lock (m_parts) | 2260 | lockPartsForRead(true); |
2102 | { | 2261 | { |
2103 | foreach (SceneObjectPart part in m_parts.Values) | 2262 | foreach (SceneObjectPart part in m_parts.Values) |
2104 | { | 2263 | { |
2105 | if (part.LinkNum == linknum) | 2264 | if (part.LinkNum == linknum) |
2106 | { | 2265 | { |
2266 | lockPartsForRead(false); | ||
2107 | return part; | 2267 | return part; |
2108 | } | 2268 | } |
2109 | } | 2269 | } |
2110 | } | 2270 | } |
2271 | lockPartsForRead(false); | ||
2111 | 2272 | ||
2112 | return null; | 2273 | return null; |
2113 | } | 2274 | } |
@@ -2135,17 +2296,19 @@ namespace OpenSim.Region.Framework.Scenes | |||
2135 | public SceneObjectPart GetChildPart(uint localID) | 2296 | public SceneObjectPart GetChildPart(uint localID) |
2136 | { | 2297 | { |
2137 | //m_log.DebugFormat("Entered looking for {0}", localID); | 2298 | //m_log.DebugFormat("Entered looking for {0}", localID); |
2138 | lock (m_parts) | 2299 | lockPartsForRead(true); |
2139 | { | 2300 | { |
2140 | foreach (SceneObjectPart part in m_parts.Values) | 2301 | foreach (SceneObjectPart part in m_parts.Values) |
2141 | { | 2302 | { |
2142 | //m_log.DebugFormat("Found {0}", part.LocalId); | 2303 | //m_log.DebugFormat("Found {0}", part.LocalId); |
2143 | if (part.LocalId == localID) | 2304 | if (part.LocalId == localID) |
2144 | { | 2305 | { |
2306 | lockPartsForRead(false); | ||
2145 | return part; | 2307 | return part; |
2146 | } | 2308 | } |
2147 | } | 2309 | } |
2148 | } | 2310 | } |
2311 | lockPartsForRead(false); | ||
2149 | 2312 | ||
2150 | return null; | 2313 | return null; |
2151 | } | 2314 | } |
@@ -2175,17 +2338,19 @@ namespace OpenSim.Region.Framework.Scenes | |||
2175 | public bool HasChildPrim(uint localID) | 2338 | public bool HasChildPrim(uint localID) |
2176 | { | 2339 | { |
2177 | //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID); | 2340 | //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID); |
2178 | lock (m_parts) | 2341 | lockPartsForRead(true); |
2179 | { | 2342 | { |
2180 | foreach (SceneObjectPart part in m_parts.Values) | 2343 | foreach (SceneObjectPart part in m_parts.Values) |
2181 | { | 2344 | { |
2182 | //m_log.DebugFormat("Found {0}", part.LocalId); | 2345 | //m_log.DebugFormat("Found {0}", part.LocalId); |
2183 | if (part.LocalId == localID) | 2346 | if (part.LocalId == localID) |
2184 | { | 2347 | { |
2348 | lockPartsForRead(false); | ||
2185 | return true; | 2349 | return true; |
2186 | } | 2350 | } |
2187 | } | 2351 | } |
2188 | } | 2352 | } |
2353 | lockPartsForRead(false); | ||
2189 | 2354 | ||
2190 | return false; | 2355 | return false; |
2191 | } | 2356 | } |
@@ -2235,53 +2400,57 @@ namespace OpenSim.Region.Framework.Scenes | |||
2235 | if (m_rootPart.LinkNum == 0) | 2400 | if (m_rootPart.LinkNum == 0) |
2236 | m_rootPart.LinkNum = 1; | 2401 | m_rootPart.LinkNum = 1; |
2237 | 2402 | ||
2238 | lock (m_parts) | 2403 | lockPartsForWrite(true); |
2239 | { | 2404 | |
2240 | m_parts.Add(linkPart.UUID, linkPart); | 2405 | m_parts.Add(linkPart.UUID, linkPart); |
2406 | |||
2407 | lockPartsForWrite(false); | ||
2241 | 2408 | ||
2242 | // Insert in terms of link numbers, the new links | 2409 | // Insert in terms of link numbers, the new links |
2243 | // before the current ones (with the exception of | 2410 | // before the current ones (with the exception of |
2244 | // the root prim. Shuffle the old ones up | 2411 | // the root prim. Shuffle the old ones up |
2245 | foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts) | 2412 | lockPartsForRead(true); |
2413 | foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts) | ||
2414 | { | ||
2415 | if (kvp.Value.LinkNum != 1) | ||
2246 | { | 2416 | { |
2247 | if (kvp.Value.LinkNum != 1) | 2417 | // Don't update root prim link number |
2248 | { | 2418 | kvp.Value.LinkNum += objectGroup.PrimCount; |
2249 | // Don't update root prim link number | ||
2250 | kvp.Value.LinkNum += objectGroup.PrimCount; | ||
2251 | } | ||
2252 | } | 2419 | } |
2420 | } | ||
2421 | lockPartsForRead(false); | ||
2253 | 2422 | ||
2254 | linkPart.LinkNum = 2; | 2423 | linkPart.LinkNum = 2; |
2255 | 2424 | ||
2256 | linkPart.SetParent(this); | 2425 | linkPart.SetParent(this); |
2257 | linkPart.AddFlag(PrimFlags.CreateSelected); | 2426 | linkPart.AddFlag(PrimFlags.CreateSelected); |
2258 | 2427 | ||
2259 | //if (linkPart.PhysActor != null) | 2428 | //if (linkPart.PhysActor != null) |
2260 | //{ | 2429 | //{ |
2261 | // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); | 2430 | // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); |
2262 | 2431 | ||
2263 | //linkPart.PhysActor = null; | 2432 | //linkPart.PhysActor = null; |
2264 | //} | 2433 | //} |
2265 | 2434 | ||
2266 | //TODO: rest of parts | 2435 | //TODO: rest of parts |
2267 | int linkNum = 3; | 2436 | int linkNum = 3; |
2268 | foreach (SceneObjectPart part in objectGroup.Children.Values) | 2437 | foreach (SceneObjectPart part in objectGroup.Children.Values) |
2438 | { | ||
2439 | if (part.UUID != objectGroup.m_rootPart.UUID) | ||
2269 | { | 2440 | { |
2270 | if (part.UUID != objectGroup.m_rootPart.UUID) | 2441 | LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++); |
2271 | { | ||
2272 | LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++); | ||
2273 | } | ||
2274 | part.ClearUndoState(); | ||
2275 | } | 2442 | } |
2443 | part.ClearUndoState(); | ||
2276 | } | 2444 | } |
2277 | 2445 | ||
2278 | m_scene.UnlinkSceneObject(objectGroup.UUID, true); | 2446 | m_scene.UnlinkSceneObject(objectGroup.UUID, true); |
2279 | objectGroup.m_isDeleted = true; | 2447 | objectGroup.m_isDeleted = true; |
2448 | |||
2449 | objectGroup.lockPartsForWrite(true); | ||
2280 | 2450 | ||
2281 | lock (objectGroup.m_parts) | 2451 | objectGroup.m_parts.Clear(); |
2282 | { | 2452 | |
2283 | objectGroup.m_parts.Clear(); | 2453 | objectGroup.lockPartsForWrite(false); |
2284 | } | ||
2285 | 2454 | ||
2286 | // Can't do this yet since backup still makes use of the root part without any synchronization | 2455 | // Can't do this yet since backup still makes use of the root part without any synchronization |
2287 | // objectGroup.m_rootPart = null; | 2456 | // objectGroup.m_rootPart = null; |
@@ -2351,11 +2520,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
2351 | Quaternion worldRot = linkPart.GetWorldRotation(); | 2520 | Quaternion worldRot = linkPart.GetWorldRotation(); |
2352 | 2521 | ||
2353 | // Remove the part from this object | 2522 | // Remove the part from this object |
2354 | lock (m_parts) | 2523 | lockPartsForWrite(true); |
2355 | { | 2524 | { |
2356 | m_parts.Remove(linkPart.UUID); | 2525 | m_parts.Remove(linkPart.UUID); |
2357 | } | 2526 | } |
2358 | 2527 | lockPartsForWrite(false); | |
2528 | lockPartsForRead(true); | ||
2359 | if (m_parts.Count == 1 && RootPart != null) //Single prim is left | 2529 | if (m_parts.Count == 1 && RootPart != null) //Single prim is left |
2360 | RootPart.LinkNum = 0; | 2530 | RootPart.LinkNum = 0; |
2361 | else | 2531 | else |
@@ -2366,6 +2536,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2366 | p.LinkNum--; | 2536 | p.LinkNum--; |
2367 | } | 2537 | } |
2368 | } | 2538 | } |
2539 | lockPartsForRead(false); | ||
2369 | 2540 | ||
2370 | linkPart.ParentID = 0; | 2541 | linkPart.ParentID = 0; |
2371 | linkPart.LinkNum = 0; | 2542 | linkPart.LinkNum = 0; |
@@ -2687,9 +2858,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
2687 | 2858 | ||
2688 | if (selectionPart != null) | 2859 | if (selectionPart != null) |
2689 | { | 2860 | { |
2690 | lock (m_parts) | 2861 | lockPartsForRead(true); |
2862 | List<SceneObjectPart> parts = new List<SceneObjectPart>(m_parts.Values); | ||
2863 | lockPartsForRead(false); | ||
2864 | foreach (SceneObjectPart part in parts) | ||
2691 | { | 2865 | { |
2692 | foreach (SceneObjectPart part in m_parts.Values) | 2866 | if (part.Scale.X > 10.0 || part.Scale.Y > 10.0 || part.Scale.Z > 10.0) |
2693 | { | 2867 | { |
2694 | if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax || | 2868 | if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax || |
2695 | part.Scale.Y > m_scene.RegionInfo.PhysPrimMax || | 2869 | part.Scale.Y > m_scene.RegionInfo.PhysPrimMax || |
@@ -2699,12 +2873,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
2699 | break; | 2873 | break; |
2700 | } | 2874 | } |
2701 | } | 2875 | } |
2876 | } | ||
2702 | 2877 | ||
2703 | foreach (SceneObjectPart part in m_parts.Values) | 2878 | foreach (SceneObjectPart part in parts) |
2704 | { | 2879 | { |
2705 | part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect); | 2880 | part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect); |
2706 | } | ||
2707 | } | 2881 | } |
2882 | |||
2708 | } | 2883 | } |
2709 | } | 2884 | } |
2710 | 2885 | ||
@@ -2790,11 +2965,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
2790 | scale.Y = m_scene.m_maxNonphys; | 2965 | scale.Y = m_scene.m_maxNonphys; |
2791 | if (scale.Z > m_scene.m_maxNonphys) | 2966 | if (scale.Z > m_scene.m_maxNonphys) |
2792 | scale.Z = m_scene.m_maxNonphys; | 2967 | scale.Z = m_scene.m_maxNonphys; |
2793 | |||
2794 | SceneObjectPart part = GetChildPart(localID); | 2968 | SceneObjectPart part = GetChildPart(localID); |
2795 | if (part != null) | 2969 | if (part != null) |
2796 | { | 2970 | { |
2797 | part.Resize(scale); | ||
2798 | if (part.PhysActor != null) | 2971 | if (part.PhysActor != null) |
2799 | { | 2972 | { |
2800 | if (part.PhysActor.IsPhysical) | 2973 | if (part.PhysActor.IsPhysical) |
@@ -2809,7 +2982,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2809 | part.PhysActor.Size = scale; | 2982 | part.PhysActor.Size = scale; |
2810 | m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); | 2983 | m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); |
2811 | } | 2984 | } |
2812 | //if (part.UUID != m_rootPart.UUID) | 2985 | part.Resize(scale); |
2813 | 2986 | ||
2814 | HasGroupChanged = true; | 2987 | HasGroupChanged = true; |
2815 | ScheduleGroupForFullUpdate(); | 2988 | ScheduleGroupForFullUpdate(); |
@@ -2851,73 +3024,71 @@ namespace OpenSim.Region.Framework.Scenes | |||
2851 | float y = (scale.Y / part.Scale.Y); | 3024 | float y = (scale.Y / part.Scale.Y); |
2852 | float z = (scale.Z / part.Scale.Z); | 3025 | float z = (scale.Z / part.Scale.Z); |
2853 | 3026 | ||
2854 | lock (m_parts) | 3027 | lockPartsForRead(true); |
3028 | if (x > 1.0f || y > 1.0f || z > 1.0f) | ||
2855 | { | 3029 | { |
2856 | if (x > 1.0f || y > 1.0f || z > 1.0f) | 3030 | foreach (SceneObjectPart obPart in m_parts.Values) |
2857 | { | 3031 | { |
2858 | foreach (SceneObjectPart obPart in m_parts.Values) | 3032 | if (obPart.UUID != m_rootPart.UUID) |
2859 | { | 3033 | { |
2860 | if (obPart.UUID != m_rootPart.UUID) | 3034 | Vector3 oldSize = new Vector3(obPart.Scale); |
2861 | { | 3035 | obPart.IgnoreUndoUpdate = true; |
2862 | obPart.IgnoreUndoUpdate = true; | ||
2863 | Vector3 oldSize = new Vector3(obPart.Scale); | ||
2864 | 3036 | ||
2865 | float f = 1.0f; | 3037 | float f = 1.0f; |
2866 | float a = 1.0f; | 3038 | float a = 1.0f; |
2867 | 3039 | ||
2868 | if (part.PhysActor != null && part.PhysActor.IsPhysical) | 3040 | if (part.PhysActor != null && part.PhysActor.IsPhysical) |
3041 | { | ||
3042 | if (oldSize.X*x > m_scene.m_maxPhys) | ||
2869 | { | 3043 | { |
2870 | if (oldSize.X*x > m_scene.m_maxPhys) | 3044 | f = m_scene.m_maxPhys / oldSize.X; |
2871 | { | 3045 | a = f / x; |
2872 | f = m_scene.m_maxPhys / oldSize.X; | 3046 | x *= a; |
2873 | a = f / x; | 3047 | y *= a; |
2874 | x *= a; | 3048 | 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 | } | 3049 | } |
2895 | else | 3050 | if (oldSize.Y*y > m_scene.m_maxPhys) |
3051 | { | ||
3052 | f = m_scene.m_maxPhys / oldSize.Y; | ||
3053 | a = f / y; | ||
3054 | x *= a; | ||
3055 | y *= a; | ||
3056 | z *= a; | ||
3057 | } | ||
3058 | if (oldSize.Z*z > m_scene.m_maxPhys) | ||
3059 | { | ||
3060 | f = m_scene.m_maxPhys / oldSize.Z; | ||
3061 | a = f / z; | ||
3062 | x *= a; | ||
3063 | y *= a; | ||
3064 | z *= a; | ||
3065 | } | ||
3066 | } | ||
3067 | else | ||
3068 | { | ||
3069 | if (oldSize.X*x > m_scene.m_maxNonphys) | ||
3070 | { | ||
3071 | f = m_scene.m_maxNonphys / oldSize.X; | ||
3072 | a = f / x; | ||
3073 | x *= a; | ||
3074 | y *= a; | ||
3075 | z *= a; | ||
3076 | } | ||
3077 | if (oldSize.Y*y > m_scene.m_maxNonphys) | ||
2896 | { | 3078 | { |
2897 | if (oldSize.X*x > m_scene.m_maxNonphys) | 3079 | f = m_scene.m_maxNonphys / oldSize.Y; |
2898 | { | 3080 | a = f / y; |
2899 | f = m_scene.m_maxNonphys / oldSize.X; | 3081 | x *= a; |
2900 | a = f / x; | 3082 | y *= a; |
2901 | x *= a; | 3083 | z *= a; |
2902 | y *= a; | 3084 | } |
2903 | z *= a; | 3085 | if (oldSize.Z*z > m_scene.m_maxNonphys) |
2904 | } | 3086 | { |
2905 | if (oldSize.Y*y > m_scene.m_maxNonphys) | 3087 | f = m_scene.m_maxNonphys / oldSize.Z; |
2906 | { | 3088 | a = f / z; |
2907 | f = m_scene.m_maxNonphys / oldSize.Y; | 3089 | x *= a; |
2908 | a = f / y; | 3090 | y *= a; |
2909 | x *= a; | 3091 | z *= a; |
2910 | y *= a; | ||
2911 | z *= a; | ||
2912 | } | ||
2913 | if (oldSize.Z*z > m_scene.m_maxNonphys) | ||
2914 | { | ||
2915 | f = m_scene.m_maxNonphys / oldSize.Z; | ||
2916 | a = f / z; | ||
2917 | x *= a; | ||
2918 | y *= a; | ||
2919 | z *= a; | ||
2920 | } | ||
2921 | } | 3092 | } |
2922 | obPart.IgnoreUndoUpdate = false; | 3093 | obPart.IgnoreUndoUpdate = false; |
2923 | obPart.StoreUndoState(); | 3094 | obPart.StoreUndoState(); |
@@ -2925,6 +3096,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2925 | } | 3096 | } |
2926 | } | 3097 | } |
2927 | } | 3098 | } |
3099 | lockPartsForRead(false); | ||
2928 | 3100 | ||
2929 | Vector3 prevScale = part.Scale; | 3101 | Vector3 prevScale = part.Scale; |
2930 | prevScale.X *= x; | 3102 | prevScale.X *= x; |
@@ -2932,7 +3104,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2932 | prevScale.Z *= z; | 3104 | prevScale.Z *= z; |
2933 | part.Resize(prevScale); | 3105 | part.Resize(prevScale); |
2934 | 3106 | ||
2935 | lock (m_parts) | 3107 | lockPartsForRead(true); |
2936 | { | 3108 | { |
2937 | foreach (SceneObjectPart obPart in m_parts.Values) | 3109 | foreach (SceneObjectPart obPart in m_parts.Values) |
2938 | { | 3110 | { |
@@ -2954,6 +3126,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2954 | obPart.StoreUndoState(); | 3126 | obPart.StoreUndoState(); |
2955 | } | 3127 | } |
2956 | } | 3128 | } |
3129 | lockPartsForRead(false); | ||
2957 | 3130 | ||
2958 | if (part.PhysActor != null) | 3131 | if (part.PhysActor != null) |
2959 | { | 3132 | { |
@@ -3056,7 +3229,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3056 | axDiff *= Quaternion.Inverse(partRotation); | 3229 | axDiff *= Quaternion.Inverse(partRotation); |
3057 | diff = axDiff; | 3230 | diff = axDiff; |
3058 | 3231 | ||
3059 | lock (m_parts) | 3232 | lockPartsForRead(true); |
3060 | { | 3233 | { |
3061 | foreach (SceneObjectPart obPart in m_parts.Values) | 3234 | foreach (SceneObjectPart obPart in m_parts.Values) |
3062 | { | 3235 | { |
@@ -3066,6 +3239,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3066 | } | 3239 | } |
3067 | } | 3240 | } |
3068 | } | 3241 | } |
3242 | lockPartsForRead(false); | ||
3069 | 3243 | ||
3070 | AbsolutePosition = newPos; | 3244 | AbsolutePosition = newPos; |
3071 | 3245 | ||
@@ -3199,25 +3373,25 @@ namespace OpenSim.Region.Framework.Scenes | |||
3199 | m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); | 3373 | m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); |
3200 | } | 3374 | } |
3201 | 3375 | ||
3202 | lock (m_parts) | 3376 | lockPartsForRead(true); |
3377 | |||
3378 | foreach (SceneObjectPart prim in m_parts.Values) | ||
3203 | { | 3379 | { |
3204 | foreach (SceneObjectPart prim in m_parts.Values) | 3380 | if (prim.UUID != m_rootPart.UUID) |
3205 | { | 3381 | { |
3206 | if (prim.UUID != m_rootPart.UUID) | 3382 | prim.IgnoreUndoUpdate = true; |
3207 | { | 3383 | Vector3 axPos = prim.OffsetPosition; |
3208 | prim.IgnoreUndoUpdate = true; | 3384 | axPos *= oldParentRot; |
3209 | Vector3 axPos = prim.OffsetPosition; | 3385 | axPos *= Quaternion.Inverse(axRot); |
3210 | axPos *= oldParentRot; | 3386 | prim.OffsetPosition = axPos; |
3211 | axPos *= Quaternion.Inverse(axRot); | 3387 | Quaternion primsRot = prim.RotationOffset; |
3212 | prim.OffsetPosition = axPos; | 3388 | Quaternion newRot = primsRot * oldParentRot; |
3213 | Quaternion primsRot = prim.RotationOffset; | 3389 | newRot *= Quaternion.Inverse(axRot); |
3214 | Quaternion newRot = primsRot * oldParentRot; | 3390 | prim.RotationOffset = newRot; |
3215 | newRot *= Quaternion.Inverse(axRot); | 3391 | prim.ScheduleTerseUpdate(); |
3216 | prim.RotationOffset = newRot; | ||
3217 | prim.ScheduleTerseUpdate(); | ||
3218 | } | ||
3219 | } | 3392 | } |
3220 | } | 3393 | } |
3394 | |||
3221 | foreach (SceneObjectPart childpart in Children.Values) | 3395 | foreach (SceneObjectPart childpart in Children.Values) |
3222 | { | 3396 | { |
3223 | if (childpart != m_rootPart) | 3397 | if (childpart != m_rootPart) |
@@ -3226,6 +3400,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
3226 | childpart.StoreUndoState(); | 3400 | childpart.StoreUndoState(); |
3227 | } | 3401 | } |
3228 | } | 3402 | } |
3403 | |||
3404 | lockPartsForRead(false); | ||
3405 | |||
3229 | m_rootPart.ScheduleTerseUpdate(); | 3406 | m_rootPart.ScheduleTerseUpdate(); |
3230 | } | 3407 | } |
3231 | 3408 | ||
@@ -3347,7 +3524,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3347 | if (atTargets.Count > 0) | 3524 | if (atTargets.Count > 0) |
3348 | { | 3525 | { |
3349 | uint[] localids = new uint[0]; | 3526 | uint[] localids = new uint[0]; |
3350 | lock (m_parts) | 3527 | lockPartsForRead(true); |
3351 | { | 3528 | { |
3352 | localids = new uint[m_parts.Count]; | 3529 | localids = new uint[m_parts.Count]; |
3353 | int cntr = 0; | 3530 | int cntr = 0; |
@@ -3357,6 +3534,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3357 | cntr++; | 3534 | cntr++; |
3358 | } | 3535 | } |
3359 | } | 3536 | } |
3537 | lockPartsForRead(false); | ||
3360 | 3538 | ||
3361 | for (int ctr = 0; ctr < localids.Length; ctr++) | 3539 | for (int ctr = 0; ctr < localids.Length; ctr++) |
3362 | { | 3540 | { |
@@ -3375,7 +3553,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3375 | { | 3553 | { |
3376 | //trigger not_at_target | 3554 | //trigger not_at_target |
3377 | uint[] localids = new uint[0]; | 3555 | uint[] localids = new uint[0]; |
3378 | lock (m_parts) | 3556 | lockPartsForRead(true); |
3379 | { | 3557 | { |
3380 | localids = new uint[m_parts.Count]; | 3558 | localids = new uint[m_parts.Count]; |
3381 | int cntr = 0; | 3559 | int cntr = 0; |
@@ -3385,7 +3563,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
3385 | cntr++; | 3563 | cntr++; |
3386 | } | 3564 | } |
3387 | } | 3565 | } |
3388 | 3566 | lockPartsForRead(false); | |
3567 | |||
3389 | for (int ctr = 0; ctr < localids.Length; ctr++) | 3568 | for (int ctr = 0; ctr < localids.Length; ctr++) |
3390 | { | 3569 | { |
3391 | m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]); | 3570 | m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]); |
@@ -3477,19 +3656,20 @@ namespace OpenSim.Region.Framework.Scenes | |||
3477 | public float GetMass() | 3656 | public float GetMass() |
3478 | { | 3657 | { |
3479 | float retmass = 0f; | 3658 | float retmass = 0f; |
3480 | lock (m_parts) | 3659 | lockPartsForRead(true); |
3481 | { | 3660 | { |
3482 | foreach (SceneObjectPart part in m_parts.Values) | 3661 | foreach (SceneObjectPart part in m_parts.Values) |
3483 | { | 3662 | { |
3484 | retmass += part.GetMass(); | 3663 | retmass += part.GetMass(); |
3485 | } | 3664 | } |
3486 | } | 3665 | } |
3666 | lockPartsForRead(false); | ||
3487 | return retmass; | 3667 | return retmass; |
3488 | } | 3668 | } |
3489 | 3669 | ||
3490 | public void CheckSculptAndLoad() | 3670 | public void CheckSculptAndLoad() |
3491 | { | 3671 | { |
3492 | lock (m_parts) | 3672 | lockPartsForRead(true); |
3493 | { | 3673 | { |
3494 | if (!IsDeleted) | 3674 | if (!IsDeleted) |
3495 | { | 3675 | { |
@@ -3514,6 +3694,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3514 | } | 3694 | } |
3515 | } | 3695 | } |
3516 | } | 3696 | } |
3697 | lockPartsForRead(false); | ||
3517 | } | 3698 | } |
3518 | 3699 | ||
3519 | protected void AssetReceived(string id, Object sender, AssetBase asset) | 3700 | protected void AssetReceived(string id, Object sender, AssetBase asset) |
@@ -3534,7 +3715,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3534 | /// <param name="client"></param> | 3715 | /// <param name="client"></param> |
3535 | public void SetGroup(UUID GroupID, IClientAPI client) | 3716 | public void SetGroup(UUID GroupID, IClientAPI client) |
3536 | { | 3717 | { |
3537 | lock (m_parts) | 3718 | lockPartsForRead(true); |
3538 | { | 3719 | { |
3539 | foreach (SceneObjectPart part in m_parts.Values) | 3720 | foreach (SceneObjectPart part in m_parts.Values) |
3540 | { | 3721 | { |
@@ -3544,6 +3725,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3544 | 3725 | ||
3545 | HasGroupChanged = true; | 3726 | HasGroupChanged = true; |
3546 | } | 3727 | } |
3728 | lockPartsForRead(false); | ||
3547 | 3729 | ||
3548 | // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled | 3730 | // 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. | 3731 | // for the same object with very different properties. The caller must schedule the update. |
@@ -3565,11 +3747,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
3565 | 3747 | ||
3566 | public void SetAttachmentPoint(byte point) | 3748 | public void SetAttachmentPoint(byte point) |
3567 | { | 3749 | { |
3568 | lock (m_parts) | 3750 | lockPartsForRead(true); |
3569 | { | 3751 | { |
3570 | foreach (SceneObjectPart part in m_parts.Values) | 3752 | foreach (SceneObjectPart part in m_parts.Values) |
3571 | part.SetAttachmentPoint(point); | 3753 | part.SetAttachmentPoint(point); |
3572 | } | 3754 | } |
3755 | lockPartsForRead(false); | ||
3573 | } | 3756 | } |
3574 | 3757 | ||
3575 | #region ISceneObject | 3758 | #region ISceneObject |