diff options
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs')
-rw-r--r-- | OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 152 |
1 files changed, 93 insertions, 59 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 9b66fad..5a586d4 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | |||
@@ -360,7 +360,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
360 | /// </summary> | 360 | /// </summary> |
361 | public int PrimCount | 361 | public int PrimCount |
362 | { | 362 | { |
363 | get { return m_parts.Count; } | 363 | get { lock (m_parts) { return m_parts.Count; } } |
364 | } | 364 | } |
365 | 365 | ||
366 | protected Quaternion m_rotation = Quaternion.Identity; | 366 | protected Quaternion m_rotation = Quaternion.Identity; |
@@ -398,6 +398,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
398 | 398 | ||
399 | /// <value> | 399 | /// <value> |
400 | /// The parts of this scene object group. You must lock this property before using it. | 400 | /// The parts of this scene object group. You must lock this property before using it. |
401 | /// If you're doing anything other than reading values, please take a copy of the values rather than locking | ||
402 | /// the dictionary for the entirety of the operation. This increases liveness and reduces the danger of deadlock | ||
403 | /// If you want to know the number of children, consider using the PrimCount property instead | ||
401 | /// </value> | 404 | /// </value> |
402 | public Dictionary<UUID, SceneObjectPart> Children | 405 | public Dictionary<UUID, SceneObjectPart> Children |
403 | { | 406 | { |
@@ -521,7 +524,16 @@ namespace OpenSim.Region.Framework.Scenes | |||
521 | public override UUID UUID | 524 | public override UUID UUID |
522 | { | 525 | { |
523 | get { return m_rootPart.UUID; } | 526 | get { return m_rootPart.UUID; } |
524 | set { m_rootPart.UUID = value; } | 527 | set |
528 | { | ||
529 | m_rootPart.UUID = value; | ||
530 | |||
531 | lock (m_parts) | ||
532 | { | ||
533 | m_parts.Remove(m_rootPart.UUID); | ||
534 | m_parts.Add(m_rootPart.UUID, m_rootPart); | ||
535 | } | ||
536 | } | ||
525 | } | 537 | } |
526 | 538 | ||
527 | public UUID OwnerID | 539 | public UUID OwnerID |
@@ -742,21 +754,23 @@ namespace OpenSim.Region.Framework.Scenes | |||
742 | if (m_rootPart.LocalId == 0) | 754 | if (m_rootPart.LocalId == 0) |
743 | m_rootPart.LocalId = m_scene.AllocateLocalId(); | 755 | m_rootPart.LocalId = m_scene.AllocateLocalId(); |
744 | 756 | ||
745 | // No need to lock here since the object isn't yet in a scene | 757 | lock (m_parts) |
746 | foreach (SceneObjectPart part in m_parts.Values) | ||
747 | { | 758 | { |
748 | if (Object.ReferenceEquals(part, m_rootPart)) | 759 | foreach (SceneObjectPart part in m_parts.Values) |
749 | { | ||
750 | continue; | ||
751 | } | ||
752 | |||
753 | if (part.LocalId == 0) | ||
754 | { | 760 | { |
755 | part.LocalId = m_scene.AllocateLocalId(); | 761 | if (Object.ReferenceEquals(part, m_rootPart)) |
762 | { | ||
763 | continue; | ||
764 | } | ||
765 | |||
766 | if (part.LocalId == 0) | ||
767 | { | ||
768 | part.LocalId = m_scene.AllocateLocalId(); | ||
769 | } | ||
770 | |||
771 | part.ParentID = m_rootPart.LocalId; | ||
772 | //m_log.DebugFormat("[SCENE]: Given local id {0} to part {1}, linknum {2}, parent {3} {4}", part.LocalId, part.UUID, part.LinkNum, part.ParentID, part.ParentUUID); | ||
756 | } | 773 | } |
757 | |||
758 | part.ParentID = m_rootPart.LocalId; | ||
759 | //m_log.DebugFormat("[SCENE]: Given local id {0} to part {1}, linknum {2}, parent {3} {4}", part.LocalId, part.UUID, part.LinkNum, part.ParentID, part.ParentUUID); | ||
760 | } | 774 | } |
761 | 775 | ||
762 | ApplyPhysics(m_scene.m_physicalPrim); | 776 | ApplyPhysics(m_scene.m_physicalPrim); |
@@ -1238,9 +1252,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
1238 | m_rootPart.AttachedAvatar = agentID; | 1252 | m_rootPart.AttachedAvatar = agentID; |
1239 | 1253 | ||
1240 | //Anakin Lohner bug #3839 | 1254 | //Anakin Lohner bug #3839 |
1241 | foreach (SceneObjectPart p in m_parts.Values) | 1255 | lock (m_parts) |
1242 | { | 1256 | { |
1243 | p.AttachedAvatar = agentID; | 1257 | foreach (SceneObjectPart p in m_parts.Values) |
1258 | { | ||
1259 | p.AttachedAvatar = agentID; | ||
1260 | } | ||
1244 | } | 1261 | } |
1245 | 1262 | ||
1246 | if (m_rootPart.PhysActor != null) | 1263 | if (m_rootPart.PhysActor != null) |
@@ -1308,10 +1325,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
1308 | 1325 | ||
1309 | AbsolutePosition = detachedpos; | 1326 | AbsolutePosition = detachedpos; |
1310 | m_rootPart.AttachedAvatar = UUID.Zero; | 1327 | m_rootPart.AttachedAvatar = UUID.Zero; |
1311 | //Anakin Lohner bug #3839 | 1328 | |
1312 | foreach (SceneObjectPart p in m_parts.Values) | 1329 | //Anakin Lohner bug #3839 |
1330 | lock (m_parts) | ||
1313 | { | 1331 | { |
1314 | p.AttachedAvatar = UUID.Zero; | 1332 | foreach (SceneObjectPart p in m_parts.Values) |
1333 | { | ||
1334 | p.AttachedAvatar = UUID.Zero; | ||
1335 | } | ||
1315 | } | 1336 | } |
1316 | 1337 | ||
1317 | m_rootPart.SetParentLocalId(0); | 1338 | m_rootPart.SetParentLocalId(0); |
@@ -1337,10 +1358,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
1337 | } | 1358 | } |
1338 | 1359 | ||
1339 | m_rootPart.AttachedAvatar = UUID.Zero; | 1360 | m_rootPart.AttachedAvatar = UUID.Zero; |
1361 | |||
1340 | //Anakin Lohner bug #3839 | 1362 | //Anakin Lohner bug #3839 |
1341 | foreach (SceneObjectPart p in m_parts.Values) | 1363 | lock (m_parts) |
1342 | { | 1364 | { |
1343 | p.AttachedAvatar = UUID.Zero; | 1365 | foreach (SceneObjectPart p in m_parts.Values) |
1366 | { | ||
1367 | p.AttachedAvatar = UUID.Zero; | ||
1368 | } | ||
1344 | } | 1369 | } |
1345 | 1370 | ||
1346 | m_rootPart.SetParentLocalId(0); | 1371 | m_rootPart.SetParentLocalId(0); |
@@ -1406,9 +1431,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
1406 | part.ParentID = 0; | 1431 | part.ParentID = 0; |
1407 | part.LinkNum = 0; | 1432 | part.LinkNum = 0; |
1408 | 1433 | ||
1409 | // No locking required since the SOG should not be in the scene yet - one can't change root parts after | 1434 | lock (m_parts) |
1410 | // the scene object has been attached to the scene | 1435 | m_parts.Add(m_rootPart.UUID, m_rootPart); |
1411 | m_parts.Add(m_rootPart.UUID, m_rootPart); | ||
1412 | } | 1436 | } |
1413 | 1437 | ||
1414 | /// <summary> | 1438 | /// <summary> |
@@ -1928,14 +1952,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
1928 | } | 1952 | } |
1929 | 1953 | ||
1930 | /// <summary> | 1954 | /// <summary> |
1931 | /// | 1955 | /// Copy the given part as the root part of this scene object. |
1932 | /// </summary> | 1956 | /// </summary> |
1933 | /// <param name="part"></param> | 1957 | /// <param name="part"></param> |
1934 | /// <param name="cAgentID"></param> | 1958 | /// <param name="cAgentID"></param> |
1935 | /// <param name="cGroupID"></param> | 1959 | /// <param name="cGroupID"></param> |
1936 | public void CopyRootPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) | 1960 | public void CopyRootPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) |
1937 | { | 1961 | { |
1938 | SetRootPart(part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed)); | 1962 | SetRootPart(part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, 0, userExposed)); |
1939 | } | 1963 | } |
1940 | 1964 | ||
1941 | public void ScriptSetPhysicsStatus(bool UsePhysics) | 1965 | public void ScriptSetPhysicsStatus(bool UsePhysics) |
@@ -2234,14 +2258,15 @@ namespace OpenSim.Region.Framework.Scenes | |||
2234 | /// </summary> | 2258 | /// </summary> |
2235 | public void ResetIDs() | 2259 | public void ResetIDs() |
2236 | { | 2260 | { |
2237 | // As this is only ever called for prims which are not currently part of the scene (and hence | 2261 | lock (m_parts) |
2238 | // not accessible by clients), there should be no need to lock | ||
2239 | List<SceneObjectPart> partsList = new List<SceneObjectPart>(m_parts.Values); | ||
2240 | m_parts.Clear(); | ||
2241 | foreach (SceneObjectPart part in partsList) | ||
2242 | { | 2262 | { |
2243 | part.ResetIDs(part.LinkNum); // Don't change link nums | 2263 | List<SceneObjectPart> partsList = new List<SceneObjectPart>(m_parts.Values); |
2244 | m_parts.Add(part.UUID, part); | 2264 | m_parts.Clear(); |
2265 | foreach (SceneObjectPart part in partsList) | ||
2266 | { | ||
2267 | part.ResetIDs(part.LinkNum); // Don't change link nums | ||
2268 | m_parts.Add(part.UUID, part); | ||
2269 | } | ||
2245 | } | 2270 | } |
2246 | } | 2271 | } |
2247 | 2272 | ||
@@ -2283,29 +2308,29 @@ namespace OpenSim.Region.Framework.Scenes | |||
2283 | // return; | 2308 | // return; |
2284 | 2309 | ||
2285 | lockPartsForRead(true); | 2310 | lockPartsForRead(true); |
2286 | { | ||
2287 | bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0); | ||
2288 | 2311 | ||
2289 | if (UsePhysics && !AbsolutePosition.ApproxEquals(lastPhysGroupPos, 0.02f)) | 2312 | bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0); |
2290 | { | ||
2291 | m_rootPart.UpdateFlag = 1; | ||
2292 | lastPhysGroupPos = AbsolutePosition; | ||
2293 | } | ||
2294 | 2313 | ||
2295 | if (UsePhysics && !GroupRotation.ApproxEquals(lastPhysGroupRot, 0.1f)) | 2314 | if (UsePhysics && !AbsolutePosition.ApproxEquals(lastPhysGroupPos, 0.02f)) |
2296 | { | 2315 | { |
2297 | m_rootPart.UpdateFlag = 1; | 2316 | m_rootPart.UpdateFlag = 1; |
2298 | lastPhysGroupRot = GroupRotation; | 2317 | lastPhysGroupPos = AbsolutePosition; |
2299 | } | 2318 | } |
2300 | 2319 | ||
2301 | foreach (SceneObjectPart part in m_parts.Values) | 2320 | if (UsePhysics && !GroupRotation.ApproxEquals(lastPhysGroupRot, 0.1f)) |
2302 | { | 2321 | { |
2303 | if (!IsSelected) | 2322 | m_rootPart.UpdateFlag = 1; |
2304 | part.UpdateLookAt(); | 2323 | lastPhysGroupRot = GroupRotation; |
2324 | } | ||
2305 | 2325 | ||
2306 | part.SendScheduledUpdates(); | 2326 | List<SceneObjectPart> partList = null; |
2307 | 2327 | partList = new List<SceneObjectPart>(m_parts.Values); | |
2308 | } | 2328 | |
2329 | foreach (SceneObjectPart part in partList) | ||
2330 | { | ||
2331 | if (!IsSelected) | ||
2332 | part.UpdateLookAt(); | ||
2333 | part.SendScheduledUpdates(); | ||
2309 | } | 2334 | } |
2310 | lockPartsForRead(false); | 2335 | lockPartsForRead(false); |
2311 | } | 2336 | } |
@@ -2479,10 +2504,15 @@ namespace OpenSim.Region.Framework.Scenes | |||
2479 | public SceneObjectPart GetChildPart(UUID primID) | 2504 | public SceneObjectPart GetChildPart(UUID primID) |
2480 | { | 2505 | { |
2481 | SceneObjectPart childPart = null; | 2506 | SceneObjectPart childPart = null; |
2482 | if (m_parts.ContainsKey(primID)) | 2507 | |
2508 | lock (m_parts) | ||
2483 | { | 2509 | { |
2484 | childPart = m_parts[primID]; | 2510 | if (m_parts.ContainsKey(primID)) |
2511 | { | ||
2512 | childPart = m_parts[primID]; | ||
2513 | } | ||
2485 | } | 2514 | } |
2515 | |||
2486 | return childPart; | 2516 | return childPart; |
2487 | } | 2517 | } |
2488 | 2518 | ||
@@ -2519,9 +2549,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
2519 | /// <returns></returns> | 2549 | /// <returns></returns> |
2520 | public bool HasChildPrim(UUID primID) | 2550 | public bool HasChildPrim(UUID primID) |
2521 | { | 2551 | { |
2522 | if (m_parts.ContainsKey(primID)) | 2552 | lock (m_parts) |
2523 | { | 2553 | { |
2524 | return true; | 2554 | if (m_parts.ContainsKey(primID)) |
2555 | return true; | ||
2525 | } | 2556 | } |
2526 | 2557 | ||
2527 | return false; | 2558 | return false; |
@@ -3132,9 +3163,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
3132 | public void UpdatePermissions(UUID AgentID, byte field, uint localID, | 3163 | public void UpdatePermissions(UUID AgentID, byte field, uint localID, |
3133 | uint mask, byte addRemTF) | 3164 | uint mask, byte addRemTF) |
3134 | { | 3165 | { |
3135 | foreach (SceneObjectPart part in m_parts.Values) | 3166 | List<SceneObjectPart> partList = null; |
3136 | part.UpdatePermissions(AgentID, field, localID, mask, | 3167 | lock (m_parts) |
3137 | addRemTF); | 3168 | partList = new List<SceneObjectPart>(m_parts.Values); |
3169 | |||
3170 | foreach (SceneObjectPart part in partList) | ||
3171 | part.UpdatePermissions(AgentID, field, localID, mask, addRemTF); | ||
3138 | 3172 | ||
3139 | HasGroupChanged = true; | 3173 | HasGroupChanged = true; |
3140 | } | 3174 | } |