aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework/Scenes/SceneGraph.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/SceneGraph.cs')
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs230
1 files changed, 174 insertions, 56 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index 06de72f..aecca27 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();
@@ -353,6 +395,11 @@ namespace OpenSim.Region.Framework.Scenes
353 /// </returns> 395 /// </returns>
354 protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) 396 protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates)
355 { 397 {
398 if (sceneObject == null)
399 {
400 m_log.ErrorFormat("[SCENEGRAPH]: Tried to add null scene object");
401 return false;
402 }
356 if (sceneObject.UUID == UUID.Zero) 403 if (sceneObject.UUID == UUID.Zero)
357 { 404 {
358 m_log.ErrorFormat( 405 m_log.ErrorFormat(
@@ -487,6 +534,30 @@ namespace OpenSim.Region.Framework.Scenes
487 m_updateList[obj.UUID] = obj; 534 m_updateList[obj.UUID] = obj;
488 } 535 }
489 536
537 public void FireAttachToBackup(SceneObjectGroup obj)
538 {
539 if (OnAttachToBackup != null)
540 {
541 OnAttachToBackup(obj);
542 }
543 }
544
545 public void FireDetachFromBackup(SceneObjectGroup obj)
546 {
547 if (OnDetachFromBackup != null)
548 {
549 OnDetachFromBackup(obj);
550 }
551 }
552
553 public void FireChangeBackup(SceneObjectGroup obj)
554 {
555 if (OnChangeBackup != null)
556 {
557 OnChangeBackup(obj);
558 }
559 }
560
490 /// <summary> 561 /// <summary>
491 /// Process all pending updates 562 /// Process all pending updates
492 /// </summary> 563 /// </summary>
@@ -604,7 +675,8 @@ namespace OpenSim.Region.Framework.Scenes
604 675
605 Entities[presence.UUID] = presence; 676 Entities[presence.UUID] = presence;
606 677
607 lock (m_presenceLock) 678 m_scenePresencesLock.EnterWriteLock();
679 try
608 { 680 {
609 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 681 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
610 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 682 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -628,6 +700,10 @@ namespace OpenSim.Region.Framework.Scenes
628 m_scenePresenceMap = newmap; 700 m_scenePresenceMap = newmap;
629 m_scenePresenceArray = newlist; 701 m_scenePresenceArray = newlist;
630 } 702 }
703 finally
704 {
705 m_scenePresencesLock.ExitWriteLock();
706 }
631 } 707 }
632 708
633 /// <summary> 709 /// <summary>
@@ -642,7 +718,8 @@ namespace OpenSim.Region.Framework.Scenes
642 agentID); 718 agentID);
643 } 719 }
644 720
645 lock (m_presenceLock) 721 m_scenePresencesLock.EnterWriteLock();
722 try
646 { 723 {
647 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 724 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
648 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 725 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -664,6 +741,10 @@ namespace OpenSim.Region.Framework.Scenes
664 m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); 741 m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID);
665 } 742 }
666 } 743 }
744 finally
745 {
746 m_scenePresencesLock.ExitWriteLock();
747 }
667 } 748 }
668 749
669 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) 750 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F)
@@ -1379,8 +1460,13 @@ namespace OpenSim.Region.Framework.Scenes
1379 { 1460 {
1380 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) 1461 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0))
1381 { 1462 {
1382 if (m_parentScene.AttachmentsModule != null) 1463 // Set the new attachment point data in the object
1383 m_parentScene.AttachmentsModule.UpdateAttachmentPosition(group, pos); 1464 byte attachmentPoint = group.GetAttachmentPoint();
1465 group.UpdateGroupPosition(pos);
1466 group.IsAttachment = false;
1467 group.AbsolutePosition = group.RootPart.AttachedPos;
1468 group.AttachmentPoint = attachmentPoint;
1469 group.HasGroupChanged = true;
1384 } 1470 }
1385 else 1471 else
1386 { 1472 {
@@ -1652,8 +1738,11 @@ namespace OpenSim.Region.Framework.Scenes
1652 return; 1738 return;
1653 1739
1654 Monitor.Enter(m_updateLock); 1740 Monitor.Enter(m_updateLock);
1741
1655 try 1742 try
1656 { 1743 {
1744 parentGroup.areUpdatesSuspended = true;
1745
1657 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); 1746 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>();
1658 1747
1659 // We do this in reverse to get the link order of the prims correct 1748 // We do this in reverse to get the link order of the prims correct
@@ -1664,9 +1753,13 @@ namespace OpenSim.Region.Framework.Scenes
1664 // Make sure no child prim is set for sale 1753 // Make sure no child prim is set for sale
1665 // So that, on delink, no prims are unwittingly 1754 // So that, on delink, no prims are unwittingly
1666 // left for sale and sold off 1755 // left for sale and sold off
1667 child.RootPart.ObjectSaleType = 0; 1756
1668 child.RootPart.SalePrice = 10; 1757 if (child != null)
1669 childGroups.Add(child); 1758 {
1759 child.RootPart.ObjectSaleType = 0;
1760 child.RootPart.SalePrice = 10;
1761 childGroups.Add(child);
1762 }
1670 } 1763 }
1671 1764
1672 foreach (SceneObjectGroup child in childGroups) 1765 foreach (SceneObjectGroup child in childGroups)
@@ -1685,12 +1778,19 @@ namespace OpenSim.Region.Framework.Scenes
1685 // occur on link to invoke this elsewhere (such as object selection) 1778 // occur on link to invoke this elsewhere (such as object selection)
1686 parentGroup.RootPart.CreateSelected = true; 1779 parentGroup.RootPart.CreateSelected = true;
1687 parentGroup.TriggerScriptChangedEvent(Changed.LINK); 1780 parentGroup.TriggerScriptChangedEvent(Changed.LINK);
1688 parentGroup.HasGroupChanged = true;
1689 parentGroup.ScheduleGroupForFullUpdate();
1690
1691 } 1781 }
1692 finally 1782 finally
1693 { 1783 {
1784 lock (SceneObjectGroupsByLocalPartID)
1785 {
1786 foreach (SceneObjectPart part in parentGroup.Parts)
1787 SceneObjectGroupsByLocalPartID[part.LocalId] = parentGroup;
1788 }
1789
1790 parentGroup.areUpdatesSuspended = false;
1791 parentGroup.HasGroupChanged = true;
1792 parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true);
1793 parentGroup.ScheduleGroupForFullUpdate();
1694 Monitor.Exit(m_updateLock); 1794 Monitor.Exit(m_updateLock);
1695 } 1795 }
1696 } 1796 }
@@ -1727,21 +1827,24 @@ namespace OpenSim.Region.Framework.Scenes
1727 1827
1728 SceneObjectGroup group = part.ParentGroup; 1828 SceneObjectGroup group = part.ParentGroup;
1729 if (!affectedGroups.Contains(group)) 1829 if (!affectedGroups.Contains(group))
1830 {
1831 group.areUpdatesSuspended = true;
1730 affectedGroups.Add(group); 1832 affectedGroups.Add(group);
1833 }
1731 } 1834 }
1732 } 1835 }
1733 } 1836 }
1734 1837
1735 foreach (SceneObjectPart child in childParts) 1838 if (childParts.Count > 0)
1736 { 1839 {
1737 // Unlink all child parts from their groups 1840 foreach (SceneObjectPart child in childParts)
1738 // 1841 {
1739 child.ParentGroup.DelinkFromGroup(child, true); 1842 // Unlink all child parts from their groups
1740 1843 //
1741 // These are not in affected groups and will not be 1844 child.ParentGroup.DelinkFromGroup(child, true);
1742 // handled further. Do the honors here. 1845 child.ParentGroup.HasGroupChanged = true;
1743 child.ParentGroup.HasGroupChanged = true; 1846 child.ParentGroup.ScheduleGroupForFullUpdate();
1744 child.ParentGroup.ScheduleGroupForFullUpdate(); 1847 }
1745 } 1848 }
1746 1849
1747 foreach (SceneObjectPart root in rootParts) 1850 foreach (SceneObjectPart root in rootParts)
@@ -1751,56 +1854,68 @@ namespace OpenSim.Region.Framework.Scenes
1751 // However, editing linked parts and unlinking may be different 1854 // However, editing linked parts and unlinking may be different
1752 // 1855 //
1753 SceneObjectGroup group = root.ParentGroup; 1856 SceneObjectGroup group = root.ParentGroup;
1857 group.areUpdatesSuspended = true;
1754 1858
1755 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); 1859 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts);
1756 int numChildren = newSet.Count; 1860 int numChildren = newSet.Count;
1757 1861
1862 if (numChildren == 1)
1863 break;
1864
1758 // If there are prims left in a link set, but the root is 1865 // If there are prims left in a link set, but the root is
1759 // slated for unlink, we need to do this 1866 // slated for unlink, we need to do this
1867 // Unlink the remaining set
1760 // 1868 //
1761 if (numChildren != 1) 1869 bool sendEventsToRemainder = true;
1762 { 1870 if (numChildren > 1)
1763 // Unlink the remaining set 1871 sendEventsToRemainder = false;
1764 //
1765 bool sendEventsToRemainder = true;
1766 if (numChildren > 1)
1767 sendEventsToRemainder = false;
1768 1872
1769 foreach (SceneObjectPart p in newSet) 1873 foreach (SceneObjectPart p in newSet)
1874 {
1875 if (p != group.RootPart)
1770 { 1876 {
1771 if (p != group.RootPart) 1877 group.DelinkFromGroup(p, sendEventsToRemainder);
1772 group.DelinkFromGroup(p, sendEventsToRemainder); 1878 if (numChildren > 2)
1879 {
1880 p.ParentGroup.areUpdatesSuspended = true;
1881 }
1882 else
1883 {
1884 p.ParentGroup.HasGroupChanged = true;
1885 p.ParentGroup.ScheduleGroupForFullUpdate();
1886 }
1773 } 1887 }
1888 }
1889
1890 // If there is more than one prim remaining, we
1891 // need to re-link
1892 //
1893 if (numChildren > 2)
1894 {
1895 // Remove old root
1896 //
1897 if (newSet.Contains(root))
1898 newSet.Remove(root);
1774 1899
1775 // If there is more than one prim remaining, we 1900 // Preserve link ordering
1776 // need to re-link
1777 // 1901 //
1778 if (numChildren > 2) 1902 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1779 { 1903 {
1780 // Remove old root 1904 return a.LinkNum.CompareTo(b.LinkNum);
1781 // 1905 });
1782 if (newSet.Contains(root))
1783 newSet.Remove(root);
1784
1785 // Preserve link ordering
1786 //
1787 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1788 {
1789 return a.LinkNum.CompareTo(b.LinkNum);
1790 });
1791 1906
1792 // Determine new root 1907 // Determine new root
1793 // 1908 //
1794 SceneObjectPart newRoot = newSet[0]; 1909 SceneObjectPart newRoot = newSet[0];
1795 newSet.RemoveAt(0); 1910 newSet.RemoveAt(0);
1796 1911
1797 foreach (SceneObjectPart newChild in newSet) 1912 foreach (SceneObjectPart newChild in newSet)
1798 newChild.ClearUpdateSchedule(); 1913 newChild.ClearUpdateSchedule();
1799 1914
1800 LinkObjects(newRoot, newSet); 1915 newRoot.ParentGroup.areUpdatesSuspended = true;
1801 if (!affectedGroups.Contains(newRoot.ParentGroup)) 1916 LinkObjects(newRoot, newSet);
1802 affectedGroups.Add(newRoot.ParentGroup); 1917 if (!affectedGroups.Contains(newRoot.ParentGroup))
1803 } 1918 affectedGroups.Add(newRoot.ParentGroup);
1804 } 1919 }
1805 } 1920 }
1806 1921
@@ -1808,8 +1923,14 @@ namespace OpenSim.Region.Framework.Scenes
1808 // 1923 //
1809 foreach (SceneObjectGroup g in affectedGroups) 1924 foreach (SceneObjectGroup g in affectedGroups)
1810 { 1925 {
1926 // Child prims that have been unlinked and deleted will
1927 // return unless the root is deleted. This will remove them
1928 // from the database. They will be rewritten immediately,
1929 // minus the rows for the unlinked child prims.
1930 m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID);
1811 g.TriggerScriptChangedEvent(Changed.LINK); 1931 g.TriggerScriptChangedEvent(Changed.LINK);
1812 g.HasGroupChanged = true; // Persist 1932 g.HasGroupChanged = true; // Persist
1933 g.areUpdatesSuspended = false;
1813 g.ScheduleGroupForFullUpdate(); 1934 g.ScheduleGroupForFullUpdate();
1814 } 1935 }
1815 } 1936 }
@@ -1927,9 +2048,6 @@ namespace OpenSim.Region.Framework.Scenes
1927 child.ApplyNextOwnerPermissions(); 2048 child.ApplyNextOwnerPermissions();
1928 } 2049 }
1929 } 2050 }
1930
1931 copy.RootPart.ObjectSaleType = 0;
1932 copy.RootPart.SalePrice = 10;
1933 } 2051 }
1934 2052
1935 // FIXME: This section needs to be refactored so that it just calls AddSceneObject() 2053 // FIXME: This section needs to be refactored so that it just calls AddSceneObject()