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 1af8346..c4dd655 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); |
@@ -60,11 +66,15 @@ namespace OpenSim.Region.Framework.Scenes | |||
60 | protected internal event PhysicsCrash UnRecoverableError; | 66 | protected internal event PhysicsCrash UnRecoverableError; |
61 | private PhysicsCrash handlerPhysicsCrash = null; | 67 | private PhysicsCrash handlerPhysicsCrash = null; |
62 | 68 | ||
69 | public event AttachToBackupDelegate OnAttachToBackup; | ||
70 | public event DetachFromBackupDelegate OnDetachFromBackup; | ||
71 | public event ChangedBackupDelegate OnChangeBackup; | ||
72 | |||
63 | #endregion | 73 | #endregion |
64 | 74 | ||
65 | #region Fields | 75 | #region Fields |
66 | 76 | ||
67 | protected object m_presenceLock = new object(); | 77 | protected OpenMetaverse.ReaderWriterLockSlim m_scenePresencesLock = new OpenMetaverse.ReaderWriterLockSlim(); |
68 | protected Dictionary<UUID, ScenePresence> m_scenePresenceMap = new Dictionary<UUID, ScenePresence>(); | 78 | protected Dictionary<UUID, ScenePresence> m_scenePresenceMap = new Dictionary<UUID, ScenePresence>(); |
69 | protected List<ScenePresence> m_scenePresenceArray = new List<ScenePresence>(); | 79 | protected List<ScenePresence> m_scenePresenceArray = new List<ScenePresence>(); |
70 | 80 | ||
@@ -126,13 +136,18 @@ namespace OpenSim.Region.Framework.Scenes | |||
126 | 136 | ||
127 | protected internal void Close() | 137 | protected internal void Close() |
128 | { | 138 | { |
129 | lock (m_presenceLock) | 139 | m_scenePresencesLock.EnterWriteLock(); |
140 | try | ||
130 | { | 141 | { |
131 | Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(); | 142 | Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(); |
132 | List<ScenePresence> newlist = new List<ScenePresence>(); | 143 | List<ScenePresence> newlist = new List<ScenePresence>(); |
133 | m_scenePresenceMap = newmap; | 144 | m_scenePresenceMap = newmap; |
134 | m_scenePresenceArray = newlist; | 145 | m_scenePresenceArray = newlist; |
135 | } | 146 | } |
147 | finally | ||
148 | { | ||
149 | m_scenePresencesLock.ExitWriteLock(); | ||
150 | } | ||
136 | 151 | ||
137 | lock (SceneObjectGroupsByFullID) | 152 | lock (SceneObjectGroupsByFullID) |
138 | SceneObjectGroupsByFullID.Clear(); | 153 | SceneObjectGroupsByFullID.Clear(); |
@@ -271,6 +286,33 @@ namespace OpenSim.Region.Framework.Scenes | |||
271 | protected internal bool AddRestoredSceneObject( | 286 | protected internal bool AddRestoredSceneObject( |
272 | SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) | 287 | SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) |
273 | { | 288 | { |
289 | if (!m_parentScene.CombineRegions) | ||
290 | { | ||
291 | // KF: Check for out-of-region, move inside and make static. | ||
292 | Vector3 npos = new Vector3(sceneObject.RootPart.GroupPosition.X, | ||
293 | sceneObject.RootPart.GroupPosition.Y, | ||
294 | sceneObject.RootPart.GroupPosition.Z); | ||
295 | 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 || | ||
296 | npos.X > Constants.RegionSize || | ||
297 | npos.Y > Constants.RegionSize)) | ||
298 | { | ||
299 | if (npos.X < 0.0) npos.X = 1.0f; | ||
300 | if (npos.Y < 0.0) npos.Y = 1.0f; | ||
301 | if (npos.Z < 0.0) npos.Z = 0.0f; | ||
302 | if (npos.X > Constants.RegionSize) npos.X = Constants.RegionSize - 1.0f; | ||
303 | if (npos.Y > Constants.RegionSize) npos.Y = Constants.RegionSize - 1.0f; | ||
304 | |||
305 | foreach (SceneObjectPart part in sceneObject.Parts) | ||
306 | { | ||
307 | part.GroupPosition = npos; | ||
308 | } | ||
309 | sceneObject.RootPart.Velocity = Vector3.Zero; | ||
310 | sceneObject.RootPart.AngularVelocity = Vector3.Zero; | ||
311 | sceneObject.RootPart.Acceleration = Vector3.Zero; | ||
312 | sceneObject.RootPart.Velocity = Vector3.Zero; | ||
313 | } | ||
314 | } | ||
315 | |||
274 | if (attachToBackup && (!alreadyPersisted)) | 316 | if (attachToBackup && (!alreadyPersisted)) |
275 | { | 317 | { |
276 | sceneObject.ForceInventoryPersistence(); | 318 | sceneObject.ForceInventoryPersistence(); |
@@ -481,6 +523,30 @@ namespace OpenSim.Region.Framework.Scenes | |||
481 | m_updateList[obj.UUID] = obj; | 523 | m_updateList[obj.UUID] = obj; |
482 | } | 524 | } |
483 | 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 | |||
484 | /// <summary> | 550 | /// <summary> |
485 | /// Process all pending updates | 551 | /// Process all pending updates |
486 | /// </summary> | 552 | /// </summary> |
@@ -598,7 +664,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
598 | 664 | ||
599 | Entities[presence.UUID] = presence; | 665 | Entities[presence.UUID] = presence; |
600 | 666 | ||
601 | lock (m_presenceLock) | 667 | m_scenePresencesLock.EnterWriteLock(); |
668 | try | ||
602 | { | 669 | { |
603 | Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); | 670 | Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); |
604 | List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); | 671 | List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); |
@@ -622,6 +689,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
622 | m_scenePresenceMap = newmap; | 689 | m_scenePresenceMap = newmap; |
623 | m_scenePresenceArray = newlist; | 690 | m_scenePresenceArray = newlist; |
624 | } | 691 | } |
692 | finally | ||
693 | { | ||
694 | m_scenePresencesLock.ExitWriteLock(); | ||
695 | } | ||
625 | } | 696 | } |
626 | 697 | ||
627 | /// <summary> | 698 | /// <summary> |
@@ -636,7 +707,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
636 | agentID); | 707 | agentID); |
637 | } | 708 | } |
638 | 709 | ||
639 | lock (m_presenceLock) | 710 | m_scenePresencesLock.EnterWriteLock(); |
711 | try | ||
640 | { | 712 | { |
641 | Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); | 713 | Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); |
642 | List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); | 714 | List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); |
@@ -658,6 +730,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
658 | m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); | 730 | m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); |
659 | } | 731 | } |
660 | } | 732 | } |
733 | finally | ||
734 | { | ||
735 | m_scenePresencesLock.ExitWriteLock(); | ||
736 | } | ||
661 | } | 737 | } |
662 | 738 | ||
663 | protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) | 739 | protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) |
@@ -1371,8 +1447,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
1371 | { | 1447 | { |
1372 | if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) | 1448 | if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) |
1373 | { | 1449 | { |
1374 | if (m_parentScene.AttachmentsModule != null) | 1450 | // Set the new attachment point data in the object |
1375 | m_parentScene.AttachmentsModule.UpdateAttachmentPosition(group, pos); | 1451 | byte attachmentPoint = group.GetAttachmentPoint(); |
1452 | group.UpdateGroupPosition(pos); | ||
1453 | group.IsAttachment = false; | ||
1454 | group.AbsolutePosition = group.RootPart.AttachedPos; | ||
1455 | group.AttachmentPoint = attachmentPoint; | ||
1456 | group.HasGroupChanged = true; | ||
1376 | } | 1457 | } |
1377 | else | 1458 | else |
1378 | { | 1459 | { |
@@ -1644,8 +1725,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
1644 | return; | 1725 | return; |
1645 | 1726 | ||
1646 | Monitor.Enter(m_updateLock); | 1727 | Monitor.Enter(m_updateLock); |
1728 | |||
1647 | try | 1729 | try |
1648 | { | 1730 | { |
1731 | parentGroup.areUpdatesSuspended = true; | ||
1732 | |||
1649 | List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); | 1733 | List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); |
1650 | 1734 | ||
1651 | // We do this in reverse to get the link order of the prims correct | 1735 | // We do this in reverse to get the link order of the prims correct |
@@ -1656,9 +1740,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
1656 | // Make sure no child prim is set for sale | 1740 | // Make sure no child prim is set for sale |
1657 | // So that, on delink, no prims are unwittingly | 1741 | // So that, on delink, no prims are unwittingly |
1658 | // left for sale and sold off | 1742 | // left for sale and sold off |
1659 | child.RootPart.ObjectSaleType = 0; | 1743 | |
1660 | child.RootPart.SalePrice = 10; | 1744 | if (child != null) |
1661 | childGroups.Add(child); | 1745 | { |
1746 | child.RootPart.ObjectSaleType = 0; | ||
1747 | child.RootPart.SalePrice = 10; | ||
1748 | childGroups.Add(child); | ||
1749 | } | ||
1662 | } | 1750 | } |
1663 | 1751 | ||
1664 | foreach (SceneObjectGroup child in childGroups) | 1752 | foreach (SceneObjectGroup child in childGroups) |
@@ -1677,12 +1765,19 @@ namespace OpenSim.Region.Framework.Scenes | |||
1677 | // occur on link to invoke this elsewhere (such as object selection) | 1765 | // occur on link to invoke this elsewhere (such as object selection) |
1678 | parentGroup.RootPart.CreateSelected = true; | 1766 | parentGroup.RootPart.CreateSelected = true; |
1679 | parentGroup.TriggerScriptChangedEvent(Changed.LINK); | 1767 | parentGroup.TriggerScriptChangedEvent(Changed.LINK); |
1680 | parentGroup.HasGroupChanged = true; | ||
1681 | parentGroup.ScheduleGroupForFullUpdate(); | ||
1682 | |||
1683 | } | 1768 | } |
1684 | finally | 1769 | finally |
1685 | { | 1770 | { |
1771 | lock (SceneObjectGroupsByLocalPartID) | ||
1772 | { | ||
1773 | foreach (SceneObjectPart part in parentGroup.Parts) | ||
1774 | SceneObjectGroupsByLocalPartID[part.LocalId] = parentGroup; | ||
1775 | } | ||
1776 | |||
1777 | parentGroup.areUpdatesSuspended = false; | ||
1778 | parentGroup.HasGroupChanged = true; | ||
1779 | parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true); | ||
1780 | parentGroup.ScheduleGroupForFullUpdate(); | ||
1686 | Monitor.Exit(m_updateLock); | 1781 | Monitor.Exit(m_updateLock); |
1687 | } | 1782 | } |
1688 | } | 1783 | } |
@@ -1719,21 +1814,24 @@ namespace OpenSim.Region.Framework.Scenes | |||
1719 | 1814 | ||
1720 | SceneObjectGroup group = part.ParentGroup; | 1815 | SceneObjectGroup group = part.ParentGroup; |
1721 | if (!affectedGroups.Contains(group)) | 1816 | if (!affectedGroups.Contains(group)) |
1817 | { | ||
1818 | group.areUpdatesSuspended = true; | ||
1722 | affectedGroups.Add(group); | 1819 | affectedGroups.Add(group); |
1820 | } | ||
1723 | } | 1821 | } |
1724 | } | 1822 | } |
1725 | } | 1823 | } |
1726 | 1824 | ||
1727 | foreach (SceneObjectPart child in childParts) | 1825 | if (childParts.Count > 0) |
1728 | { | 1826 | { |
1729 | // Unlink all child parts from their groups | 1827 | foreach (SceneObjectPart child in childParts) |
1730 | // | 1828 | { |
1731 | child.ParentGroup.DelinkFromGroup(child, true); | 1829 | // Unlink all child parts from their groups |
1732 | 1830 | // | |
1733 | // These are not in affected groups and will not be | 1831 | child.ParentGroup.DelinkFromGroup(child, true); |
1734 | // handled further. Do the honors here. | 1832 | child.ParentGroup.HasGroupChanged = true; |
1735 | child.ParentGroup.HasGroupChanged = true; | 1833 | child.ParentGroup.ScheduleGroupForFullUpdate(); |
1736 | child.ParentGroup.ScheduleGroupForFullUpdate(); | 1834 | } |
1737 | } | 1835 | } |
1738 | 1836 | ||
1739 | foreach (SceneObjectPart root in rootParts) | 1837 | foreach (SceneObjectPart root in rootParts) |
@@ -1743,56 +1841,68 @@ namespace OpenSim.Region.Framework.Scenes | |||
1743 | // However, editing linked parts and unlinking may be different | 1841 | // However, editing linked parts and unlinking may be different |
1744 | // | 1842 | // |
1745 | SceneObjectGroup group = root.ParentGroup; | 1843 | SceneObjectGroup group = root.ParentGroup; |
1844 | group.areUpdatesSuspended = true; | ||
1746 | 1845 | ||
1747 | List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); | 1846 | List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); |
1748 | int numChildren = newSet.Count; | 1847 | int numChildren = newSet.Count; |
1749 | 1848 | ||
1849 | if (numChildren == 1) | ||
1850 | break; | ||
1851 | |||
1750 | // If there are prims left in a link set, but the root is | 1852 | // If there are prims left in a link set, but the root is |
1751 | // slated for unlink, we need to do this | 1853 | // slated for unlink, we need to do this |
1854 | // Unlink the remaining set | ||
1752 | // | 1855 | // |
1753 | if (numChildren != 1) | 1856 | bool sendEventsToRemainder = true; |
1754 | { | 1857 | if (numChildren > 1) |
1755 | // Unlink the remaining set | 1858 | sendEventsToRemainder = false; |
1756 | // | ||
1757 | bool sendEventsToRemainder = true; | ||
1758 | if (numChildren > 1) | ||
1759 | sendEventsToRemainder = false; | ||
1760 | 1859 | ||
1761 | foreach (SceneObjectPart p in newSet) | 1860 | foreach (SceneObjectPart p in newSet) |
1861 | { | ||
1862 | if (p != group.RootPart) | ||
1762 | { | 1863 | { |
1763 | if (p != group.RootPart) | 1864 | group.DelinkFromGroup(p, sendEventsToRemainder); |
1764 | group.DelinkFromGroup(p, sendEventsToRemainder); | 1865 | if (numChildren > 2) |
1866 | { | ||
1867 | p.ParentGroup.areUpdatesSuspended = true; | ||
1868 | } | ||
1869 | else | ||
1870 | { | ||
1871 | p.ParentGroup.HasGroupChanged = true; | ||
1872 | p.ParentGroup.ScheduleGroupForFullUpdate(); | ||
1873 | } | ||
1765 | } | 1874 | } |
1875 | } | ||
1876 | |||
1877 | // If there is more than one prim remaining, we | ||
1878 | // need to re-link | ||
1879 | // | ||
1880 | if (numChildren > 2) | ||
1881 | { | ||
1882 | // Remove old root | ||
1883 | // | ||
1884 | if (newSet.Contains(root)) | ||
1885 | newSet.Remove(root); | ||
1766 | 1886 | ||
1767 | // If there is more than one prim remaining, we | 1887 | // Preserve link ordering |
1768 | // need to re-link | ||
1769 | // | 1888 | // |
1770 | if (numChildren > 2) | 1889 | newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b) |
1771 | { | 1890 | { |
1772 | // Remove old root | 1891 | return a.LinkNum.CompareTo(b.LinkNum); |
1773 | // | 1892 | }); |
1774 | if (newSet.Contains(root)) | ||
1775 | newSet.Remove(root); | ||
1776 | |||
1777 | // Preserve link ordering | ||
1778 | // | ||
1779 | newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b) | ||
1780 | { | ||
1781 | return a.LinkNum.CompareTo(b.LinkNum); | ||
1782 | }); | ||
1783 | 1893 | ||
1784 | // Determine new root | 1894 | // Determine new root |
1785 | // | 1895 | // |
1786 | SceneObjectPart newRoot = newSet[0]; | 1896 | SceneObjectPart newRoot = newSet[0]; |
1787 | newSet.RemoveAt(0); | 1897 | newSet.RemoveAt(0); |
1788 | 1898 | ||
1789 | foreach (SceneObjectPart newChild in newSet) | 1899 | foreach (SceneObjectPart newChild in newSet) |
1790 | newChild.ClearUpdateSchedule(); | 1900 | newChild.ClearUpdateSchedule(); |
1791 | 1901 | ||
1792 | LinkObjects(newRoot, newSet); | 1902 | newRoot.ParentGroup.areUpdatesSuspended = true; |
1793 | if (!affectedGroups.Contains(newRoot.ParentGroup)) | 1903 | LinkObjects(newRoot, newSet); |
1794 | affectedGroups.Add(newRoot.ParentGroup); | 1904 | if (!affectedGroups.Contains(newRoot.ParentGroup)) |
1795 | } | 1905 | affectedGroups.Add(newRoot.ParentGroup); |
1796 | } | 1906 | } |
1797 | } | 1907 | } |
1798 | 1908 | ||
@@ -1800,8 +1910,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
1800 | // | 1910 | // |
1801 | foreach (SceneObjectGroup g in affectedGroups) | 1911 | foreach (SceneObjectGroup g in affectedGroups) |
1802 | { | 1912 | { |
1913 | // Child prims that have been unlinked and deleted will | ||
1914 | // return unless the root is deleted. This will remove them | ||
1915 | // from the database. They will be rewritten immediately, | ||
1916 | // minus the rows for the unlinked child prims. | ||
1917 | m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID); | ||
1803 | g.TriggerScriptChangedEvent(Changed.LINK); | 1918 | g.TriggerScriptChangedEvent(Changed.LINK); |
1804 | g.HasGroupChanged = true; // Persist | 1919 | g.HasGroupChanged = true; // Persist |
1920 | g.areUpdatesSuspended = false; | ||
1805 | g.ScheduleGroupForFullUpdate(); | 1921 | g.ScheduleGroupForFullUpdate(); |
1806 | } | 1922 | } |
1807 | } | 1923 | } |
@@ -1919,9 +2035,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
1919 | child.ApplyNextOwnerPermissions(); | 2035 | child.ApplyNextOwnerPermissions(); |
1920 | } | 2036 | } |
1921 | } | 2037 | } |
1922 | |||
1923 | copy.RootPart.ObjectSaleType = 0; | ||
1924 | copy.RootPart.SalePrice = 10; | ||
1925 | } | 2038 | } |
1926 | 2039 | ||
1927 | // FIXME: This section needs to be refactored so that it just calls AddSceneObject() | 2040 | // FIXME: This section needs to be refactored so that it just calls AddSceneObject() |