aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework/Scenes/SceneGraph.cs
diff options
context:
space:
mode:
authorMelanie Thielker2009-04-29 15:54:16 +0000
committerMelanie Thielker2009-04-29 15:54:16 +0000
commitd604cd284efc61af4616506830ff17ee52ff6e48 (patch)
tree94f26b6d1605f09b6c6ef0aef422a33b9eb77bbb /OpenSim/Region/Framework/Scenes/SceneGraph.cs
parentfixes exception thrown when client session is shutdown while (diff)
downloadopensim-SC-d604cd284efc61af4616506830ff17ee52ff6e48.zip
opensim-SC-d604cd284efc61af4616506830ff17ee52ff6e48.tar.gz
opensim-SC-d604cd284efc61af4616506830ff17ee52ff6e48.tar.bz2
opensim-SC-d604cd284efc61af4616506830ff17ee52ff6e48.tar.xz
Again, completely revamp the unlink code to finally allow unlinking
arbitrary combinations of root and child prims from one or multiple link sets. Please test throughly and consider things UNSTABLE until this is proven out.
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/SceneGraph.cs')
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs160
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