diff options
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/SceneGraph.cs')
-rw-r--r-- | OpenSim/Region/Framework/Scenes/SceneGraph.cs | 225 |
1 files changed, 169 insertions, 56 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 7f18140..5e8227d 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs | |||
@@ -41,6 +41,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
41 | { | 41 | { |
42 | public delegate void PhysicsCrash(); | 42 | public delegate void PhysicsCrash(); |
43 | 43 | ||
44 | public delegate void AttachToBackupDelegate(SceneObjectGroup sog); | ||
45 | |||
46 | public delegate void DetachFromBackupDelegate(SceneObjectGroup sog); | ||
47 | |||
48 | public delegate void ChangedBackupDelegate(SceneObjectGroup sog); | ||
49 | |||
44 | /// <summary> | 50 | /// <summary> |
45 | /// This class used to be called InnerScene and may not yet truly be a SceneGraph. The non scene graph components | 51 | /// This class used to be called InnerScene and may not yet truly be a SceneGraph. The non scene graph components |
46 | /// should be migrated out over time. | 52 | /// should be migrated out over time. |
@@ -54,11 +60,15 @@ namespace OpenSim.Region.Framework.Scenes | |||
54 | protected internal event PhysicsCrash UnRecoverableError; | 60 | protected internal event PhysicsCrash UnRecoverableError; |
55 | private PhysicsCrash handlerPhysicsCrash = null; | 61 | private PhysicsCrash handlerPhysicsCrash = null; |
56 | 62 | ||
63 | public event AttachToBackupDelegate OnAttachToBackup; | ||
64 | public event DetachFromBackupDelegate OnDetachFromBackup; | ||
65 | public event ChangedBackupDelegate OnChangeBackup; | ||
66 | |||
57 | #endregion | 67 | #endregion |
58 | 68 | ||
59 | #region Fields | 69 | #region Fields |
60 | 70 | ||
61 | protected object m_presenceLock = new object(); | 71 | protected OpenMetaverse.ReaderWriterLockSlim m_scenePresencesLock = new OpenMetaverse.ReaderWriterLockSlim(); |
62 | protected Dictionary<UUID, ScenePresence> m_scenePresenceMap = new Dictionary<UUID, ScenePresence>(); | 72 | protected Dictionary<UUID, ScenePresence> m_scenePresenceMap = new Dictionary<UUID, ScenePresence>(); |
63 | protected List<ScenePresence> m_scenePresenceArray = new List<ScenePresence>(); | 73 | protected List<ScenePresence> m_scenePresenceArray = new List<ScenePresence>(); |
64 | 74 | ||
@@ -120,13 +130,18 @@ namespace OpenSim.Region.Framework.Scenes | |||
120 | 130 | ||
121 | protected internal void Close() | 131 | protected internal void Close() |
122 | { | 132 | { |
123 | lock (m_presenceLock) | 133 | m_scenePresencesLock.EnterWriteLock(); |
134 | try | ||
124 | { | 135 | { |
125 | Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(); | 136 | Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(); |
126 | List<ScenePresence> newlist = new List<ScenePresence>(); | 137 | List<ScenePresence> newlist = new List<ScenePresence>(); |
127 | m_scenePresenceMap = newmap; | 138 | m_scenePresenceMap = newmap; |
128 | m_scenePresenceArray = newlist; | 139 | m_scenePresenceArray = newlist; |
129 | } | 140 | } |
141 | finally | ||
142 | { | ||
143 | m_scenePresencesLock.ExitWriteLock(); | ||
144 | } | ||
130 | 145 | ||
131 | lock (SceneObjectGroupsByFullID) | 146 | lock (SceneObjectGroupsByFullID) |
132 | SceneObjectGroupsByFullID.Clear(); | 147 | SceneObjectGroupsByFullID.Clear(); |
@@ -265,6 +280,33 @@ namespace OpenSim.Region.Framework.Scenes | |||
265 | protected internal bool AddRestoredSceneObject( | 280 | protected internal bool AddRestoredSceneObject( |
266 | SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) | 281 | SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) |
267 | { | 282 | { |
283 | if (!m_parentScene.CombineRegions) | ||
284 | { | ||
285 | // KF: Check for out-of-region, move inside and make static. | ||
286 | Vector3 npos = new Vector3(sceneObject.RootPart.GroupPosition.X, | ||
287 | sceneObject.RootPart.GroupPosition.Y, | ||
288 | sceneObject.RootPart.GroupPosition.Z); | ||
289 | 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 || | ||
290 | npos.X > Constants.RegionSize || | ||
291 | npos.Y > Constants.RegionSize)) | ||
292 | { | ||
293 | if (npos.X < 0.0) npos.X = 1.0f; | ||
294 | if (npos.Y < 0.0) npos.Y = 1.0f; | ||
295 | if (npos.Z < 0.0) npos.Z = 0.0f; | ||
296 | if (npos.X > Constants.RegionSize) npos.X = Constants.RegionSize - 1.0f; | ||
297 | if (npos.Y > Constants.RegionSize) npos.Y = Constants.RegionSize - 1.0f; | ||
298 | |||
299 | foreach (SceneObjectPart part in sceneObject.Parts) | ||
300 | { | ||
301 | part.GroupPosition = npos; | ||
302 | } | ||
303 | sceneObject.RootPart.Velocity = Vector3.Zero; | ||
304 | sceneObject.RootPart.AngularVelocity = Vector3.Zero; | ||
305 | sceneObject.RootPart.Acceleration = Vector3.Zero; | ||
306 | sceneObject.RootPart.Velocity = Vector3.Zero; | ||
307 | } | ||
308 | } | ||
309 | |||
268 | if (attachToBackup && (!alreadyPersisted)) | 310 | if (attachToBackup && (!alreadyPersisted)) |
269 | { | 311 | { |
270 | sceneObject.ForceInventoryPersistence(); | 312 | sceneObject.ForceInventoryPersistence(); |
@@ -475,6 +517,30 @@ namespace OpenSim.Region.Framework.Scenes | |||
475 | m_updateList[obj.UUID] = obj; | 517 | m_updateList[obj.UUID] = obj; |
476 | } | 518 | } |
477 | 519 | ||
520 | public void FireAttachToBackup(SceneObjectGroup obj) | ||
521 | { | ||
522 | if (OnAttachToBackup != null) | ||
523 | { | ||
524 | OnAttachToBackup(obj); | ||
525 | } | ||
526 | } | ||
527 | |||
528 | public void FireDetachFromBackup(SceneObjectGroup obj) | ||
529 | { | ||
530 | if (OnDetachFromBackup != null) | ||
531 | { | ||
532 | OnDetachFromBackup(obj); | ||
533 | } | ||
534 | } | ||
535 | |||
536 | public void FireChangeBackup(SceneObjectGroup obj) | ||
537 | { | ||
538 | if (OnChangeBackup != null) | ||
539 | { | ||
540 | OnChangeBackup(obj); | ||
541 | } | ||
542 | } | ||
543 | |||
478 | /// <summary> | 544 | /// <summary> |
479 | /// Process all pending updates | 545 | /// Process all pending updates |
480 | /// </summary> | 546 | /// </summary> |
@@ -592,7 +658,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
592 | 658 | ||
593 | Entities[presence.UUID] = presence; | 659 | Entities[presence.UUID] = presence; |
594 | 660 | ||
595 | lock (m_presenceLock) | 661 | m_scenePresencesLock.EnterWriteLock(); |
662 | try | ||
596 | { | 663 | { |
597 | Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); | 664 | Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); |
598 | List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); | 665 | List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); |
@@ -616,6 +683,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
616 | m_scenePresenceMap = newmap; | 683 | m_scenePresenceMap = newmap; |
617 | m_scenePresenceArray = newlist; | 684 | m_scenePresenceArray = newlist; |
618 | } | 685 | } |
686 | finally | ||
687 | { | ||
688 | m_scenePresencesLock.ExitWriteLock(); | ||
689 | } | ||
619 | } | 690 | } |
620 | 691 | ||
621 | /// <summary> | 692 | /// <summary> |
@@ -630,7 +701,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
630 | agentID); | 701 | agentID); |
631 | } | 702 | } |
632 | 703 | ||
633 | lock (m_presenceLock) | 704 | m_scenePresencesLock.EnterWriteLock(); |
705 | try | ||
634 | { | 706 | { |
635 | Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); | 707 | Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); |
636 | List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); | 708 | List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); |
@@ -652,6 +724,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
652 | m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); | 724 | m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); |
653 | } | 725 | } |
654 | } | 726 | } |
727 | finally | ||
728 | { | ||
729 | m_scenePresencesLock.ExitWriteLock(); | ||
730 | } | ||
655 | } | 731 | } |
656 | 732 | ||
657 | protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) | 733 | protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) |
@@ -1365,8 +1441,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
1365 | { | 1441 | { |
1366 | if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) | 1442 | if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) |
1367 | { | 1443 | { |
1368 | if (m_parentScene.AttachmentsModule != null) | 1444 | // Set the new attachment point data in the object |
1369 | m_parentScene.AttachmentsModule.UpdateAttachmentPosition(group, pos); | 1445 | byte attachmentPoint = group.GetAttachmentPoint(); |
1446 | group.UpdateGroupPosition(pos); | ||
1447 | group.IsAttachment = false; | ||
1448 | group.AbsolutePosition = group.RootPart.AttachedPos; | ||
1449 | group.AttachmentPoint = attachmentPoint; | ||
1450 | group.HasGroupChanged = true; | ||
1370 | } | 1451 | } |
1371 | else | 1452 | else |
1372 | { | 1453 | { |
@@ -1638,8 +1719,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
1638 | return; | 1719 | return; |
1639 | 1720 | ||
1640 | Monitor.Enter(m_updateLock); | 1721 | Monitor.Enter(m_updateLock); |
1722 | |||
1641 | try | 1723 | try |
1642 | { | 1724 | { |
1725 | parentGroup.areUpdatesSuspended = true; | ||
1726 | |||
1643 | List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); | 1727 | List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); |
1644 | 1728 | ||
1645 | // We do this in reverse to get the link order of the prims correct | 1729 | // We do this in reverse to get the link order of the prims correct |
@@ -1650,9 +1734,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
1650 | // Make sure no child prim is set for sale | 1734 | // Make sure no child prim is set for sale |
1651 | // So that, on delink, no prims are unwittingly | 1735 | // So that, on delink, no prims are unwittingly |
1652 | // left for sale and sold off | 1736 | // left for sale and sold off |
1653 | child.RootPart.ObjectSaleType = 0; | 1737 | |
1654 | child.RootPart.SalePrice = 10; | 1738 | if (child != null) |
1655 | childGroups.Add(child); | 1739 | { |
1740 | child.RootPart.ObjectSaleType = 0; | ||
1741 | child.RootPart.SalePrice = 10; | ||
1742 | childGroups.Add(child); | ||
1743 | } | ||
1656 | } | 1744 | } |
1657 | 1745 | ||
1658 | foreach (SceneObjectGroup child in childGroups) | 1746 | foreach (SceneObjectGroup child in childGroups) |
@@ -1671,12 +1759,19 @@ namespace OpenSim.Region.Framework.Scenes | |||
1671 | // occur on link to invoke this elsewhere (such as object selection) | 1759 | // occur on link to invoke this elsewhere (such as object selection) |
1672 | parentGroup.RootPart.CreateSelected = true; | 1760 | parentGroup.RootPart.CreateSelected = true; |
1673 | parentGroup.TriggerScriptChangedEvent(Changed.LINK); | 1761 | parentGroup.TriggerScriptChangedEvent(Changed.LINK); |
1674 | parentGroup.HasGroupChanged = true; | ||
1675 | parentGroup.ScheduleGroupForFullUpdate(); | ||
1676 | |||
1677 | } | 1762 | } |
1678 | finally | 1763 | finally |
1679 | { | 1764 | { |
1765 | lock (SceneObjectGroupsByLocalPartID) | ||
1766 | { | ||
1767 | foreach (SceneObjectPart part in parentGroup.Parts) | ||
1768 | SceneObjectGroupsByLocalPartID[part.LocalId] = parentGroup; | ||
1769 | } | ||
1770 | |||
1771 | parentGroup.areUpdatesSuspended = false; | ||
1772 | parentGroup.HasGroupChanged = true; | ||
1773 | parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true); | ||
1774 | parentGroup.ScheduleGroupForFullUpdate(); | ||
1680 | Monitor.Exit(m_updateLock); | 1775 | Monitor.Exit(m_updateLock); |
1681 | } | 1776 | } |
1682 | } | 1777 | } |
@@ -1713,21 +1808,24 @@ namespace OpenSim.Region.Framework.Scenes | |||
1713 | 1808 | ||
1714 | SceneObjectGroup group = part.ParentGroup; | 1809 | SceneObjectGroup group = part.ParentGroup; |
1715 | if (!affectedGroups.Contains(group)) | 1810 | if (!affectedGroups.Contains(group)) |
1811 | { | ||
1812 | group.areUpdatesSuspended = true; | ||
1716 | affectedGroups.Add(group); | 1813 | affectedGroups.Add(group); |
1814 | } | ||
1717 | } | 1815 | } |
1718 | } | 1816 | } |
1719 | } | 1817 | } |
1720 | 1818 | ||
1721 | foreach (SceneObjectPart child in childParts) | 1819 | if (childParts.Count > 0) |
1722 | { | 1820 | { |
1723 | // Unlink all child parts from their groups | 1821 | foreach (SceneObjectPart child in childParts) |
1724 | // | 1822 | { |
1725 | child.ParentGroup.DelinkFromGroup(child, true); | 1823 | // Unlink all child parts from their groups |
1726 | 1824 | // | |
1727 | // These are not in affected groups and will not be | 1825 | child.ParentGroup.DelinkFromGroup(child, true); |
1728 | // handled further. Do the honors here. | 1826 | child.ParentGroup.HasGroupChanged = true; |
1729 | child.ParentGroup.HasGroupChanged = true; | 1827 | child.ParentGroup.ScheduleGroupForFullUpdate(); |
1730 | child.ParentGroup.ScheduleGroupForFullUpdate(); | 1828 | } |
1731 | } | 1829 | } |
1732 | 1830 | ||
1733 | foreach (SceneObjectPart root in rootParts) | 1831 | foreach (SceneObjectPart root in rootParts) |
@@ -1737,56 +1835,68 @@ namespace OpenSim.Region.Framework.Scenes | |||
1737 | // However, editing linked parts and unlinking may be different | 1835 | // However, editing linked parts and unlinking may be different |
1738 | // | 1836 | // |
1739 | SceneObjectGroup group = root.ParentGroup; | 1837 | SceneObjectGroup group = root.ParentGroup; |
1838 | group.areUpdatesSuspended = true; | ||
1740 | 1839 | ||
1741 | List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); | 1840 | List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); |
1742 | int numChildren = newSet.Count; | 1841 | int numChildren = newSet.Count; |
1743 | 1842 | ||
1843 | if (numChildren == 1) | ||
1844 | break; | ||
1845 | |||
1744 | // If there are prims left in a link set, but the root is | 1846 | // If there are prims left in a link set, but the root is |
1745 | // slated for unlink, we need to do this | 1847 | // slated for unlink, we need to do this |
1848 | // Unlink the remaining set | ||
1746 | // | 1849 | // |
1747 | if (numChildren != 1) | 1850 | bool sendEventsToRemainder = true; |
1748 | { | 1851 | if (numChildren > 1) |
1749 | // Unlink the remaining set | 1852 | sendEventsToRemainder = false; |
1750 | // | ||
1751 | bool sendEventsToRemainder = true; | ||
1752 | if (numChildren > 1) | ||
1753 | sendEventsToRemainder = false; | ||
1754 | 1853 | ||
1755 | foreach (SceneObjectPart p in newSet) | 1854 | foreach (SceneObjectPart p in newSet) |
1855 | { | ||
1856 | if (p != group.RootPart) | ||
1756 | { | 1857 | { |
1757 | if (p != group.RootPart) | 1858 | group.DelinkFromGroup(p, sendEventsToRemainder); |
1758 | group.DelinkFromGroup(p, sendEventsToRemainder); | 1859 | if (numChildren > 2) |
1860 | { | ||
1861 | p.ParentGroup.areUpdatesSuspended = true; | ||
1862 | } | ||
1863 | else | ||
1864 | { | ||
1865 | p.ParentGroup.HasGroupChanged = true; | ||
1866 | p.ParentGroup.ScheduleGroupForFullUpdate(); | ||
1867 | } | ||
1759 | } | 1868 | } |
1869 | } | ||
1870 | |||
1871 | // If there is more than one prim remaining, we | ||
1872 | // need to re-link | ||
1873 | // | ||
1874 | if (numChildren > 2) | ||
1875 | { | ||
1876 | // Remove old root | ||
1877 | // | ||
1878 | if (newSet.Contains(root)) | ||
1879 | newSet.Remove(root); | ||
1760 | 1880 | ||
1761 | // If there is more than one prim remaining, we | 1881 | // Preserve link ordering |
1762 | // need to re-link | ||
1763 | // | 1882 | // |
1764 | if (numChildren > 2) | 1883 | newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b) |
1765 | { | 1884 | { |
1766 | // Remove old root | 1885 | return a.LinkNum.CompareTo(b.LinkNum); |
1767 | // | 1886 | }); |
1768 | if (newSet.Contains(root)) | ||
1769 | newSet.Remove(root); | ||
1770 | |||
1771 | // Preserve link ordering | ||
1772 | // | ||
1773 | newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b) | ||
1774 | { | ||
1775 | return a.LinkNum.CompareTo(b.LinkNum); | ||
1776 | }); | ||
1777 | 1887 | ||
1778 | // Determine new root | 1888 | // Determine new root |
1779 | // | 1889 | // |
1780 | SceneObjectPart newRoot = newSet[0]; | 1890 | SceneObjectPart newRoot = newSet[0]; |
1781 | newSet.RemoveAt(0); | 1891 | newSet.RemoveAt(0); |
1782 | 1892 | ||
1783 | foreach (SceneObjectPart newChild in newSet) | 1893 | foreach (SceneObjectPart newChild in newSet) |
1784 | newChild.ClearUpdateSchedule(); | 1894 | newChild.ClearUpdateSchedule(); |
1785 | 1895 | ||
1786 | LinkObjects(newRoot, newSet); | 1896 | newRoot.ParentGroup.areUpdatesSuspended = true; |
1787 | if (!affectedGroups.Contains(newRoot.ParentGroup)) | 1897 | LinkObjects(newRoot, newSet); |
1788 | affectedGroups.Add(newRoot.ParentGroup); | 1898 | if (!affectedGroups.Contains(newRoot.ParentGroup)) |
1789 | } | 1899 | affectedGroups.Add(newRoot.ParentGroup); |
1790 | } | 1900 | } |
1791 | } | 1901 | } |
1792 | 1902 | ||
@@ -1794,8 +1904,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
1794 | // | 1904 | // |
1795 | foreach (SceneObjectGroup g in affectedGroups) | 1905 | foreach (SceneObjectGroup g in affectedGroups) |
1796 | { | 1906 | { |
1907 | // Child prims that have been unlinked and deleted will | ||
1908 | // return unless the root is deleted. This will remove them | ||
1909 | // from the database. They will be rewritten immediately, | ||
1910 | // minus the rows for the unlinked child prims. | ||
1911 | m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID); | ||
1797 | g.TriggerScriptChangedEvent(Changed.LINK); | 1912 | g.TriggerScriptChangedEvent(Changed.LINK); |
1798 | g.HasGroupChanged = true; // Persist | 1913 | g.HasGroupChanged = true; // Persist |
1914 | g.areUpdatesSuspended = false; | ||
1799 | g.ScheduleGroupForFullUpdate(); | 1915 | g.ScheduleGroupForFullUpdate(); |
1800 | } | 1916 | } |
1801 | } | 1917 | } |
@@ -1913,9 +2029,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
1913 | child.ApplyNextOwnerPermissions(); | 2029 | child.ApplyNextOwnerPermissions(); |
1914 | } | 2030 | } |
1915 | } | 2031 | } |
1916 | |||
1917 | copy.RootPart.ObjectSaleType = 0; | ||
1918 | copy.RootPart.SalePrice = 10; | ||
1919 | } | 2032 | } |
1920 | 2033 | ||
1921 | // FIXME: This section needs to be refactored so that it just calls AddSceneObject() | 2034 | // FIXME: This section needs to be refactored so that it just calls AddSceneObject() |