diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 8fc807aea6..238ec8e863 100755 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -1913,31 +1913,36 @@ namespace OpenSim.Region.Framework.Scenes // foreach (SceneObjectPart part in prims) { - if (part != null) - { - if (part.KeyframeMotion != null) - { - part.KeyframeMotion.Stop(); - part.KeyframeMotion = null; - } - if (part.ParentGroup.PrimCount != 1) // Skip single - { - if (part.LinkNum < 2) // Root - { - rootParts.Add(part); - } - else - { - part.LastOwnerID = part.ParentGroup.RootPart.LastOwnerID; - childParts.Add(part); - } + if(part == null) + continue; + SceneObjectGroup parentSOG = part.ParentGroup; + if(parentSOG == null || + parentSOG.IsDeleted || + parentSOG.inTransit || + parentSOG.PrimCount == 1) + continue; - SceneObjectGroup group = part.ParentGroup; - if (!affectedGroups.Contains(group)) - { - affectedGroups.Add(group); - } - } + if (!affectedGroups.Contains(parentSOG)) + { + affectedGroups.Add(parentSOG); + if(parentSOG.RootPart.PhysActor != null) + parentSOG.RootPart.PhysActor.Building = true; + } + + if (part.KeyframeMotion != null) + { + part.KeyframeMotion.Stop(); + part.KeyframeMotion = null; + } + + if (part.LinkNum < 2) // Root + { + rootParts.Add(part); + } + else + { + part.LastOwnerID = part.ParentGroup.RootPart.LastOwnerID; + childParts.Add(part); } } @@ -1946,8 +1951,8 @@ namespace OpenSim.Region.Framework.Scenes foreach (SceneObjectPart child in childParts) { // Unlink all child parts from their groups - // child.ParentGroup.DelinkFromGroup(child, true); + //child.ParentGroup is now other child.ParentGroup.HasGroupChanged = true; child.ParentGroup.ScheduleGroupForFullUpdate(); } @@ -1960,74 +1965,51 @@ namespace OpenSim.Region.Framework.Scenes // However, editing linked parts and unlinking may be different // SceneObjectGroup group = root.ParentGroup; - + List newSet = new List(group.Parts); - int numChildren = newSet.Count; - if (numChildren == 1) + newSet.Remove(root); + int numChildren = newSet.Count; + if(numChildren == 0) break; - // If there are prims left in a link set, but the root is - // slated for unlink, we need to do this - // Unlink the remaining set - // - bool sendEventsToRemainder = false; - if (numChildren == 2) // only one child prim no re-link needed - sendEventsToRemainder = true; - foreach (SceneObjectPart p in newSet) - { - if (p != group.RootPart) - { - group.DelinkFromGroup(p, sendEventsToRemainder); - if (sendEventsToRemainder) // finish single child prim now - { - p.ParentGroup.HasGroupChanged = true; - p.ParentGroup.ScheduleGroupForFullUpdate(); - } - } - } + group.DelinkFromGroup(p, false); + SceneObjectPart newRoot = newSet[0]; + // If there is more than one prim remaining, we // need to re-link // - if (numChildren > 2) + if (numChildren > 1) { - // Remove old root - // - if (newSet.Contains(root)) - newSet.Remove(root); - - // Preserve link ordering - // - newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b) - { - return a.LinkNum.CompareTo(b.LinkNum); - }); - // Determine new root // - SceneObjectPart newRoot = newSet[0]; newSet.RemoveAt(0); - - foreach (SceneObjectPart newChild in newSet) - newChild.ClearUpdateSchedule(); + foreach (SceneObjectPart newChild in newSet) + newChild.ClearUpdateSchedule(); LinkObjects(newRoot, newSet); -// if (!affectedGroups.Contains(newRoot.ParentGroup)) -// affectedGroups.Add(newRoot.ParentGroup); + } + else + { + newRoot.TriggerScriptChangedEvent(Changed.LINK); + newRoot.ParentGroup.HasGroupChanged = true; + newRoot.ParentGroup.ScheduleGroupForFullUpdate(); } } - // Finally, trigger events in the roots + // trigger events in the roots // foreach (SceneObjectGroup g in affectedGroups) { + if(g.RootPart.PhysActor != null) + g.RootPart.PhysActor.Building = false; + g.AdjustChildPrimPermissions(false); // Child prims that have been unlinked and deleted will // return unless the root is deleted. This will remove them // from the database. They will be rewritten immediately, // minus the rows for the unlinked child prims. - g.AdjustChildPrimPermissions(false); m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID); g.TriggerScriptChangedEvent(Changed.LINK); g.HasGroupChanged = true; // Persist diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 17dfb85bf6..53a9441896 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -3168,10 +3168,11 @@ namespace OpenSim.Region.Framework.Scenes if (insert) { linkNum = 2; + int insertSize = objectGroup.PrimCount; foreach (SceneObjectPart part in Parts) { if (part.LinkNum > 1) - part.LinkNum++; + part.LinkNum += insertSize; } } else @@ -3200,14 +3201,14 @@ namespace OpenSim.Region.Framework.Scenes linkPart.LinkNum = linkNum++; linkPart.UpdatePrimFlags(UsesPhysics, IsTemporary, IsPhantom, IsVolumeDetect, false); - // Get a list of the SOP's in the old group in order of their linknum's. + // Get a list of the SOP's in the source group in order of their linknum's. SceneObjectPart[] ogParts = objectGroup.Parts; Array.Sort(ogParts, delegate(SceneObjectPart a, SceneObjectPart b) { return a.LinkNum - b.LinkNum; }); - // Add each of the SOP's from the old linkset to our linkset + // Add each of the SOP's from the source linkset to our linkset for (int i = 0; i < ogParts.Length; i++) { SceneObjectPart part = ogParts[i]; @@ -3415,6 +3416,110 @@ namespace OpenSim.Region.Framework.Scenes return objectGroup; } +/* working on it + public void DelinkFromGroup(List linkParts, bool sendEvents) + { +// m_log.DebugFormat( +// "[SCENE OBJECT GROUP]: Delinking part {0}, {1} from group with root part {2}, {3}", +// linkPart.Name, linkPart.UUID, RootPart.Name, RootPart.UUID); + + if(PrimCount == 1) + return; + + if (m_rootPart.PhysActor != null) + m_rootPart.PhysActor.Building = true; + + bool unlinkroot = false; + foreach(SceneObjectPart linkPart in linkParts) + { + // first we only remove child parts + if(linkPart.LocalId == m_rootPart.LocalId) + { + unlinkroot = true; + continue; + } + + lock (m_parts.SyncRoot) + if(!m_parts.Remove(linkPart.UUID)) + continue; + + linkPart.ClearUndoState(); + + Vector3 worldPos = linkPart.GetWorldPosition(); + Quaternion worldRot = linkPart.GetWorldRotation(); + + linkPart.ParentID = 0; + linkPart.LinkNum = 0; + + PhysicsActor linkPartPa = linkPart.PhysActor; + + // Remove the SOP from the physical scene. + // If the new SOG is physical, it is re-created later. + // (There is a problem here in that we have not yet told the physics + // engine about the delink. Someday, linksets should be made first + // class objects in the physics engine interface). + if (linkPartPa != null) + { + m_scene.PhysicsScene.RemovePrim(linkPartPa); + linkPart.PhysActor = null; + } + + linkPart.setGroupPosition(worldPos); + linkPart.setOffsetPosition(Vector3.Zero); + linkPart.setRotationOffset(worldRot); + + // Create a new SOG to go around this unlinked and unattached SOP + SceneObjectGroup objectGroup = new SceneObjectGroup(linkPart); + + m_scene.AddNewSceneObject(objectGroup, true); + + linkPart.Rezzed = RootPart.Rezzed; + + // this is as it seems to be in sl now + if(linkPart.PhysicsShapeType == (byte)PhysShapeType.none) + linkPart.PhysicsShapeType = linkPart.DefaultPhysicsShapeType(); // root prims can't have type none for now + + objectGroup.HasGroupChangedDueToDelink = true; + if (sendEvents) + linkPart.TriggerScriptChangedEvent(Changed.LINK); + } + + if(unlinkroot) + { + //TODO + } + + lock (m_parts.SyncRoot) + { + SceneObjectPart[] parts = m_parts.GetArray(); + if (parts.Length == 1) + { + // Single prim left + m_rootPart.LinkNum = 0; + } + else + { + m_rootPart.LinkNum = 1; + int linknum = 2; + for (int i = 1; i < parts.Length; i++) + parts[i].LinkNum = linknum++; + } + } + + InvalidBoundsRadius(); + + if (m_rootPart.PhysActor != null) + m_rootPart.PhysActor.Building = false; + + // When we delete a group, we currently have to force persist to the database if the object id has changed + // (since delete works by deleting all rows which have a given object id) + + Scene.SimulationDataService.RemoveObject(UUID, Scene.RegionInfo.RegionID); + HasGroupChangedDueToDelink = true; + TriggerScriptChangedEvent(Changed.LINK); + return; + } +*/ /// /// Stop this object from being persisted over server restarts. ///