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 7d801b5..17563bd 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
@@ -1665,9 +1754,13 @@ namespace OpenSim.Region.Framework.Scenes
1665 // Make sure no child prim is set for sale 1754 // Make sure no child prim is set for sale
1666 // So that, on delink, no prims are unwittingly 1755 // So that, on delink, no prims are unwittingly
1667 // left for sale and sold off 1756 // left for sale and sold off
1668 child.RootPart.ObjectSaleType = 0; 1757
1669 child.RootPart.SalePrice = 10; 1758 if (child != null)
1670 childGroups.Add(child); 1759 {
1760 child.RootPart.ObjectSaleType = 0;
1761 child.RootPart.SalePrice = 10;
1762 childGroups.Add(child);
1763 }
1671 } 1764 }
1672 1765
1673 foreach (SceneObjectGroup child in childGroups) 1766 foreach (SceneObjectGroup child in childGroups)
@@ -1686,12 +1779,19 @@ namespace OpenSim.Region.Framework.Scenes
1686 // occur on link to invoke this elsewhere (such as object selection) 1779 // occur on link to invoke this elsewhere (such as object selection)
1687 parentGroup.RootPart.CreateSelected = true; 1780 parentGroup.RootPart.CreateSelected = true;
1688 parentGroup.TriggerScriptChangedEvent(Changed.LINK); 1781 parentGroup.TriggerScriptChangedEvent(Changed.LINK);
1689 parentGroup.HasGroupChanged = true;
1690 parentGroup.ScheduleGroupForFullUpdate();
1691
1692 } 1782 }
1693 finally 1783 finally
1694 { 1784 {
1785 lock (SceneObjectGroupsByLocalPartID)
1786 {
1787 foreach (SceneObjectPart part in parentGroup.Parts)
1788 SceneObjectGroupsByLocalPartID[part.LocalId] = parentGroup;
1789 }
1790
1791 parentGroup.areUpdatesSuspended = false;
1792 parentGroup.HasGroupChanged = true;
1793 parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true);
1794 parentGroup.ScheduleGroupForFullUpdate();
1695 Monitor.Exit(m_updateLock); 1795 Monitor.Exit(m_updateLock);
1696 } 1796 }
1697 } 1797 }
@@ -1728,21 +1828,24 @@ namespace OpenSim.Region.Framework.Scenes
1728 1828
1729 SceneObjectGroup group = part.ParentGroup; 1829 SceneObjectGroup group = part.ParentGroup;
1730 if (!affectedGroups.Contains(group)) 1830 if (!affectedGroups.Contains(group))
1831 {
1832 group.areUpdatesSuspended = true;
1731 affectedGroups.Add(group); 1833 affectedGroups.Add(group);
1834 }
1732 } 1835 }
1733 } 1836 }
1734 } 1837 }
1735 1838
1736 foreach (SceneObjectPart child in childParts) 1839 if (childParts.Count > 0)
1737 { 1840 {
1738 // Unlink all child parts from their groups 1841 foreach (SceneObjectPart child in childParts)
1739 // 1842 {
1740 child.ParentGroup.DelinkFromGroup(child, true); 1843 // Unlink all child parts from their groups
1741 1844 //
1742 // These are not in affected groups and will not be 1845 child.ParentGroup.DelinkFromGroup(child, true);
1743 // handled further. Do the honors here. 1846 child.ParentGroup.HasGroupChanged = true;
1744 child.ParentGroup.HasGroupChanged = true; 1847 child.ParentGroup.ScheduleGroupForFullUpdate();
1745 child.ParentGroup.ScheduleGroupForFullUpdate(); 1848 }
1746 } 1849 }
1747 1850
1748 foreach (SceneObjectPart root in rootParts) 1851 foreach (SceneObjectPart root in rootParts)
@@ -1752,56 +1855,68 @@ namespace OpenSim.Region.Framework.Scenes
1752 // However, editing linked parts and unlinking may be different 1855 // However, editing linked parts and unlinking may be different
1753 // 1856 //
1754 SceneObjectGroup group = root.ParentGroup; 1857 SceneObjectGroup group = root.ParentGroup;
1858 group.areUpdatesSuspended = true;
1755 1859
1756 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); 1860 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts);
1757 int numChildren = newSet.Count; 1861 int numChildren = newSet.Count;
1758 1862
1863 if (numChildren == 1)
1864 break;
1865
1759 // If there are prims left in a link set, but the root is 1866 // If there are prims left in a link set, but the root is
1760 // slated for unlink, we need to do this 1867 // slated for unlink, we need to do this
1868 // Unlink the remaining set
1761 // 1869 //
1762 if (numChildren != 1) 1870 bool sendEventsToRemainder = true;
1763 { 1871 if (numChildren > 1)
1764 // Unlink the remaining set 1872 sendEventsToRemainder = false;
1765 //
1766 bool sendEventsToRemainder = true;
1767 if (numChildren > 1)
1768 sendEventsToRemainder = false;
1769 1873
1770 foreach (SceneObjectPart p in newSet) 1874 foreach (SceneObjectPart p in newSet)
1875 {
1876 if (p != group.RootPart)
1771 { 1877 {
1772 if (p != group.RootPart) 1878 group.DelinkFromGroup(p, sendEventsToRemainder);
1773 group.DelinkFromGroup(p, sendEventsToRemainder); 1879 if (numChildren > 2)
1880 {
1881 p.ParentGroup.areUpdatesSuspended = true;
1882 }
1883 else
1884 {
1885 p.ParentGroup.HasGroupChanged = true;
1886 p.ParentGroup.ScheduleGroupForFullUpdate();
1887 }
1774 } 1888 }
1889 }
1890
1891 // If there is more than one prim remaining, we
1892 // need to re-link
1893 //
1894 if (numChildren > 2)
1895 {
1896 // Remove old root
1897 //
1898 if (newSet.Contains(root))
1899 newSet.Remove(root);
1775 1900
1776 // If there is more than one prim remaining, we 1901 // Preserve link ordering
1777 // need to re-link
1778 // 1902 //
1779 if (numChildren > 2) 1903 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1780 { 1904 {
1781 // Remove old root 1905 return a.LinkNum.CompareTo(b.LinkNum);
1782 // 1906 });
1783 if (newSet.Contains(root))
1784 newSet.Remove(root);
1785
1786 // Preserve link ordering
1787 //
1788 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1789 {
1790 return a.LinkNum.CompareTo(b.LinkNum);
1791 });
1792 1907
1793 // Determine new root 1908 // Determine new root
1794 // 1909 //
1795 SceneObjectPart newRoot = newSet[0]; 1910 SceneObjectPart newRoot = newSet[0];
1796 newSet.RemoveAt(0); 1911 newSet.RemoveAt(0);
1797 1912
1798 foreach (SceneObjectPart newChild in newSet) 1913 foreach (SceneObjectPart newChild in newSet)
1799 newChild.ClearUpdateSchedule(); 1914 newChild.ClearUpdateSchedule();
1800 1915
1801 LinkObjects(newRoot, newSet); 1916 newRoot.ParentGroup.areUpdatesSuspended = true;
1802 if (!affectedGroups.Contains(newRoot.ParentGroup)) 1917 LinkObjects(newRoot, newSet);
1803 affectedGroups.Add(newRoot.ParentGroup); 1918 if (!affectedGroups.Contains(newRoot.ParentGroup))
1804 } 1919 affectedGroups.Add(newRoot.ParentGroup);
1805 } 1920 }
1806 } 1921 }
1807 1922
@@ -1809,8 +1924,14 @@ namespace OpenSim.Region.Framework.Scenes
1809 // 1924 //
1810 foreach (SceneObjectGroup g in affectedGroups) 1925 foreach (SceneObjectGroup g in affectedGroups)
1811 { 1926 {
1927 // Child prims that have been unlinked and deleted will
1928 // return unless the root is deleted. This will remove them
1929 // from the database. They will be rewritten immediately,
1930 // minus the rows for the unlinked child prims.
1931 m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID);
1812 g.TriggerScriptChangedEvent(Changed.LINK); 1932 g.TriggerScriptChangedEvent(Changed.LINK);
1813 g.HasGroupChanged = true; // Persist 1933 g.HasGroupChanged = true; // Persist
1934 g.areUpdatesSuspended = false;
1814 g.ScheduleGroupForFullUpdate(); 1935 g.ScheduleGroupForFullUpdate();
1815 } 1936 }
1816 } 1937 }
@@ -1912,9 +2033,6 @@ namespace OpenSim.Region.Framework.Scenes
1912 child.ApplyNextOwnerPermissions(); 2033 child.ApplyNextOwnerPermissions();
1913 } 2034 }
1914 } 2035 }
1915
1916 copy.RootPart.ObjectSaleType = 0;
1917 copy.RootPart.SalePrice = 10;
1918 } 2036 }
1919 2037
1920 // FIXME: This section needs to be refactored so that it just calls AddSceneObject() 2038 // FIXME: This section needs to be refactored so that it just calls AddSceneObject()