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.cs238
1 files changed, 185 insertions, 53 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index 66fb493..a3206015 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 {
@@ -1645,6 +1731,12 @@ namespace OpenSim.Region.Framework.Scenes
1645 /// <param name="childPrims"></param> 1731 /// <param name="childPrims"></param>
1646 protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children) 1732 protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children)
1647 { 1733 {
1734 if (root.KeyframeMotion != null)
1735 {
1736 root.KeyframeMotion.Stop();
1737 root.KeyframeMotion = null;
1738 }
1739
1648 SceneObjectGroup parentGroup = root.ParentGroup; 1740 SceneObjectGroup parentGroup = root.ParentGroup;
1649 if (parentGroup == null) return; 1741 if (parentGroup == null) return;
1650 1742
@@ -1653,8 +1745,11 @@ namespace OpenSim.Region.Framework.Scenes
1653 return; 1745 return;
1654 1746
1655 Monitor.Enter(m_updateLock); 1747 Monitor.Enter(m_updateLock);
1748
1656 try 1749 try
1657 { 1750 {
1751 parentGroup.areUpdatesSuspended = true;
1752
1658 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); 1753 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>();
1659 1754
1660 // We do this in reverse to get the link order of the prims correct 1755 // We do this in reverse to get the link order of the prims correct
@@ -1669,9 +1764,13 @@ namespace OpenSim.Region.Framework.Scenes
1669 // Make sure no child prim is set for sale 1764 // Make sure no child prim is set for sale
1670 // So that, on delink, no prims are unwittingly 1765 // So that, on delink, no prims are unwittingly
1671 // left for sale and sold off 1766 // left for sale and sold off
1672 child.RootPart.ObjectSaleType = 0; 1767
1673 child.RootPart.SalePrice = 10; 1768 if (child != null)
1674 childGroups.Add(child); 1769 {
1770 child.RootPart.ObjectSaleType = 0;
1771 child.RootPart.SalePrice = 10;
1772 childGroups.Add(child);
1773 }
1675 } 1774 }
1676 1775
1677 foreach (SceneObjectGroup child in childGroups) 1776 foreach (SceneObjectGroup child in childGroups)
@@ -1698,6 +1797,16 @@ namespace OpenSim.Region.Framework.Scenes
1698 } 1797 }
1699 finally 1798 finally
1700 { 1799 {
1800 lock (SceneObjectGroupsByLocalPartID)
1801 {
1802 foreach (SceneObjectPart part in parentGroup.Parts)
1803 SceneObjectGroupsByLocalPartID[part.LocalId] = parentGroup;
1804 }
1805
1806 parentGroup.areUpdatesSuspended = false;
1807 parentGroup.HasGroupChanged = true;
1808 parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true);
1809 parentGroup.ScheduleGroupForFullUpdate();
1701 Monitor.Exit(m_updateLock); 1810 Monitor.Exit(m_updateLock);
1702 } 1811 }
1703 } 1812 }
@@ -1720,6 +1829,11 @@ namespace OpenSim.Region.Framework.Scenes
1720 { 1829 {
1721 if (part != null) 1830 if (part != null)
1722 { 1831 {
1832 if (part.KeyframeMotion != null)
1833 {
1834 part.KeyframeMotion.Stop();
1835 part.KeyframeMotion = null;
1836 }
1723 if (part.ParentGroup.PrimCount != 1) // Skip single 1837 if (part.ParentGroup.PrimCount != 1) // Skip single
1724 { 1838 {
1725 if (part.LinkNum < 2) // Root 1839 if (part.LinkNum < 2) // Root
@@ -1734,21 +1848,24 @@ namespace OpenSim.Region.Framework.Scenes
1734 1848
1735 SceneObjectGroup group = part.ParentGroup; 1849 SceneObjectGroup group = part.ParentGroup;
1736 if (!affectedGroups.Contains(group)) 1850 if (!affectedGroups.Contains(group))
1851 {
1852 group.areUpdatesSuspended = true;
1737 affectedGroups.Add(group); 1853 affectedGroups.Add(group);
1854 }
1738 } 1855 }
1739 } 1856 }
1740 } 1857 }
1741 1858
1742 foreach (SceneObjectPart child in childParts) 1859 if (childParts.Count > 0)
1743 { 1860 {
1744 // Unlink all child parts from their groups 1861 foreach (SceneObjectPart child in childParts)
1745 // 1862 {
1746 child.ParentGroup.DelinkFromGroup(child, true); 1863 // Unlink all child parts from their groups
1747 1864 //
1748 // These are not in affected groups and will not be 1865 child.ParentGroup.DelinkFromGroup(child, true);
1749 // handled further. Do the honors here. 1866 child.ParentGroup.HasGroupChanged = true;
1750 child.ParentGroup.HasGroupChanged = true; 1867 child.ParentGroup.ScheduleGroupForFullUpdate();
1751 child.ParentGroup.ScheduleGroupForFullUpdate(); 1868 }
1752 } 1869 }
1753 1870
1754 foreach (SceneObjectPart root in rootParts) 1871 foreach (SceneObjectPart root in rootParts)
@@ -1758,56 +1875,68 @@ namespace OpenSim.Region.Framework.Scenes
1758 // However, editing linked parts and unlinking may be different 1875 // However, editing linked parts and unlinking may be different
1759 // 1876 //
1760 SceneObjectGroup group = root.ParentGroup; 1877 SceneObjectGroup group = root.ParentGroup;
1878 group.areUpdatesSuspended = true;
1761 1879
1762 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); 1880 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts);
1763 int numChildren = newSet.Count; 1881 int numChildren = newSet.Count;
1764 1882
1883 if (numChildren == 1)
1884 break;
1885
1765 // If there are prims left in a link set, but the root is 1886 // If there are prims left in a link set, but the root is
1766 // slated for unlink, we need to do this 1887 // slated for unlink, we need to do this
1888 // Unlink the remaining set
1767 // 1889 //
1768 if (numChildren != 1) 1890 bool sendEventsToRemainder = true;
1769 { 1891 if (numChildren > 1)
1770 // Unlink the remaining set 1892 sendEventsToRemainder = false;
1771 //
1772 bool sendEventsToRemainder = true;
1773 if (numChildren > 1)
1774 sendEventsToRemainder = false;
1775 1893
1776 foreach (SceneObjectPart p in newSet) 1894 foreach (SceneObjectPart p in newSet)
1895 {
1896 if (p != group.RootPart)
1777 { 1897 {
1778 if (p != group.RootPart) 1898 group.DelinkFromGroup(p, sendEventsToRemainder);
1779 group.DelinkFromGroup(p, sendEventsToRemainder); 1899 if (numChildren > 2)
1900 {
1901 p.ParentGroup.areUpdatesSuspended = true;
1902 }
1903 else
1904 {
1905 p.ParentGroup.HasGroupChanged = true;
1906 p.ParentGroup.ScheduleGroupForFullUpdate();
1907 }
1780 } 1908 }
1909 }
1910
1911 // If there is more than one prim remaining, we
1912 // need to re-link
1913 //
1914 if (numChildren > 2)
1915 {
1916 // Remove old root
1917 //
1918 if (newSet.Contains(root))
1919 newSet.Remove(root);
1781 1920
1782 // If there is more than one prim remaining, we 1921 // Preserve link ordering
1783 // need to re-link
1784 // 1922 //
1785 if (numChildren > 2) 1923 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1786 { 1924 {
1787 // Remove old root 1925 return a.LinkNum.CompareTo(b.LinkNum);
1788 // 1926 });
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 1927
1799 // Determine new root 1928 // Determine new root
1800 // 1929 //
1801 SceneObjectPart newRoot = newSet[0]; 1930 SceneObjectPart newRoot = newSet[0];
1802 newSet.RemoveAt(0); 1931 newSet.RemoveAt(0);
1803 1932
1804 foreach (SceneObjectPart newChild in newSet) 1933 foreach (SceneObjectPart newChild in newSet)
1805 newChild.ClearUpdateSchedule(); 1934 newChild.ClearUpdateSchedule();
1806 1935
1807 LinkObjects(newRoot, newSet); 1936 newRoot.ParentGroup.areUpdatesSuspended = true;
1808 if (!affectedGroups.Contains(newRoot.ParentGroup)) 1937 LinkObjects(newRoot, newSet);
1809 affectedGroups.Add(newRoot.ParentGroup); 1938 if (!affectedGroups.Contains(newRoot.ParentGroup))
1810 } 1939 affectedGroups.Add(newRoot.ParentGroup);
1811 } 1940 }
1812 } 1941 }
1813 1942
@@ -1815,8 +1944,14 @@ namespace OpenSim.Region.Framework.Scenes
1815 // 1944 //
1816 foreach (SceneObjectGroup g in affectedGroups) 1945 foreach (SceneObjectGroup g in affectedGroups)
1817 { 1946 {
1947 // Child prims that have been unlinked and deleted will
1948 // return unless the root is deleted. This will remove them
1949 // from the database. They will be rewritten immediately,
1950 // minus the rows for the unlinked child prims.
1951 m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID);
1818 g.TriggerScriptChangedEvent(Changed.LINK); 1952 g.TriggerScriptChangedEvent(Changed.LINK);
1819 g.HasGroupChanged = true; // Persist 1953 g.HasGroupChanged = true; // Persist
1954 g.areUpdatesSuspended = false;
1820 g.ScheduleGroupForFullUpdate(); 1955 g.ScheduleGroupForFullUpdate();
1821 } 1956 }
1822 } 1957 }
@@ -1918,9 +2053,6 @@ namespace OpenSim.Region.Framework.Scenes
1918 child.ApplyNextOwnerPermissions(); 2053 child.ApplyNextOwnerPermissions();
1919 } 2054 }
1920 } 2055 }
1921
1922 copy.RootPart.ObjectSaleType = 0;
1923 copy.RootPart.SalePrice = 10;
1924 } 2056 }
1925 2057
1926 // FIXME: This section needs to be refactored so that it just calls AddSceneObject() 2058 // FIXME: This section needs to be refactored so that it just calls AddSceneObject()