diff options
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/SceneGraph.cs')
-rw-r--r-- | OpenSim/Region/Framework/Scenes/SceneGraph.cs | 255 |
1 files changed, 134 insertions, 121 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index d87e814..5efe188 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs | |||
@@ -26,6 +26,7 @@ | |||
26 | */ | 26 | */ |
27 | 27 | ||
28 | using System; | 28 | using System; |
29 | using System.Threading; | ||
29 | using System.Collections.Generic; | 30 | using System.Collections.Generic; |
30 | using System.Reflection; | 31 | using System.Reflection; |
31 | using OpenMetaverse; | 32 | using OpenMetaverse; |
@@ -96,6 +97,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
96 | protected internal Dictionary<UUID, SceneObjectGroup> SceneObjectGroupsByFullID = new Dictionary<UUID, SceneObjectGroup>(); | 97 | protected internal Dictionary<UUID, SceneObjectGroup> SceneObjectGroupsByFullID = new Dictionary<UUID, SceneObjectGroup>(); |
97 | private readonly Object m_dictionary_lock = new Object(); | 98 | private readonly Object m_dictionary_lock = new Object(); |
98 | 99 | ||
100 | private Object m_updateLock = new Object(); | ||
101 | |||
99 | #endregion | 102 | #endregion |
100 | 103 | ||
101 | protected internal SceneGraph(Scene parent, RegionInfo regInfo) | 104 | protected internal SceneGraph(Scene parent, RegionInfo regInfo) |
@@ -369,6 +372,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
369 | /// </summary> | 372 | /// </summary> |
370 | protected internal void UpdateObjectGroups() | 373 | protected internal void UpdateObjectGroups() |
371 | { | 374 | { |
375 | if (!Monitor.TryEnter(m_updateLock)) | ||
376 | return; | ||
377 | |||
372 | List<SceneObjectGroup> updates; | 378 | List<SceneObjectGroup> updates; |
373 | 379 | ||
374 | // Some updates add more updates to the updateList. | 380 | // Some updates add more updates to the updateList. |
@@ -395,6 +401,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
395 | "[INNER SCENE]: Failed to update {0}, {1} - {2}", sog.Name, sog.UUID, e); | 401 | "[INNER SCENE]: Failed to update {0}, {1} - {2}", sog.Name, sog.UUID, e); |
396 | } | 402 | } |
397 | } | 403 | } |
404 | Monitor.Exit(m_updateLock); | ||
398 | } | 405 | } |
399 | 406 | ||
400 | protected internal void AddPhysicalPrim(int number) | 407 | protected internal void AddPhysicalPrim(int number) |
@@ -1555,56 +1562,59 @@ namespace OpenSim.Region.Framework.Scenes | |||
1555 | /// <param name="childPrims"></param> | 1562 | /// <param name="childPrims"></param> |
1556 | protected internal void LinkObjects(IClientAPI client, uint parentPrimId, List<uint> childPrimIds) | 1563 | protected internal void LinkObjects(IClientAPI client, uint parentPrimId, List<uint> childPrimIds) |
1557 | { | 1564 | { |
1558 | SceneObjectGroup parentGroup = GetGroupByPrim(parentPrimId); | 1565 | lock (m_updateLock) |
1559 | |||
1560 | List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); | ||
1561 | if (parentGroup != null) | ||
1562 | { | 1566 | { |
1563 | // We do this in reverse to get the link order of the prims correct | 1567 | SceneObjectGroup parentGroup = GetGroupByPrim(parentPrimId); |
1564 | for (int i = childPrimIds.Count - 1; i >= 0; i--) | 1568 | |
1569 | List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); | ||
1570 | if (parentGroup != null) | ||
1565 | { | 1571 | { |
1566 | SceneObjectGroup child = GetGroupByPrim(childPrimIds[i]); | 1572 | // We do this in reverse to get the link order of the prims correct |
1567 | if (child != null) | 1573 | for (int i = childPrimIds.Count - 1; i >= 0; i--) |
1568 | { | 1574 | { |
1569 | // Make sure no child prim is set for sale | 1575 | SceneObjectGroup child = GetGroupByPrim(childPrimIds[i]); |
1570 | // So that, on delink, no prims are unwittingly | 1576 | if (child != null) |
1571 | // left for sale and sold off | 1577 | { |
1572 | child.RootPart.ObjectSaleType = 0; | 1578 | // Make sure no child prim is set for sale |
1573 | child.RootPart.SalePrice = 10; | 1579 | // So that, on delink, no prims are unwittingly |
1574 | childGroups.Add(child); | 1580 | // left for sale and sold off |
1581 | child.RootPart.ObjectSaleType = 0; | ||
1582 | child.RootPart.SalePrice = 10; | ||
1583 | childGroups.Add(child); | ||
1584 | } | ||
1575 | } | 1585 | } |
1576 | } | 1586 | } |
1577 | } | 1587 | else |
1578 | else | 1588 | { |
1579 | { | 1589 | return; // parent is null so not in this region |
1580 | return; // parent is null so not in this region | 1590 | } |
1581 | } | ||
1582 | 1591 | ||
1583 | foreach (SceneObjectGroup child in childGroups) | 1592 | foreach (SceneObjectGroup child in childGroups) |
1584 | { | 1593 | { |
1585 | parentGroup.LinkToGroup(child); | 1594 | parentGroup.LinkToGroup(child); |
1586 | 1595 | ||
1587 | // this is here so physics gets updated! | 1596 | // this is here so physics gets updated! |
1588 | // Don't remove! Bad juju! Stay away! or fix physics! | 1597 | // Don't remove! Bad juju! Stay away! or fix physics! |
1589 | child.AbsolutePosition = child.AbsolutePosition; | 1598 | child.AbsolutePosition = child.AbsolutePosition; |
1590 | } | 1599 | } |
1591 | 1600 | ||
1592 | // We need to explicitly resend the newly link prim's object properties since no other actions | 1601 | // We need to explicitly resend the newly link prim's object properties since no other actions |
1593 | // occur on link to invoke this elsewhere (such as object selection) | 1602 | // occur on link to invoke this elsewhere (such as object selection) |
1594 | parentGroup.RootPart.AddFlag(PrimFlags.CreateSelected); | 1603 | parentGroup.RootPart.AddFlag(PrimFlags.CreateSelected); |
1595 | parentGroup.TriggerScriptChangedEvent(Changed.LINK); | 1604 | parentGroup.TriggerScriptChangedEvent(Changed.LINK); |
1596 | parentGroup.HasGroupChanged = true; | 1605 | parentGroup.HasGroupChanged = true; |
1597 | parentGroup.ScheduleGroupForFullUpdate(); | 1606 | parentGroup.ScheduleGroupForFullUpdate(); |
1598 | 1607 | ||
1599 | if (client != null) | 1608 | if (client != null) |
1600 | { | ||
1601 | parentGroup.GetProperties(client); | ||
1602 | } | ||
1603 | else | ||
1604 | { | ||
1605 | foreach (ScenePresence p in GetScenePresences()) | ||
1606 | { | 1609 | { |
1607 | parentGroup.GetProperties(p.ControllingClient); | 1610 | parentGroup.GetProperties(client); |
1611 | } | ||
1612 | else | ||
1613 | { | ||
1614 | foreach (ScenePresence p in GetScenePresences()) | ||
1615 | { | ||
1616 | parentGroup.GetProperties(p.ControllingClient); | ||
1617 | } | ||
1608 | } | 1618 | } |
1609 | } | 1619 | } |
1610 | } | 1620 | } |
@@ -1620,109 +1630,112 @@ namespace OpenSim.Region.Framework.Scenes | |||
1620 | 1630 | ||
1621 | protected internal void DelinkObjects(List<uint> primIds, bool sendEvents) | 1631 | protected internal void DelinkObjects(List<uint> primIds, bool sendEvents) |
1622 | { | 1632 | { |
1623 | List<SceneObjectPart> childParts = new List<SceneObjectPart>(); | 1633 | lock (m_updateLock) |
1624 | List<SceneObjectPart> rootParts = new List<SceneObjectPart>(); | ||
1625 | List<SceneObjectGroup> affectedGroups = new List<SceneObjectGroup>(); | ||
1626 | // Look them all up in one go, since that is comparatively expensive | ||
1627 | // | ||
1628 | foreach (uint primID in primIds) | ||
1629 | { | 1634 | { |
1630 | SceneObjectPart part = m_parentScene.GetSceneObjectPart(primID); | 1635 | List<SceneObjectPart> childParts = new List<SceneObjectPart>(); |
1631 | if (part != null) | 1636 | List<SceneObjectPart> rootParts = new List<SceneObjectPart>(); |
1637 | List<SceneObjectGroup> affectedGroups = new List<SceneObjectGroup>(); | ||
1638 | // Look them all up in one go, since that is comparatively expensive | ||
1639 | // | ||
1640 | foreach (uint primID in primIds) | ||
1632 | { | 1641 | { |
1633 | if (part.LinkNum < 2) // Root or single | 1642 | SceneObjectPart part = m_parentScene.GetSceneObjectPart(primID); |
1634 | rootParts.Add(part); | 1643 | if (part != null) |
1644 | { | ||
1645 | if (part.LinkNum < 2) // Root or single | ||
1646 | rootParts.Add(part); | ||
1647 | else | ||
1648 | childParts.Add(part); | ||
1649 | |||
1650 | SceneObjectGroup group = part.ParentGroup; | ||
1651 | if (!affectedGroups.Contains(group)) | ||
1652 | affectedGroups.Add(group); | ||
1653 | } | ||
1635 | else | 1654 | else |
1636 | childParts.Add(part); | 1655 | { |
1637 | 1656 | m_log.ErrorFormat("Viewer requested unlink of nonexistent part {0}", primID); | |
1638 | SceneObjectGroup group = part.ParentGroup; | 1657 | } |
1639 | if (!affectedGroups.Contains(group)) | ||
1640 | affectedGroups.Add(group); | ||
1641 | } | 1658 | } |
1642 | else | 1659 | |
1660 | foreach (SceneObjectPart child in childParts) | ||
1643 | { | 1661 | { |
1644 | m_log.ErrorFormat("Viewer requested unlink of nonexistent part {0}", primID); | 1662 | // Unlink all child parts from their groups |
1663 | // | ||
1664 | child.ParentGroup.DelinkFromGroup(child, sendEvents); | ||
1645 | } | 1665 | } |
1646 | } | ||
1647 | 1666 | ||
1648 | foreach (SceneObjectPart child in childParts) | 1667 | foreach (SceneObjectPart root in rootParts) |
1649 | { | ||
1650 | // Unlink all child parts from their groups | ||
1651 | // | ||
1652 | child.ParentGroup.DelinkFromGroup(child, sendEvents); | ||
1653 | } | ||
1654 | |||
1655 | foreach (SceneObjectPart root in rootParts) | ||
1656 | { | ||
1657 | // In most cases, this will run only one time, and the prim | ||
1658 | // will be a solo prim | ||
1659 | // However, editing linked parts and unlinking may be different | ||
1660 | // | ||
1661 | SceneObjectGroup group = root.ParentGroup; | ||
1662 | List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Children.Values); | ||
1663 | int numChildren = group.Children.Count; | ||
1664 | |||
1665 | // If there are prims left in a link set, but the root is | ||
1666 | // slated for unlink, we need to do this | ||
1667 | // | ||
1668 | if (numChildren != 1) | ||
1669 | { | 1668 | { |
1670 | // Unlink the remaining set | 1669 | // In most cases, this will run only one time, and the prim |
1670 | // will be a solo prim | ||
1671 | // However, editing linked parts and unlinking may be different | ||
1671 | // | 1672 | // |
1672 | bool sendEventsToRemainder = true; | 1673 | SceneObjectGroup group = root.ParentGroup; |
1673 | if (numChildren > 1) | 1674 | List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Children.Values); |
1674 | sendEventsToRemainder = false; | 1675 | int numChildren = group.Children.Count; |
1675 | |||
1676 | foreach (SceneObjectPart p in newSet) | ||
1677 | { | ||
1678 | if (p != group.RootPart) | ||
1679 | group.DelinkFromGroup(p, sendEventsToRemainder); | ||
1680 | } | ||
1681 | 1676 | ||
1682 | // If there is more than one prim remaining, we | 1677 | // If there are prims left in a link set, but the root is |
1683 | // need to re-link | 1678 | // slated for unlink, we need to do this |
1684 | // | 1679 | // |
1685 | if (numChildren > 2) | 1680 | if (numChildren != 1) |
1686 | { | 1681 | { |
1687 | // Remove old root | 1682 | // Unlink the remaining set |
1688 | // | 1683 | // |
1689 | if (newSet.Contains(root)) | 1684 | bool sendEventsToRemainder = true; |
1690 | newSet.Remove(root); | 1685 | if (numChildren > 1) |
1686 | sendEventsToRemainder = false; | ||
1691 | 1687 | ||
1692 | // Preserve link ordering | 1688 | foreach (SceneObjectPart p in newSet) |
1693 | // | ||
1694 | newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b) | ||
1695 | { | 1689 | { |
1696 | return a.LinkNum.CompareTo(b.LinkNum); | 1690 | if (p != group.RootPart) |
1697 | }); | 1691 | group.DelinkFromGroup(p, sendEventsToRemainder); |
1692 | } | ||
1698 | 1693 | ||
1699 | // Determine new root | 1694 | // If there is more than one prim remaining, we |
1695 | // need to re-link | ||
1700 | // | 1696 | // |
1701 | SceneObjectPart newRoot = newSet[0]; | 1697 | if (numChildren > 2) |
1702 | newSet.RemoveAt(0); | 1698 | { |
1699 | // Remove old root | ||
1700 | // | ||
1701 | if (newSet.Contains(root)) | ||
1702 | newSet.Remove(root); | ||
1703 | |||
1704 | // Preserve link ordering | ||
1705 | // | ||
1706 | newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b) | ||
1707 | { | ||
1708 | return a.LinkNum.CompareTo(b.LinkNum); | ||
1709 | }); | ||
1703 | 1710 | ||
1704 | List<uint> linkIDs = new List<uint>(); | 1711 | // Determine new root |
1712 | // | ||
1713 | SceneObjectPart newRoot = newSet[0]; | ||
1714 | newSet.RemoveAt(0); | ||
1705 | 1715 | ||
1706 | foreach (SceneObjectPart newChild in newSet) | 1716 | List<uint> linkIDs = new List<uint>(); |
1707 | { | 1717 | |
1708 | newChild.UpdateFlag = 0; | 1718 | foreach (SceneObjectPart newChild in newSet) |
1709 | linkIDs.Add(newChild.LocalId); | 1719 | { |
1710 | } | 1720 | newChild.UpdateFlag = 0; |
1721 | linkIDs.Add(newChild.LocalId); | ||
1722 | } | ||
1711 | 1723 | ||
1712 | LinkObjects(null, newRoot.LocalId, linkIDs); | 1724 | LinkObjects(null, newRoot.LocalId, linkIDs); |
1713 | if (!affectedGroups.Contains(newRoot.ParentGroup)) | 1725 | if (!affectedGroups.Contains(newRoot.ParentGroup)) |
1714 | affectedGroups.Add(newRoot.ParentGroup); | 1726 | affectedGroups.Add(newRoot.ParentGroup); |
1727 | } | ||
1715 | } | 1728 | } |
1716 | } | 1729 | } |
1717 | } | ||
1718 | 1730 | ||
1719 | // Finally, trigger events in the roots | 1731 | // Finally, trigger events in the roots |
1720 | // | 1732 | // |
1721 | foreach (SceneObjectGroup g in affectedGroups) | 1733 | foreach (SceneObjectGroup g in affectedGroups) |
1722 | { | 1734 | { |
1723 | g.TriggerScriptChangedEvent(Changed.LINK); | 1735 | g.TriggerScriptChangedEvent(Changed.LINK); |
1724 | g.HasGroupChanged = true; // Persist | 1736 | g.HasGroupChanged = true; // Persist |
1725 | g.ScheduleGroupForFullUpdate(); | 1737 | g.ScheduleGroupForFullUpdate(); |
1738 | } | ||
1726 | } | 1739 | } |
1727 | } | 1740 | } |
1728 | 1741 | ||