diff options
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/SceneGraph.cs')
-rw-r--r-- | OpenSim/Region/Framework/Scenes/SceneGraph.cs | 224 |
1 files changed, 163 insertions, 61 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 60855b2..62e7d36 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs | |||
@@ -43,6 +43,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
43 | 43 | ||
44 | public delegate void ObjectDuplicateDelegate(EntityBase original, EntityBase clone); | 44 | public delegate void ObjectDuplicateDelegate(EntityBase original, EntityBase clone); |
45 | 45 | ||
46 | public delegate void AttachToBackupDelegate(SceneObjectGroup sog); | ||
47 | |||
48 | public delegate void DetachFromBackupDelegate(SceneObjectGroup sog); | ||
49 | |||
50 | public delegate void ChangedBackupDelegate(SceneObjectGroup sog); | ||
51 | |||
46 | public delegate void ObjectCreateDelegate(EntityBase obj); | 52 | public delegate void ObjectCreateDelegate(EntityBase obj); |
47 | 53 | ||
48 | public delegate void ObjectDeleteDelegate(EntityBase obj); | 54 | public delegate void ObjectDeleteDelegate(EntityBase obj); |
@@ -61,6 +67,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
61 | private PhysicsCrash handlerPhysicsCrash = null; | 67 | private PhysicsCrash handlerPhysicsCrash = null; |
62 | 68 | ||
63 | public event ObjectDuplicateDelegate OnObjectDuplicate; | 69 | public event ObjectDuplicateDelegate OnObjectDuplicate; |
70 | public event AttachToBackupDelegate OnAttachToBackup; | ||
71 | public event DetachFromBackupDelegate OnDetachFromBackup; | ||
72 | public event ChangedBackupDelegate OnChangeBackup; | ||
64 | public event ObjectCreateDelegate OnObjectCreate; | 73 | public event ObjectCreateDelegate OnObjectCreate; |
65 | public event ObjectDeleteDelegate OnObjectRemove; | 74 | public event ObjectDeleteDelegate OnObjectRemove; |
66 | 75 | ||
@@ -68,7 +77,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
68 | 77 | ||
69 | #region Fields | 78 | #region Fields |
70 | 79 | ||
71 | protected object m_presenceLock = new object(); | 80 | protected OpenMetaverse.ReaderWriterLockSlim m_scenePresencesLock = new OpenMetaverse.ReaderWriterLockSlim(); |
72 | protected Dictionary<UUID, ScenePresence> m_scenePresenceMap = new Dictionary<UUID, ScenePresence>(); | 81 | protected Dictionary<UUID, ScenePresence> m_scenePresenceMap = new Dictionary<UUID, ScenePresence>(); |
73 | protected List<ScenePresence> m_scenePresenceArray = new List<ScenePresence>(); | 82 | protected List<ScenePresence> m_scenePresenceArray = new List<ScenePresence>(); |
74 | 83 | ||
@@ -135,13 +144,18 @@ namespace OpenSim.Region.Framework.Scenes | |||
135 | 144 | ||
136 | protected internal void Close() | 145 | protected internal void Close() |
137 | { | 146 | { |
138 | lock (m_presenceLock) | 147 | m_scenePresencesLock.EnterWriteLock(); |
148 | try | ||
139 | { | 149 | { |
140 | Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(); | 150 | Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(); |
141 | List<ScenePresence> newlist = new List<ScenePresence>(); | 151 | List<ScenePresence> newlist = new List<ScenePresence>(); |
142 | m_scenePresenceMap = newmap; | 152 | m_scenePresenceMap = newmap; |
143 | m_scenePresenceArray = newlist; | 153 | m_scenePresenceArray = newlist; |
144 | } | 154 | } |
155 | finally | ||
156 | { | ||
157 | m_scenePresencesLock.ExitWriteLock(); | ||
158 | } | ||
145 | 159 | ||
146 | lock (SceneObjectGroupsByFullID) | 160 | lock (SceneObjectGroupsByFullID) |
147 | SceneObjectGroupsByFullID.Clear(); | 161 | SceneObjectGroupsByFullID.Clear(); |
@@ -273,6 +287,33 @@ namespace OpenSim.Region.Framework.Scenes | |||
273 | protected internal bool AddRestoredSceneObject( | 287 | protected internal bool AddRestoredSceneObject( |
274 | SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) | 288 | SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) |
275 | { | 289 | { |
290 | if (!m_parentScene.CombineRegions) | ||
291 | { | ||
292 | // KF: Check for out-of-region, move inside and make static. | ||
293 | Vector3 npos = new Vector3(sceneObject.RootPart.GroupPosition.X, | ||
294 | sceneObject.RootPart.GroupPosition.Y, | ||
295 | sceneObject.RootPart.GroupPosition.Z); | ||
296 | if (!(((sceneObject.RootPart.Shape.PCode == (byte)PCode.Prim) && (sceneObject.RootPart.Shape.State != 0))) && (npos.X < 0.0 || npos.Y < 0.0 || npos.Z < 0.0 || | ||
297 | npos.X > Constants.RegionSize || | ||
298 | npos.Y > Constants.RegionSize)) | ||
299 | { | ||
300 | if (npos.X < 0.0) npos.X = 1.0f; | ||
301 | if (npos.Y < 0.0) npos.Y = 1.0f; | ||
302 | if (npos.Z < 0.0) npos.Z = 0.0f; | ||
303 | if (npos.X > Constants.RegionSize) npos.X = Constants.RegionSize - 1.0f; | ||
304 | if (npos.Y > Constants.RegionSize) npos.Y = Constants.RegionSize - 1.0f; | ||
305 | |||
306 | foreach (SceneObjectPart part in sceneObject.Parts) | ||
307 | { | ||
308 | part.GroupPosition = npos; | ||
309 | } | ||
310 | sceneObject.RootPart.Velocity = Vector3.Zero; | ||
311 | sceneObject.RootPart.AngularVelocity = Vector3.Zero; | ||
312 | sceneObject.RootPart.Acceleration = Vector3.Zero; | ||
313 | sceneObject.RootPart.Velocity = Vector3.Zero; | ||
314 | } | ||
315 | } | ||
316 | |||
276 | if (attachToBackup && (!alreadyPersisted)) | 317 | if (attachToBackup && (!alreadyPersisted)) |
277 | { | 318 | { |
278 | sceneObject.ForceInventoryPersistence(); | 319 | sceneObject.ForceInventoryPersistence(); |
@@ -482,6 +523,30 @@ namespace OpenSim.Region.Framework.Scenes | |||
482 | m_updateList[obj.UUID] = obj; | 523 | m_updateList[obj.UUID] = obj; |
483 | } | 524 | } |
484 | 525 | ||
526 | public void FireAttachToBackup(SceneObjectGroup obj) | ||
527 | { | ||
528 | if (OnAttachToBackup != null) | ||
529 | { | ||
530 | OnAttachToBackup(obj); | ||
531 | } | ||
532 | } | ||
533 | |||
534 | public void FireDetachFromBackup(SceneObjectGroup obj) | ||
535 | { | ||
536 | if (OnDetachFromBackup != null) | ||
537 | { | ||
538 | OnDetachFromBackup(obj); | ||
539 | } | ||
540 | } | ||
541 | |||
542 | public void FireChangeBackup(SceneObjectGroup obj) | ||
543 | { | ||
544 | if (OnChangeBackup != null) | ||
545 | { | ||
546 | OnChangeBackup(obj); | ||
547 | } | ||
548 | } | ||
549 | |||
485 | /// <summary> | 550 | /// <summary> |
486 | /// Process all pending updates | 551 | /// Process all pending updates |
487 | /// </summary> | 552 | /// </summary> |
@@ -617,7 +682,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
617 | 682 | ||
618 | Entities[presence.UUID] = presence; | 683 | Entities[presence.UUID] = presence; |
619 | 684 | ||
620 | lock (m_presenceLock) | 685 | m_scenePresencesLock.EnterWriteLock(); |
686 | try | ||
621 | { | 687 | { |
622 | Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); | 688 | Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); |
623 | List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); | 689 | List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); |
@@ -641,6 +707,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
641 | m_scenePresenceMap = newmap; | 707 | m_scenePresenceMap = newmap; |
642 | m_scenePresenceArray = newlist; | 708 | m_scenePresenceArray = newlist; |
643 | } | 709 | } |
710 | finally | ||
711 | { | ||
712 | m_scenePresencesLock.ExitWriteLock(); | ||
713 | } | ||
644 | } | 714 | } |
645 | 715 | ||
646 | /// <summary> | 716 | /// <summary> |
@@ -655,7 +725,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
655 | agentID); | 725 | agentID); |
656 | } | 726 | } |
657 | 727 | ||
658 | lock (m_presenceLock) | 728 | m_scenePresencesLock.EnterWriteLock(); |
729 | try | ||
659 | { | 730 | { |
660 | Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); | 731 | Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); |
661 | List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); | 732 | List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); |
@@ -677,6 +748,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
677 | m_log.WarnFormat("[SCENEGRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); | 748 | m_log.WarnFormat("[SCENEGRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); |
678 | } | 749 | } |
679 | } | 750 | } |
751 | finally | ||
752 | { | ||
753 | m_scenePresencesLock.ExitWriteLock(); | ||
754 | } | ||
680 | } | 755 | } |
681 | 756 | ||
682 | protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) | 757 | protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) |
@@ -800,6 +875,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
800 | return m_scenePresenceArray; | 875 | return m_scenePresenceArray; |
801 | } | 876 | } |
802 | 877 | ||
878 | public int GetNumberOfScenePresences() | ||
879 | { | ||
880 | return m_scenePresenceArray.Count; | ||
881 | } | ||
882 | |||
803 | /// <summary> | 883 | /// <summary> |
804 | /// Request a scene presence by UUID. Fast, indexed lookup. | 884 | /// Request a scene presence by UUID. Fast, indexed lookup. |
805 | /// </summary> | 885 | /// </summary> |
@@ -1307,8 +1387,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
1307 | { | 1387 | { |
1308 | if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) | 1388 | if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) |
1309 | { | 1389 | { |
1310 | if (m_parentScene.AttachmentsModule != null) | 1390 | // Set the new attachment point data in the object |
1311 | m_parentScene.AttachmentsModule.UpdateAttachmentPosition(group, pos); | 1391 | byte attachmentPoint = group.GetAttachmentPoint(); |
1392 | group.UpdateGroupPosition(pos); | ||
1393 | group.RootPart.IsAttachment = false; | ||
1394 | group.AbsolutePosition = group.RootPart.AttachedPos; | ||
1395 | group.SetAttachmentPoint(attachmentPoint); | ||
1396 | group.HasGroupChanged = true; | ||
1312 | } | 1397 | } |
1313 | else | 1398 | else |
1314 | { | 1399 | { |
@@ -1552,10 +1637,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
1552 | /// <param name="childPrims"></param> | 1637 | /// <param name="childPrims"></param> |
1553 | protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children) | 1638 | protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children) |
1554 | { | 1639 | { |
1640 | SceneObjectGroup parentGroup = root.ParentGroup; | ||
1641 | if (parentGroup == null) return; | ||
1555 | Monitor.Enter(m_updateLock); | 1642 | Monitor.Enter(m_updateLock); |
1643 | |||
1556 | try | 1644 | try |
1557 | { | 1645 | { |
1558 | SceneObjectGroup parentGroup = root.ParentGroup; | 1646 | parentGroup.areUpdatesSuspended = true; |
1559 | 1647 | ||
1560 | List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); | 1648 | List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); |
1561 | if (parentGroup != null) | 1649 | if (parentGroup != null) |
@@ -1567,11 +1655,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
1567 | 1655 | ||
1568 | if (child != null) | 1656 | if (child != null) |
1569 | { | 1657 | { |
1570 | // Make sure no child prim is set for sale | ||
1571 | // So that, on delink, no prims are unwittingly | ||
1572 | // left for sale and sold off | ||
1573 | child.RootPart.ObjectSaleType = 0; | ||
1574 | child.RootPart.SalePrice = 10; | ||
1575 | childGroups.Add(child); | 1658 | childGroups.Add(child); |
1576 | } | 1659 | } |
1577 | } | 1660 | } |
@@ -1594,12 +1677,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
1594 | // occur on link to invoke this elsewhere (such as object selection) | 1677 | // occur on link to invoke this elsewhere (such as object selection) |
1595 | parentGroup.RootPart.CreateSelected = true; | 1678 | parentGroup.RootPart.CreateSelected = true; |
1596 | parentGroup.TriggerScriptChangedEvent(Changed.LINK); | 1679 | parentGroup.TriggerScriptChangedEvent(Changed.LINK); |
1597 | parentGroup.HasGroupChanged = true; | ||
1598 | parentGroup.ScheduleGroupForFullUpdate(); | ||
1599 | |||
1600 | } | 1680 | } |
1601 | finally | 1681 | finally |
1602 | { | 1682 | { |
1683 | parentGroup.areUpdatesSuspended = false; | ||
1684 | parentGroup.HasGroupChanged = true; | ||
1685 | parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true); | ||
1686 | parentGroup.ScheduleGroupForFullUpdate(); | ||
1603 | Monitor.Exit(m_updateLock); | 1687 | Monitor.Exit(m_updateLock); |
1604 | } | 1688 | } |
1605 | } | 1689 | } |
@@ -1631,21 +1715,24 @@ namespace OpenSim.Region.Framework.Scenes | |||
1631 | 1715 | ||
1632 | SceneObjectGroup group = part.ParentGroup; | 1716 | SceneObjectGroup group = part.ParentGroup; |
1633 | if (!affectedGroups.Contains(group)) | 1717 | if (!affectedGroups.Contains(group)) |
1718 | { | ||
1719 | group.areUpdatesSuspended = true; | ||
1634 | affectedGroups.Add(group); | 1720 | affectedGroups.Add(group); |
1721 | } | ||
1635 | } | 1722 | } |
1636 | } | 1723 | } |
1637 | } | 1724 | } |
1638 | 1725 | ||
1639 | foreach (SceneObjectPart child in childParts) | 1726 | if (childParts.Count > 0) |
1640 | { | 1727 | { |
1641 | // Unlink all child parts from their groups | 1728 | foreach (SceneObjectPart child in childParts) |
1642 | // | 1729 | { |
1643 | child.ParentGroup.DelinkFromGroup(child, true); | 1730 | // Unlink all child parts from their groups |
1644 | 1731 | // | |
1645 | // These are not in affected groups and will not be | 1732 | child.ParentGroup.DelinkFromGroup(child, true); |
1646 | // handled further. Do the honors here. | 1733 | child.ParentGroup.HasGroupChanged = true; |
1647 | child.ParentGroup.HasGroupChanged = true; | 1734 | child.ParentGroup.ScheduleGroupForFullUpdate(); |
1648 | child.ParentGroup.ScheduleGroupForFullUpdate(); | 1735 | } |
1649 | } | 1736 | } |
1650 | 1737 | ||
1651 | foreach (SceneObjectPart root in rootParts) | 1738 | foreach (SceneObjectPart root in rootParts) |
@@ -1655,56 +1742,68 @@ namespace OpenSim.Region.Framework.Scenes | |||
1655 | // However, editing linked parts and unlinking may be different | 1742 | // However, editing linked parts and unlinking may be different |
1656 | // | 1743 | // |
1657 | SceneObjectGroup group = root.ParentGroup; | 1744 | SceneObjectGroup group = root.ParentGroup; |
1745 | group.areUpdatesSuspended = true; | ||
1658 | 1746 | ||
1659 | List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); | 1747 | List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); |
1660 | int numChildren = newSet.Count; | 1748 | int numChildren = newSet.Count; |
1661 | 1749 | ||
1750 | if (numChildren == 1) | ||
1751 | break; | ||
1752 | |||
1662 | // If there are prims left in a link set, but the root is | 1753 | // If there are prims left in a link set, but the root is |
1663 | // slated for unlink, we need to do this | 1754 | // slated for unlink, we need to do this |
1755 | // Unlink the remaining set | ||
1664 | // | 1756 | // |
1665 | if (numChildren != 1) | 1757 | bool sendEventsToRemainder = true; |
1666 | { | 1758 | if (numChildren > 1) |
1667 | // Unlink the remaining set | 1759 | sendEventsToRemainder = false; |
1668 | // | ||
1669 | bool sendEventsToRemainder = true; | ||
1670 | if (numChildren > 1) | ||
1671 | sendEventsToRemainder = false; | ||
1672 | 1760 | ||
1673 | foreach (SceneObjectPart p in newSet) | 1761 | foreach (SceneObjectPart p in newSet) |
1762 | { | ||
1763 | if (p != group.RootPart) | ||
1674 | { | 1764 | { |
1675 | if (p != group.RootPart) | 1765 | group.DelinkFromGroup(p, sendEventsToRemainder); |
1676 | group.DelinkFromGroup(p, sendEventsToRemainder); | 1766 | if (numChildren > 2) |
1767 | { | ||
1768 | p.ParentGroup.areUpdatesSuspended = true; | ||
1769 | } | ||
1770 | else | ||
1771 | { | ||
1772 | p.ParentGroup.HasGroupChanged = true; | ||
1773 | p.ParentGroup.ScheduleGroupForFullUpdate(); | ||
1774 | } | ||
1677 | } | 1775 | } |
1776 | } | ||
1777 | |||
1778 | // If there is more than one prim remaining, we | ||
1779 | // need to re-link | ||
1780 | // | ||
1781 | if (numChildren > 2) | ||
1782 | { | ||
1783 | // Remove old root | ||
1784 | // | ||
1785 | if (newSet.Contains(root)) | ||
1786 | newSet.Remove(root); | ||
1678 | 1787 | ||
1679 | // If there is more than one prim remaining, we | 1788 | // Preserve link ordering |
1680 | // need to re-link | ||
1681 | // | 1789 | // |
1682 | if (numChildren > 2) | 1790 | newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b) |
1683 | { | 1791 | { |
1684 | // Remove old root | 1792 | return a.LinkNum.CompareTo(b.LinkNum); |
1685 | // | 1793 | }); |
1686 | if (newSet.Contains(root)) | ||
1687 | newSet.Remove(root); | ||
1688 | |||
1689 | // Preserve link ordering | ||
1690 | // | ||
1691 | newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b) | ||
1692 | { | ||
1693 | return a.LinkNum.CompareTo(b.LinkNum); | ||
1694 | }); | ||
1695 | 1794 | ||
1696 | // Determine new root | 1795 | // Determine new root |
1697 | // | 1796 | // |
1698 | SceneObjectPart newRoot = newSet[0]; | 1797 | SceneObjectPart newRoot = newSet[0]; |
1699 | newSet.RemoveAt(0); | 1798 | newSet.RemoveAt(0); |
1700 | 1799 | ||
1701 | foreach (SceneObjectPart newChild in newSet) | 1800 | foreach (SceneObjectPart newChild in newSet) |
1702 | newChild.UpdateFlag = 0; | 1801 | newChild.UpdateFlag = 0; |
1703 | 1802 | ||
1704 | LinkObjects(newRoot, newSet); | 1803 | newRoot.ParentGroup.areUpdatesSuspended = true; |
1705 | if (!affectedGroups.Contains(newRoot.ParentGroup)) | 1804 | LinkObjects(newRoot, newSet); |
1706 | affectedGroups.Add(newRoot.ParentGroup); | 1805 | if (!affectedGroups.Contains(newRoot.ParentGroup)) |
1707 | } | 1806 | affectedGroups.Add(newRoot.ParentGroup); |
1708 | } | 1807 | } |
1709 | } | 1808 | } |
1710 | 1809 | ||
@@ -1712,8 +1811,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
1712 | // | 1811 | // |
1713 | foreach (SceneObjectGroup g in affectedGroups) | 1812 | foreach (SceneObjectGroup g in affectedGroups) |
1714 | { | 1813 | { |
1814 | // Child prims that have been unlinked and deleted will | ||
1815 | // return unless the root is deleted. This will remove them | ||
1816 | // from the database. They will be rewritten immediately, | ||
1817 | // minus the rows for the unlinked child prims. | ||
1818 | m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID); | ||
1715 | g.TriggerScriptChangedEvent(Changed.LINK); | 1819 | g.TriggerScriptChangedEvent(Changed.LINK); |
1716 | g.HasGroupChanged = true; // Persist | 1820 | g.HasGroupChanged = true; // Persist |
1821 | g.areUpdatesSuspended = false; | ||
1717 | g.ScheduleGroupForFullUpdate(); | 1822 | g.ScheduleGroupForFullUpdate(); |
1718 | } | 1823 | } |
1719 | } | 1824 | } |
@@ -1831,9 +1936,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
1831 | child.ApplyNextOwnerPermissions(); | 1936 | child.ApplyNextOwnerPermissions(); |
1832 | } | 1937 | } |
1833 | } | 1938 | } |
1834 | |||
1835 | copy.RootPart.ObjectSaleType = 0; | ||
1836 | copy.RootPart.SalePrice = 10; | ||
1837 | } | 1939 | } |
1838 | 1940 | ||
1839 | // FIXME: This section needs to be refactored so that it just calls AddSceneObject() | 1941 | // FIXME: This section needs to be refactored so that it just calls AddSceneObject() |