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.cs227
1 files changed, 174 insertions, 53 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index 693a79e..6dd42dd 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();
@@ -354,6 +396,11 @@ namespace OpenSim.Region.Framework.Scenes
354 /// </returns> 396 /// </returns>
355 protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) 397 protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates)
356 { 398 {
399 if (sceneObject == null)
400 {
401 m_log.ErrorFormat("[SCENEGRAPH]: Tried to add null scene object");
402 return false;
403 }
357 if (sceneObject.UUID == UUID.Zero) 404 if (sceneObject.UUID == UUID.Zero)
358 { 405 {
359 m_log.ErrorFormat( 406 m_log.ErrorFormat(
@@ -488,6 +535,30 @@ namespace OpenSim.Region.Framework.Scenes
488 m_updateList[obj.UUID] = obj; 535 m_updateList[obj.UUID] = obj;
489 } 536 }
490 537
538 public void FireAttachToBackup(SceneObjectGroup obj)
539 {
540 if (OnAttachToBackup != null)
541 {
542 OnAttachToBackup(obj);
543 }
544 }
545
546 public void FireDetachFromBackup(SceneObjectGroup obj)
547 {
548 if (OnDetachFromBackup != null)
549 {
550 OnDetachFromBackup(obj);
551 }
552 }
553
554 public void FireChangeBackup(SceneObjectGroup obj)
555 {
556 if (OnChangeBackup != null)
557 {
558 OnChangeBackup(obj);
559 }
560 }
561
491 /// <summary> 562 /// <summary>
492 /// Process all pending updates 563 /// Process all pending updates
493 /// </summary> 564 /// </summary>
@@ -605,7 +676,8 @@ namespace OpenSim.Region.Framework.Scenes
605 676
606 Entities[presence.UUID] = presence; 677 Entities[presence.UUID] = presence;
607 678
608 lock (m_presenceLock) 679 m_scenePresencesLock.EnterWriteLock();
680 try
609 { 681 {
610 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 682 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
611 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 683 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -629,6 +701,10 @@ namespace OpenSim.Region.Framework.Scenes
629 m_scenePresenceMap = newmap; 701 m_scenePresenceMap = newmap;
630 m_scenePresenceArray = newlist; 702 m_scenePresenceArray = newlist;
631 } 703 }
704 finally
705 {
706 m_scenePresencesLock.ExitWriteLock();
707 }
632 } 708 }
633 709
634 /// <summary> 710 /// <summary>
@@ -643,7 +719,8 @@ namespace OpenSim.Region.Framework.Scenes
643 agentID); 719 agentID);
644 } 720 }
645 721
646 lock (m_presenceLock) 722 m_scenePresencesLock.EnterWriteLock();
723 try
647 { 724 {
648 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 725 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
649 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 726 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -665,6 +742,10 @@ namespace OpenSim.Region.Framework.Scenes
665 m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); 742 m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID);
666 } 743 }
667 } 744 }
745 finally
746 {
747 m_scenePresencesLock.ExitWriteLock();
748 }
668 } 749 }
669 750
670 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) 751 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F)
@@ -1380,8 +1461,13 @@ namespace OpenSim.Region.Framework.Scenes
1380 { 1461 {
1381 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) 1462 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0))
1382 { 1463 {
1383 if (m_parentScene.AttachmentsModule != null) 1464 // Set the new attachment point data in the object
1384 m_parentScene.AttachmentsModule.UpdateAttachmentPosition(group, pos); 1465 byte attachmentPoint = group.GetAttachmentPoint();
1466 group.UpdateGroupPosition(pos);
1467 group.IsAttachment = false;
1468 group.AbsolutePosition = group.RootPart.AttachedPos;
1469 group.AttachmentPoint = attachmentPoint;
1470 group.HasGroupChanged = true;
1385 } 1471 }
1386 else 1472 else
1387 { 1473 {
@@ -1653,8 +1739,11 @@ namespace OpenSim.Region.Framework.Scenes
1653 return; 1739 return;
1654 1740
1655 Monitor.Enter(m_updateLock); 1741 Monitor.Enter(m_updateLock);
1742
1656 try 1743 try
1657 { 1744 {
1745 parentGroup.areUpdatesSuspended = true;
1746
1658 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); 1747 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>();
1659 1748
1660 // We do this in reverse to get the link order of the prims correct 1749 // We do this in reverse to get the link order of the prims correct
@@ -1669,9 +1758,13 @@ namespace OpenSim.Region.Framework.Scenes
1669 // Make sure no child prim is set for sale 1758 // Make sure no child prim is set for sale
1670 // So that, on delink, no prims are unwittingly 1759 // So that, on delink, no prims are unwittingly
1671 // left for sale and sold off 1760 // left for sale and sold off
1672 child.RootPart.ObjectSaleType = 0; 1761
1673 child.RootPart.SalePrice = 10; 1762 if (child != null)
1674 childGroups.Add(child); 1763 {
1764 child.RootPart.ObjectSaleType = 0;
1765 child.RootPart.SalePrice = 10;
1766 childGroups.Add(child);
1767 }
1675 } 1768 }
1676 1769
1677 foreach (SceneObjectGroup child in childGroups) 1770 foreach (SceneObjectGroup child in childGroups)
@@ -1698,6 +1791,16 @@ namespace OpenSim.Region.Framework.Scenes
1698 } 1791 }
1699 finally 1792 finally
1700 { 1793 {
1794 lock (SceneObjectGroupsByLocalPartID)
1795 {
1796 foreach (SceneObjectPart part in parentGroup.Parts)
1797 SceneObjectGroupsByLocalPartID[part.LocalId] = parentGroup;
1798 }
1799
1800 parentGroup.areUpdatesSuspended = false;
1801 parentGroup.HasGroupChanged = true;
1802 parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true);
1803 parentGroup.ScheduleGroupForFullUpdate();
1701 Monitor.Exit(m_updateLock); 1804 Monitor.Exit(m_updateLock);
1702 } 1805 }
1703 } 1806 }
@@ -1734,21 +1837,24 @@ namespace OpenSim.Region.Framework.Scenes
1734 1837
1735 SceneObjectGroup group = part.ParentGroup; 1838 SceneObjectGroup group = part.ParentGroup;
1736 if (!affectedGroups.Contains(group)) 1839 if (!affectedGroups.Contains(group))
1840 {
1841 group.areUpdatesSuspended = true;
1737 affectedGroups.Add(group); 1842 affectedGroups.Add(group);
1843 }
1738 } 1844 }
1739 } 1845 }
1740 } 1846 }
1741 1847
1742 foreach (SceneObjectPart child in childParts) 1848 if (childParts.Count > 0)
1743 { 1849 {
1744 // Unlink all child parts from their groups 1850 foreach (SceneObjectPart child in childParts)
1745 // 1851 {
1746 child.ParentGroup.DelinkFromGroup(child, true); 1852 // Unlink all child parts from their groups
1747 1853 //
1748 // These are not in affected groups and will not be 1854 child.ParentGroup.DelinkFromGroup(child, true);
1749 // handled further. Do the honors here. 1855 child.ParentGroup.HasGroupChanged = true;
1750 child.ParentGroup.HasGroupChanged = true; 1856 child.ParentGroup.ScheduleGroupForFullUpdate();
1751 child.ParentGroup.ScheduleGroupForFullUpdate(); 1857 }
1752 } 1858 }
1753 1859
1754 foreach (SceneObjectPart root in rootParts) 1860 foreach (SceneObjectPart root in rootParts)
@@ -1758,56 +1864,68 @@ namespace OpenSim.Region.Framework.Scenes
1758 // However, editing linked parts and unlinking may be different 1864 // However, editing linked parts and unlinking may be different
1759 // 1865 //
1760 SceneObjectGroup group = root.ParentGroup; 1866 SceneObjectGroup group = root.ParentGroup;
1867 group.areUpdatesSuspended = true;
1761 1868
1762 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); 1869 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts);
1763 int numChildren = newSet.Count; 1870 int numChildren = newSet.Count;
1764 1871
1872 if (numChildren == 1)
1873 break;
1874
1765 // If there are prims left in a link set, but the root is 1875 // If there are prims left in a link set, but the root is
1766 // slated for unlink, we need to do this 1876 // slated for unlink, we need to do this
1877 // Unlink the remaining set
1767 // 1878 //
1768 if (numChildren != 1) 1879 bool sendEventsToRemainder = true;
1769 { 1880 if (numChildren > 1)
1770 // Unlink the remaining set 1881 sendEventsToRemainder = false;
1771 //
1772 bool sendEventsToRemainder = true;
1773 if (numChildren > 1)
1774 sendEventsToRemainder = false;
1775 1882
1776 foreach (SceneObjectPart p in newSet) 1883 foreach (SceneObjectPart p in newSet)
1884 {
1885 if (p != group.RootPart)
1777 { 1886 {
1778 if (p != group.RootPart) 1887 group.DelinkFromGroup(p, sendEventsToRemainder);
1779 group.DelinkFromGroup(p, sendEventsToRemainder); 1888 if (numChildren > 2)
1889 {
1890 p.ParentGroup.areUpdatesSuspended = true;
1891 }
1892 else
1893 {
1894 p.ParentGroup.HasGroupChanged = true;
1895 p.ParentGroup.ScheduleGroupForFullUpdate();
1896 }
1780 } 1897 }
1898 }
1899
1900 // If there is more than one prim remaining, we
1901 // need to re-link
1902 //
1903 if (numChildren > 2)
1904 {
1905 // Remove old root
1906 //
1907 if (newSet.Contains(root))
1908 newSet.Remove(root);
1781 1909
1782 // If there is more than one prim remaining, we 1910 // Preserve link ordering
1783 // need to re-link
1784 // 1911 //
1785 if (numChildren > 2) 1912 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1786 { 1913 {
1787 // Remove old root 1914 return a.LinkNum.CompareTo(b.LinkNum);
1788 // 1915 });
1789 if (newSet.Contains(root))
1790 newSet.Remove(root);
1791
1792 // Preserve link ordering
1793 //
1794 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1795 {
1796 return a.LinkNum.CompareTo(b.LinkNum);
1797 });
1798 1916
1799 // Determine new root 1917 // Determine new root
1800 // 1918 //
1801 SceneObjectPart newRoot = newSet[0]; 1919 SceneObjectPart newRoot = newSet[0];
1802 newSet.RemoveAt(0); 1920 newSet.RemoveAt(0);
1803 1921
1804 foreach (SceneObjectPart newChild in newSet) 1922 foreach (SceneObjectPart newChild in newSet)
1805 newChild.ClearUpdateSchedule(); 1923 newChild.ClearUpdateSchedule();
1806 1924
1807 LinkObjects(newRoot, newSet); 1925 newRoot.ParentGroup.areUpdatesSuspended = true;
1808 if (!affectedGroups.Contains(newRoot.ParentGroup)) 1926 LinkObjects(newRoot, newSet);
1809 affectedGroups.Add(newRoot.ParentGroup); 1927 if (!affectedGroups.Contains(newRoot.ParentGroup))
1810 } 1928 affectedGroups.Add(newRoot.ParentGroup);
1811 } 1929 }
1812 } 1930 }
1813 1931
@@ -1815,8 +1933,14 @@ namespace OpenSim.Region.Framework.Scenes
1815 // 1933 //
1816 foreach (SceneObjectGroup g in affectedGroups) 1934 foreach (SceneObjectGroup g in affectedGroups)
1817 { 1935 {
1936 // Child prims that have been unlinked and deleted will
1937 // return unless the root is deleted. This will remove them
1938 // from the database. They will be rewritten immediately,
1939 // minus the rows for the unlinked child prims.
1940 m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID);
1818 g.TriggerScriptChangedEvent(Changed.LINK); 1941 g.TriggerScriptChangedEvent(Changed.LINK);
1819 g.HasGroupChanged = true; // Persist 1942 g.HasGroupChanged = true; // Persist
1943 g.areUpdatesSuspended = false;
1820 g.ScheduleGroupForFullUpdate(); 1944 g.ScheduleGroupForFullUpdate();
1821 } 1945 }
1822 } 1946 }
@@ -1918,9 +2042,6 @@ namespace OpenSim.Region.Framework.Scenes
1918 child.ApplyNextOwnerPermissions(); 2042 child.ApplyNextOwnerPermissions();
1919 } 2043 }
1920 } 2044 }
1921
1922 copy.RootPart.ObjectSaleType = 0;
1923 copy.RootPart.SalePrice = 10;
1924 } 2045 }
1925 2046
1926 // FIXME: This section needs to be refactored so that it just calls AddSceneObject() 2047 // FIXME: This section needs to be refactored so that it just calls AddSceneObject()