diff options
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/SceneGraph.cs')
-rw-r--r-- | OpenSim/Region/Framework/Scenes/SceneGraph.cs | 224 |
1 files changed, 165 insertions, 59 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 36c5c52..d1ee990 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 | ||
@@ -132,13 +141,18 @@ namespace OpenSim.Region.Framework.Scenes | |||
132 | 141 | ||
133 | protected internal void Close() | 142 | protected internal void Close() |
134 | { | 143 | { |
135 | lock (m_presenceLock) | 144 | m_scenePresencesLock.EnterWriteLock(); |
145 | try | ||
136 | { | 146 | { |
137 | Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(); | 147 | Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(); |
138 | List<ScenePresence> newlist = new List<ScenePresence>(); | 148 | List<ScenePresence> newlist = new List<ScenePresence>(); |
139 | m_scenePresenceMap = newmap; | 149 | m_scenePresenceMap = newmap; |
140 | m_scenePresenceArray = newlist; | 150 | m_scenePresenceArray = newlist; |
141 | } | 151 | } |
152 | finally | ||
153 | { | ||
154 | m_scenePresencesLock.ExitWriteLock(); | ||
155 | } | ||
142 | 156 | ||
143 | lock (SceneObjectGroupsByFullID) | 157 | lock (SceneObjectGroupsByFullID) |
144 | SceneObjectGroupsByFullID.Clear(); | 158 | SceneObjectGroupsByFullID.Clear(); |
@@ -270,6 +284,33 @@ namespace OpenSim.Region.Framework.Scenes | |||
270 | protected internal bool AddRestoredSceneObject( | 284 | protected internal bool AddRestoredSceneObject( |
271 | SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) | 285 | SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) |
272 | { | 286 | { |
287 | if (!m_parentScene.CombineRegions) | ||
288 | { | ||
289 | // KF: Check for out-of-region, move inside and make static. | ||
290 | Vector3 npos = new Vector3(sceneObject.RootPart.GroupPosition.X, | ||
291 | sceneObject.RootPart.GroupPosition.Y, | ||
292 | sceneObject.RootPart.GroupPosition.Z); | ||
293 | 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 || | ||
294 | npos.X > Constants.RegionSize || | ||
295 | npos.Y > Constants.RegionSize)) | ||
296 | { | ||
297 | if (npos.X < 0.0) npos.X = 1.0f; | ||
298 | if (npos.Y < 0.0) npos.Y = 1.0f; | ||
299 | if (npos.Z < 0.0) npos.Z = 0.0f; | ||
300 | if (npos.X > Constants.RegionSize) npos.X = Constants.RegionSize - 1.0f; | ||
301 | if (npos.Y > Constants.RegionSize) npos.Y = Constants.RegionSize - 1.0f; | ||
302 | |||
303 | foreach (SceneObjectPart part in sceneObject.Parts) | ||
304 | { | ||
305 | part.GroupPosition = npos; | ||
306 | } | ||
307 | sceneObject.RootPart.Velocity = Vector3.Zero; | ||
308 | sceneObject.RootPart.AngularVelocity = Vector3.Zero; | ||
309 | sceneObject.RootPart.Acceleration = Vector3.Zero; | ||
310 | sceneObject.RootPart.Velocity = Vector3.Zero; | ||
311 | } | ||
312 | } | ||
313 | |||
273 | if (attachToBackup && (!alreadyPersisted)) | 314 | if (attachToBackup && (!alreadyPersisted)) |
274 | { | 315 | { |
275 | sceneObject.ForceInventoryPersistence(); | 316 | sceneObject.ForceInventoryPersistence(); |
@@ -487,6 +528,30 @@ namespace OpenSim.Region.Framework.Scenes | |||
487 | m_updateList[obj.UUID] = obj; | 528 | m_updateList[obj.UUID] = obj; |
488 | } | 529 | } |
489 | 530 | ||
531 | public void FireAttachToBackup(SceneObjectGroup obj) | ||
532 | { | ||
533 | if (OnAttachToBackup != null) | ||
534 | { | ||
535 | OnAttachToBackup(obj); | ||
536 | } | ||
537 | } | ||
538 | |||
539 | public void FireDetachFromBackup(SceneObjectGroup obj) | ||
540 | { | ||
541 | if (OnDetachFromBackup != null) | ||
542 | { | ||
543 | OnDetachFromBackup(obj); | ||
544 | } | ||
545 | } | ||
546 | |||
547 | public void FireChangeBackup(SceneObjectGroup obj) | ||
548 | { | ||
549 | if (OnChangeBackup != null) | ||
550 | { | ||
551 | OnChangeBackup(obj); | ||
552 | } | ||
553 | } | ||
554 | |||
490 | /// <summary> | 555 | /// <summary> |
491 | /// Process all pending updates | 556 | /// Process all pending updates |
492 | /// </summary> | 557 | /// </summary> |
@@ -618,7 +683,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
618 | 683 | ||
619 | Entities[presence.UUID] = presence; | 684 | Entities[presence.UUID] = presence; |
620 | 685 | ||
621 | lock (m_presenceLock) | 686 | m_scenePresencesLock.EnterWriteLock(); |
687 | try | ||
622 | { | 688 | { |
623 | Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); | 689 | Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); |
624 | List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); | 690 | List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); |
@@ -642,6 +708,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
642 | m_scenePresenceMap = newmap; | 708 | m_scenePresenceMap = newmap; |
643 | m_scenePresenceArray = newlist; | 709 | m_scenePresenceArray = newlist; |
644 | } | 710 | } |
711 | finally | ||
712 | { | ||
713 | m_scenePresencesLock.ExitWriteLock(); | ||
714 | } | ||
645 | } | 715 | } |
646 | 716 | ||
647 | /// <summary> | 717 | /// <summary> |
@@ -656,7 +726,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
656 | agentID); | 726 | agentID); |
657 | } | 727 | } |
658 | 728 | ||
659 | lock (m_presenceLock) | 729 | m_scenePresencesLock.EnterWriteLock(); |
730 | try | ||
660 | { | 731 | { |
661 | Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); | 732 | Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); |
662 | List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); | 733 | List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); |
@@ -678,6 +749,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
678 | m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); | 749 | m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); |
679 | } | 750 | } |
680 | } | 751 | } |
752 | finally | ||
753 | { | ||
754 | m_scenePresencesLock.ExitWriteLock(); | ||
755 | } | ||
681 | } | 756 | } |
682 | 757 | ||
683 | protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) | 758 | protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) |
@@ -1377,8 +1452,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
1377 | { | 1452 | { |
1378 | if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) | 1453 | if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) |
1379 | { | 1454 | { |
1380 | if (m_parentScene.AttachmentsModule != null) | 1455 | // Set the new attachment point data in the object |
1381 | m_parentScene.AttachmentsModule.UpdateAttachmentPosition(group, pos); | 1456 | byte attachmentPoint = group.GetAttachmentPoint(); |
1457 | group.UpdateGroupPosition(pos); | ||
1458 | group.IsAttachment = false; | ||
1459 | group.AbsolutePosition = group.RootPart.AttachedPos; | ||
1460 | group.AttachmentPoint = attachmentPoint; | ||
1461 | group.HasGroupChanged = true; | ||
1382 | } | 1462 | } |
1383 | else | 1463 | else |
1384 | { | 1464 | { |
@@ -1642,10 +1722,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
1642 | /// <param name="childPrims"></param> | 1722 | /// <param name="childPrims"></param> |
1643 | protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children) | 1723 | protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children) |
1644 | { | 1724 | { |
1725 | SceneObjectGroup parentGroup = root.ParentGroup; | ||
1726 | if (parentGroup == null) return; | ||
1645 | Monitor.Enter(m_updateLock); | 1727 | Monitor.Enter(m_updateLock); |
1728 | |||
1646 | try | 1729 | try |
1647 | { | 1730 | { |
1648 | SceneObjectGroup parentGroup = root.ParentGroup; | 1731 | parentGroup.areUpdatesSuspended = true; |
1649 | 1732 | ||
1650 | List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); | 1733 | List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); |
1651 | 1734 | ||
@@ -1657,9 +1740,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
1657 | // Make sure no child prim is set for sale | 1740 | // Make sure no child prim is set for sale |
1658 | // So that, on delink, no prims are unwittingly | 1741 | // So that, on delink, no prims are unwittingly |
1659 | // left for sale and sold off | 1742 | // left for sale and sold off |
1660 | child.RootPart.ObjectSaleType = 0; | 1743 | |
1661 | child.RootPart.SalePrice = 10; | 1744 | if (child != null) |
1662 | childGroups.Add(child); | 1745 | { |
1746 | child.RootPart.ObjectSaleType = 0; | ||
1747 | child.RootPart.SalePrice = 10; | ||
1748 | childGroups.Add(child); | ||
1749 | } | ||
1663 | } | 1750 | } |
1664 | 1751 | ||
1665 | foreach (SceneObjectGroup child in childGroups) | 1752 | foreach (SceneObjectGroup child in childGroups) |
@@ -1675,12 +1762,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
1675 | // occur on link to invoke this elsewhere (such as object selection) | 1762 | // occur on link to invoke this elsewhere (such as object selection) |
1676 | parentGroup.RootPart.CreateSelected = true; | 1763 | parentGroup.RootPart.CreateSelected = true; |
1677 | parentGroup.TriggerScriptChangedEvent(Changed.LINK); | 1764 | parentGroup.TriggerScriptChangedEvent(Changed.LINK); |
1678 | parentGroup.HasGroupChanged = true; | ||
1679 | parentGroup.ScheduleGroupForFullUpdate(); | ||
1680 | |||
1681 | } | 1765 | } |
1682 | finally | 1766 | finally |
1683 | { | 1767 | { |
1768 | parentGroup.areUpdatesSuspended = false; | ||
1769 | parentGroup.HasGroupChanged = true; | ||
1770 | parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true); | ||
1771 | parentGroup.ScheduleGroupForFullUpdate(); | ||
1684 | Monitor.Exit(m_updateLock); | 1772 | Monitor.Exit(m_updateLock); |
1685 | } | 1773 | } |
1686 | } | 1774 | } |
@@ -1712,21 +1800,24 @@ namespace OpenSim.Region.Framework.Scenes | |||
1712 | 1800 | ||
1713 | SceneObjectGroup group = part.ParentGroup; | 1801 | SceneObjectGroup group = part.ParentGroup; |
1714 | if (!affectedGroups.Contains(group)) | 1802 | if (!affectedGroups.Contains(group)) |
1803 | { | ||
1804 | group.areUpdatesSuspended = true; | ||
1715 | affectedGroups.Add(group); | 1805 | affectedGroups.Add(group); |
1806 | } | ||
1716 | } | 1807 | } |
1717 | } | 1808 | } |
1718 | } | 1809 | } |
1719 | 1810 | ||
1720 | foreach (SceneObjectPart child in childParts) | 1811 | if (childParts.Count > 0) |
1721 | { | 1812 | { |
1722 | // Unlink all child parts from their groups | 1813 | foreach (SceneObjectPart child in childParts) |
1723 | // | 1814 | { |
1724 | child.ParentGroup.DelinkFromGroup(child, true); | 1815 | // Unlink all child parts from their groups |
1725 | 1816 | // | |
1726 | // These are not in affected groups and will not be | 1817 | child.ParentGroup.DelinkFromGroup(child, true); |
1727 | // handled further. Do the honors here. | 1818 | child.ParentGroup.HasGroupChanged = true; |
1728 | child.ParentGroup.HasGroupChanged = true; | 1819 | child.ParentGroup.ScheduleGroupForFullUpdate(); |
1729 | child.ParentGroup.ScheduleGroupForFullUpdate(); | 1820 | } |
1730 | } | 1821 | } |
1731 | 1822 | ||
1732 | foreach (SceneObjectPart root in rootParts) | 1823 | foreach (SceneObjectPart root in rootParts) |
@@ -1736,56 +1827,68 @@ namespace OpenSim.Region.Framework.Scenes | |||
1736 | // However, editing linked parts and unlinking may be different | 1827 | // However, editing linked parts and unlinking may be different |
1737 | // | 1828 | // |
1738 | SceneObjectGroup group = root.ParentGroup; | 1829 | SceneObjectGroup group = root.ParentGroup; |
1830 | group.areUpdatesSuspended = true; | ||
1739 | 1831 | ||
1740 | List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); | 1832 | List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); |
1741 | int numChildren = newSet.Count; | 1833 | int numChildren = newSet.Count; |
1742 | 1834 | ||
1835 | if (numChildren == 1) | ||
1836 | break; | ||
1837 | |||
1743 | // If there are prims left in a link set, but the root is | 1838 | // If there are prims left in a link set, but the root is |
1744 | // slated for unlink, we need to do this | 1839 | // slated for unlink, we need to do this |
1840 | // Unlink the remaining set | ||
1745 | // | 1841 | // |
1746 | if (numChildren != 1) | 1842 | bool sendEventsToRemainder = true; |
1747 | { | 1843 | if (numChildren > 1) |
1748 | // Unlink the remaining set | 1844 | sendEventsToRemainder = false; |
1749 | // | ||
1750 | bool sendEventsToRemainder = true; | ||
1751 | if (numChildren > 1) | ||
1752 | sendEventsToRemainder = false; | ||
1753 | 1845 | ||
1754 | foreach (SceneObjectPart p in newSet) | 1846 | foreach (SceneObjectPart p in newSet) |
1847 | { | ||
1848 | if (p != group.RootPart) | ||
1755 | { | 1849 | { |
1756 | if (p != group.RootPart) | 1850 | group.DelinkFromGroup(p, sendEventsToRemainder); |
1757 | group.DelinkFromGroup(p, sendEventsToRemainder); | 1851 | if (numChildren > 2) |
1852 | { | ||
1853 | p.ParentGroup.areUpdatesSuspended = true; | ||
1854 | } | ||
1855 | else | ||
1856 | { | ||
1857 | p.ParentGroup.HasGroupChanged = true; | ||
1858 | p.ParentGroup.ScheduleGroupForFullUpdate(); | ||
1859 | } | ||
1758 | } | 1860 | } |
1861 | } | ||
1759 | 1862 | ||
1760 | // If there is more than one prim remaining, we | 1863 | // If there is more than one prim remaining, we |
1761 | // need to re-link | 1864 | // need to re-link |
1865 | // | ||
1866 | if (numChildren > 2) | ||
1867 | { | ||
1868 | // Remove old root | ||
1869 | // | ||
1870 | if (newSet.Contains(root)) | ||
1871 | newSet.Remove(root); | ||
1872 | |||
1873 | // Preserve link ordering | ||
1762 | // | 1874 | // |
1763 | if (numChildren > 2) | 1875 | newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b) |
1764 | { | 1876 | { |
1765 | // Remove old root | 1877 | return a.LinkNum.CompareTo(b.LinkNum); |
1766 | // | 1878 | }); |
1767 | if (newSet.Contains(root)) | ||
1768 | newSet.Remove(root); | ||
1769 | |||
1770 | // Preserve link ordering | ||
1771 | // | ||
1772 | newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b) | ||
1773 | { | ||
1774 | return a.LinkNum.CompareTo(b.LinkNum); | ||
1775 | }); | ||
1776 | 1879 | ||
1777 | // Determine new root | 1880 | // Determine new root |
1778 | // | 1881 | // |
1779 | SceneObjectPart newRoot = newSet[0]; | 1882 | SceneObjectPart newRoot = newSet[0]; |
1780 | newSet.RemoveAt(0); | 1883 | newSet.RemoveAt(0); |
1781 | 1884 | ||
1782 | foreach (SceneObjectPart newChild in newSet) | 1885 | foreach (SceneObjectPart newChild in newSet) |
1783 | newChild.UpdateFlag = 0; | 1886 | newChild.UpdateFlag = 0; |
1784 | 1887 | ||
1785 | LinkObjects(newRoot, newSet); | 1888 | newRoot.ParentGroup.areUpdatesSuspended = true; |
1786 | if (!affectedGroups.Contains(newRoot.ParentGroup)) | 1889 | LinkObjects(newRoot, newSet); |
1787 | affectedGroups.Add(newRoot.ParentGroup); | 1890 | if (!affectedGroups.Contains(newRoot.ParentGroup)) |
1788 | } | 1891 | affectedGroups.Add(newRoot.ParentGroup); |
1789 | } | 1892 | } |
1790 | } | 1893 | } |
1791 | 1894 | ||
@@ -1793,8 +1896,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
1793 | // | 1896 | // |
1794 | foreach (SceneObjectGroup g in affectedGroups) | 1897 | foreach (SceneObjectGroup g in affectedGroups) |
1795 | { | 1898 | { |
1899 | // Child prims that have been unlinked and deleted will | ||
1900 | // return unless the root is deleted. This will remove them | ||
1901 | // from the database. They will be rewritten immediately, | ||
1902 | // minus the rows for the unlinked child prims. | ||
1903 | m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID); | ||
1796 | g.TriggerScriptChangedEvent(Changed.LINK); | 1904 | g.TriggerScriptChangedEvent(Changed.LINK); |
1797 | g.HasGroupChanged = true; // Persist | 1905 | g.HasGroupChanged = true; // Persist |
1906 | g.areUpdatesSuspended = false; | ||
1798 | g.ScheduleGroupForFullUpdate(); | 1907 | g.ScheduleGroupForFullUpdate(); |
1799 | } | 1908 | } |
1800 | } | 1909 | } |
@@ -1912,9 +2021,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
1912 | child.ApplyNextOwnerPermissions(); | 2021 | child.ApplyNextOwnerPermissions(); |
1913 | } | 2022 | } |
1914 | } | 2023 | } |
1915 | |||
1916 | copy.RootPart.ObjectSaleType = 0; | ||
1917 | copy.RootPart.SalePrice = 10; | ||
1918 | } | 2024 | } |
1919 | 2025 | ||
1920 | // FIXME: This section needs to be refactored so that it just calls AddSceneObject() | 2026 | // FIXME: This section needs to be refactored so that it just calls AddSceneObject() |