From a85779e477b01ce80fa5e25e28e4e129c1bb137c Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 20 Sep 2010 18:35:19 +0100 Subject: If the uuid of a SceneObjectGroup (RootPart) is changed before adding to the scene, remove the old uuid reference from m_parts as well as adding the new one. The separate remove and set operations is SOG.set_UUID() are both locked under m_parts.SyncRoot since they are logically atomic (though this isn't such an issue if the SOG isn't part of a scene) Added unit test for this behaviour. Also changed the second m_parts.AddOrReplace() to m_parts.Add(). As the old reference is now removed we never end up replacing an identical uuid. And if we replace a uuid that's already there (from a child part) then this is an error. --- .../Region/Framework/Scenes/SceneObjectGroup.cs | 8 +++-- .../Scenes/Tests/SceneObjectBasicTests.cs | 35 ++++++++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 994b9e3..b655f39 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -330,8 +330,12 @@ namespace OpenSim.Region.Framework.Scenes get { return m_rootPart.UUID; } set { - m_rootPart.UUID = value; - m_parts.AddOrReplace(value, m_rootPart); + lock (m_parts.SyncRoot) + { + m_parts.Remove(m_rootPart.UUID); + m_rootPart.UUID = value; + m_parts.Add(value, m_rootPart); + } } } diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs index 54b3260..e6ff0c0 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs @@ -189,5 +189,40 @@ namespace OpenSim.Region.Framework.Scenes.Tests // SceneObjectPart retrievedPart = scene.GetSceneObjectPart(part.LocalId); // Assert.That(retrievedPart, Is.Null); //} + + /// + /// Changing a scene object uuid changes the root part uuid. This is a valid operation if the object is not + /// in a scene and is useful if one wants to supply a UUID directly rather than use the one generated by + /// OpenSim. + /// + [Test] + public void TestChangeSceneObjectUuid() + { + string rootPartName = "rootpart"; + UUID rootPartUuid = new UUID("00000000-0000-0000-0000-000000000001"); + string childPartName = "childPart"; + UUID childPartUuid = new UUID("00000000-0000-0000-0001-000000000000"); + + SceneObjectPart rootPart + = new SceneObjectPart(UUID.Zero, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero) + { Name = rootPartName, UUID = rootPartUuid }; + SceneObjectPart linkPart + = new SceneObjectPart(UUID.Zero, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero) + { Name = childPartName, UUID = childPartUuid }; + + SceneObjectGroup sog = new SceneObjectGroup(rootPart); + sog.AddPart(linkPart); + + Assert.That(sog.UUID, Is.EqualTo(rootPartUuid)); + Assert.That(sog.RootPart.UUID, Is.EqualTo(rootPartUuid)); + Assert.That(sog.Parts.Length, Is.EqualTo(2)); + + UUID newRootPartUuid = new UUID("00000000-0000-0000-0000-000000000002"); + sog.UUID = newRootPartUuid; + + Assert.That(sog.UUID, Is.EqualTo(newRootPartUuid)); + Assert.That(sog.RootPart.UUID, Is.EqualTo(newRootPartUuid)); + Assert.That(sog.Parts.Length, Is.EqualTo(2)); + } } } -- cgit v1.1