diff options
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/SceneGraph.cs')
-rw-r--r-- | OpenSim/Region/Framework/Scenes/SceneGraph.cs | 160 |
1 files changed, 81 insertions, 79 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 1e6955a..4b4461f 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs | |||
@@ -1588,106 +1588,108 @@ namespace OpenSim.Region.Framework.Scenes | |||
1588 | 1588 | ||
1589 | protected internal void DelinkObjects(List<uint> primIds, bool sendEvents) | 1589 | protected internal void DelinkObjects(List<uint> primIds, bool sendEvents) |
1590 | { | 1590 | { |
1591 | SceneObjectGroup parentPrim = null; | 1591 | List<SceneObjectPart> childParts = new List<SceneObjectPart>(); |
1592 | // Find the root prim among the prim ids we've been given | 1592 | List<SceneObjectPart> rootParts = new List<SceneObjectPart>(); |
1593 | for (int i = 0; i < primIds.Count; i++) | 1593 | List<SceneObjectGroup> affectedGroups = new List<SceneObjectGroup>(); |
1594 | // Look them all up in one go, since that is comparatively expensive | ||
1595 | // | ||
1596 | foreach (uint primID in primIds) | ||
1594 | { | 1597 | { |
1595 | // Get the group for this prim and check that it is the parent | 1598 | SceneObjectPart part = m_parentScene.GetSceneObjectPart(primID); |
1596 | parentPrim = GetGroupByPrim(primIds[i]); | 1599 | if (part != null) |
1597 | if (parentPrim != null && parentPrim.LocalId == primIds[i]) | ||
1598 | { | 1600 | { |
1599 | primIds.RemoveAt(i); | 1601 | if (part.LinkNum < 2) // Root or single |
1600 | break; | 1602 | rootParts.Add(part); |
1603 | else | ||
1604 | childParts.Add(part); | ||
1605 | |||
1606 | SceneObjectGroup group = part.ParentGroup; | ||
1607 | if (!affectedGroups.Contains(group)) | ||
1608 | affectedGroups.Add(group); | ||
1609 | } | ||
1610 | else | ||
1611 | { | ||
1612 | m_log.ErrorFormat("Viewer requested unlink of nonexistent part {0}", primID); | ||
1601 | } | 1613 | } |
1602 | } | 1614 | } |
1603 | 1615 | ||
1604 | if (parentPrim != null) | 1616 | foreach (SceneObjectPart child in childParts) |
1605 | { | 1617 | { |
1606 | foreach (uint childPrimId in primIds) | 1618 | // Unlink all child parts from their groups |
1607 | { | 1619 | // |
1608 | parentPrim.DelinkFromGroup(childPrimId, sendEvents); | 1620 | child.ParentGroup.DelinkFromGroup(child, sendEvents); |
1609 | } | 1621 | } |
1610 | 1622 | ||
1611 | if (parentPrim.Children.Count == 1) | 1623 | foreach (SceneObjectPart root in rootParts) |
1612 | { | 1624 | { |
1613 | // The link set has been completely torn down | 1625 | // In most cases, this will run only one time, and the prim |
1614 | // This is the case if you select a link set and delink | 1626 | // will be a solo prim |
1615 | // | 1627 | // However, editing linked parts and unlinking may be different |
1616 | parentPrim.RootPart.LinkNum = 0; | 1628 | // |
1617 | if (sendEvents) | 1629 | SceneObjectGroup group = root.ParentGroup; |
1618 | parentPrim.TriggerScriptChangedEvent(Changed.LINK); | 1630 | List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Children.Values); |
1619 | } | 1631 | int numChildren = group.Children.Count; |
1620 | else | 1632 | |
1633 | // If there are prims left in a link set, but the root is | ||
1634 | // slated for unlink, we need to do this | ||
1635 | // | ||
1636 | if (numChildren != 1) | ||
1621 | { | 1637 | { |
1622 | // The link set has prims remaining. This path is taken | 1638 | // Unlink the remaining set |
1623 | // when a subset of a link set's prims are selected | ||
1624 | // and the root prim is part of that selection | ||
1625 | // | 1639 | // |
1626 | List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Children.Values); | 1640 | bool sendEventsToRemainder = true; |
1641 | if (numChildren > 1) | ||
1642 | sendEventsToRemainder = false; | ||
1627 | 1643 | ||
1628 | List<uint> unlink_ids = new List<uint>(); | 1644 | foreach (SceneObjectPart p in newSet) |
1629 | foreach (SceneObjectPart unlink_part in parts) | 1645 | { |
1630 | unlink_ids.Add(unlink_part.LocalId); | 1646 | if (p != group.RootPart) |
1647 | group.DelinkFromGroup(p, sendEventsToRemainder); | ||
1648 | } | ||
1631 | 1649 | ||
1632 | // Tear down the remaining link set | 1650 | // If there is more than one prim remaining, we |
1651 | // need to re-link | ||
1633 | // | 1652 | // |
1634 | if (unlink_ids.Count == 2) | 1653 | if (numChildren > 2) |
1635 | { | 1654 | { |
1636 | DelinkObjects(unlink_ids, true); | 1655 | // Remove old root |
1637 | return; | 1656 | // |
1638 | } | 1657 | if (newSet.Contains(root)) |
1658 | newSet.Remove(root); | ||
1659 | |||
1660 | // Preserve link ordering | ||
1661 | // | ||
1662 | newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b) | ||
1663 | { | ||
1664 | return a.LinkNum.CompareTo(b.LinkNum); | ||
1665 | }); | ||
1639 | 1666 | ||
1640 | DelinkObjects(unlink_ids, false); | 1667 | // Determine new root |
1668 | // | ||
1669 | SceneObjectPart newRoot = newSet[0]; | ||
1670 | newSet.RemoveAt(0); | ||
1641 | 1671 | ||
1642 | // Send event to root prim, then we're done with it | 1672 | List<uint> linkIDs = new List<uint>(); |
1643 | parentPrim.TriggerScriptChangedEvent(Changed.LINK); | ||
1644 | 1673 | ||
1645 | unlink_ids.Remove(parentPrim.RootPart.LocalId); | 1674 | foreach (SceneObjectPart newChild in newSet) |
1675 | { | ||
1676 | newChild.UpdateFlag = 0; | ||
1677 | linkIDs.Add(newChild.LocalId); | ||
1678 | } | ||
1646 | 1679 | ||
1647 | foreach (uint localId in unlink_ids) | 1680 | LinkObjects(null, newRoot.LocalId, linkIDs); |
1648 | { | 1681 | if (!affectedGroups.Contains(newRoot.ParentGroup)) |
1649 | SceneObjectPart nr = GetSceneObjectPart(localId); | 1682 | affectedGroups.Add(newRoot.ParentGroup); |
1650 | nr.UpdateFlag = 0; | ||
1651 | } | 1683 | } |
1652 | |||
1653 | uint newRoot = unlink_ids[0]; | ||
1654 | unlink_ids.Remove(newRoot); | ||
1655 | |||
1656 | LinkObjects(null, newRoot, unlink_ids); | ||
1657 | } | 1684 | } |
1658 | } | 1685 | } |
1659 | else | ||
1660 | { | ||
1661 | // The selected prims were all child prims. Edit linked parts | ||
1662 | // without the root prim selected will get us here | ||
1663 | // | ||
1664 | List<SceneObjectGroup> parentGroups = new List<SceneObjectGroup>(); | ||
1665 | 1686 | ||
1666 | // If the first scan failed, we need to do a /deep/ scan of the linkages. This is /really/ slow | 1687 | // Finally, trigger events in the roots |
1667 | // We know that this is not the root prim now essentially, so we don't have to worry about remapping | 1688 | // |
1668 | // which one is the root prim | 1689 | foreach (SceneObjectGroup g in affectedGroups) |
1669 | bool delinkedSomething = false; | 1690 | { |
1670 | for (int i = 0; i < primIds.Count; i++) | 1691 | g.TriggerScriptChangedEvent(Changed.LINK); |
1671 | { | 1692 | g.ScheduleGroupForFullUpdate(); |
1672 | SceneObjectGroup parent = GetGroupByPrim(primIds[i]); | ||
1673 | parent.DelinkFromGroup(primIds[i]); | ||
1674 | delinkedSomething = true; | ||
1675 | if (!parentGroups.Contains(parent)) | ||
1676 | parentGroups.Add(parent); | ||
1677 | } | ||
1678 | if (!delinkedSomething) | ||
1679 | { | ||
1680 | m_log.InfoFormat("[SCENE]: " + | ||
1681 | "DelinkObjects(): Could not find a root prim out of {0} as given to a delink request!", | ||
1682 | primIds); | ||
1683 | } | ||
1684 | else | ||
1685 | { | ||
1686 | foreach (SceneObjectGroup g in parentGroups) | ||
1687 | { | ||
1688 | g.TriggerScriptChangedEvent(Changed.LINK); | ||
1689 | } | ||
1690 | } | ||
1691 | } | 1693 | } |
1692 | } | 1694 | } |
1693 | 1695 | ||