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 bc3400a..3cd4a10 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();
@@ -247,6 +262,33 @@ namespace OpenSim.Region.Framework.Scenes
247 protected internal bool AddRestoredSceneObject( 262 protected internal bool AddRestoredSceneObject(
248 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 263 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
249 { 264 {
265 if (!m_parentScene.CombineRegions)
266 {
267 // KF: Check for out-of-region, move inside and make static.
268 Vector3 npos = new Vector3(sceneObject.RootPart.GroupPosition.X,
269 sceneObject.RootPart.GroupPosition.Y,
270 sceneObject.RootPart.GroupPosition.Z);
271 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 ||
272 npos.X > Constants.RegionSize ||
273 npos.Y > Constants.RegionSize))
274 {
275 if (npos.X < 0.0) npos.X = 1.0f;
276 if (npos.Y < 0.0) npos.Y = 1.0f;
277 if (npos.Z < 0.0) npos.Z = 0.0f;
278 if (npos.X > Constants.RegionSize) npos.X = Constants.RegionSize - 1.0f;
279 if (npos.Y > Constants.RegionSize) npos.Y = Constants.RegionSize - 1.0f;
280
281 foreach (SceneObjectPart part in sceneObject.Parts)
282 {
283 part.GroupPosition = npos;
284 }
285 sceneObject.RootPart.Velocity = Vector3.Zero;
286 sceneObject.RootPart.AngularVelocity = Vector3.Zero;
287 sceneObject.RootPart.Acceleration = Vector3.Zero;
288 sceneObject.RootPart.Velocity = Vector3.Zero;
289 }
290 }
291
250 if (attachToBackup && (!alreadyPersisted)) 292 if (attachToBackup && (!alreadyPersisted))
251 { 293 {
252 sceneObject.ForceInventoryPersistence(); 294 sceneObject.ForceInventoryPersistence();
@@ -336,6 +378,11 @@ namespace OpenSim.Region.Framework.Scenes
336 /// </returns> 378 /// </returns>
337 protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) 379 protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates)
338 { 380 {
381 if (sceneObject == null)
382 {
383 m_log.ErrorFormat("[SCENEGRAPH]: Tried to add null scene object");
384 return false;
385 }
339 if (sceneObject.UUID == UUID.Zero) 386 if (sceneObject.UUID == UUID.Zero)
340 { 387 {
341 m_log.ErrorFormat( 388 m_log.ErrorFormat(
@@ -470,6 +517,30 @@ namespace OpenSim.Region.Framework.Scenes
470 m_updateList[obj.UUID] = obj; 517 m_updateList[obj.UUID] = obj;
471 } 518 }
472 519
520 public void FireAttachToBackup(SceneObjectGroup obj)
521 {
522 if (OnAttachToBackup != null)
523 {
524 OnAttachToBackup(obj);
525 }
526 }
527
528 public void FireDetachFromBackup(SceneObjectGroup obj)
529 {
530 if (OnDetachFromBackup != null)
531 {
532 OnDetachFromBackup(obj);
533 }
534 }
535
536 public void FireChangeBackup(SceneObjectGroup obj)
537 {
538 if (OnChangeBackup != null)
539 {
540 OnChangeBackup(obj);
541 }
542 }
543
473 /// <summary> 544 /// <summary>
474 /// Process all pending updates 545 /// Process all pending updates
475 /// </summary> 546 /// </summary>
@@ -587,7 +658,8 @@ namespace OpenSim.Region.Framework.Scenes
587 658
588 Entities[presence.UUID] = presence; 659 Entities[presence.UUID] = presence;
589 660
590 lock (m_presenceLock) 661 m_scenePresencesLock.EnterWriteLock();
662 try
591 { 663 {
592 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 664 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
593 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 665 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -611,6 +683,10 @@ namespace OpenSim.Region.Framework.Scenes
611 m_scenePresenceMap = newmap; 683 m_scenePresenceMap = newmap;
612 m_scenePresenceArray = newlist; 684 m_scenePresenceArray = newlist;
613 } 685 }
686 finally
687 {
688 m_scenePresencesLock.ExitWriteLock();
689 }
614 } 690 }
615 691
616 /// <summary> 692 /// <summary>
@@ -625,7 +701,8 @@ namespace OpenSim.Region.Framework.Scenes
625 agentID); 701 agentID);
626 } 702 }
627 703
628 lock (m_presenceLock) 704 m_scenePresencesLock.EnterWriteLock();
705 try
629 { 706 {
630 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 707 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
631 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 708 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -647,6 +724,10 @@ namespace OpenSim.Region.Framework.Scenes
647 m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); 724 m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID);
648 } 725 }
649 } 726 }
727 finally
728 {
729 m_scenePresencesLock.ExitWriteLock();
730 }
650 } 731 }
651 732
652 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) 733 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F)
@@ -1362,8 +1443,13 @@ namespace OpenSim.Region.Framework.Scenes
1362 { 1443 {
1363 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) 1444 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0))
1364 { 1445 {
1365 if (m_parentScene.AttachmentsModule != null) 1446 // Set the new attachment point data in the object
1366 m_parentScene.AttachmentsModule.UpdateAttachmentPosition(group, pos); 1447 byte attachmentPoint = group.GetAttachmentPoint();
1448 group.UpdateGroupPosition(pos);
1449 group.IsAttachment = false;
1450 group.AbsolutePosition = group.RootPart.AttachedPos;
1451 group.AttachmentPoint = attachmentPoint;
1452 group.HasGroupChanged = true;
1367 } 1453 }
1368 else 1454 else
1369 { 1455 {
@@ -1627,6 +1713,12 @@ namespace OpenSim.Region.Framework.Scenes
1627 /// <param name="childPrims"></param> 1713 /// <param name="childPrims"></param>
1628 protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children) 1714 protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children)
1629 { 1715 {
1716 if (root.KeyframeMotion != null)
1717 {
1718 root.KeyframeMotion.Stop();
1719 root.KeyframeMotion = null;
1720 }
1721
1630 SceneObjectGroup parentGroup = root.ParentGroup; 1722 SceneObjectGroup parentGroup = root.ParentGroup;
1631 if (parentGroup == null) return; 1723 if (parentGroup == null) return;
1632 1724
@@ -1635,8 +1727,11 @@ namespace OpenSim.Region.Framework.Scenes
1635 return; 1727 return;
1636 1728
1637 Monitor.Enter(m_updateLock); 1729 Monitor.Enter(m_updateLock);
1730
1638 try 1731 try
1639 { 1732 {
1733 parentGroup.areUpdatesSuspended = true;
1734
1640 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); 1735 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>();
1641 1736
1642 // We do this in reverse to get the link order of the prims correct 1737 // We do this in reverse to get the link order of the prims correct
@@ -1651,9 +1746,13 @@ namespace OpenSim.Region.Framework.Scenes
1651 // Make sure no child prim is set for sale 1746 // Make sure no child prim is set for sale
1652 // So that, on delink, no prims are unwittingly 1747 // So that, on delink, no prims are unwittingly
1653 // left for sale and sold off 1748 // left for sale and sold off
1654 child.RootPart.ObjectSaleType = 0; 1749
1655 child.RootPart.SalePrice = 10; 1750 if (child != null)
1656 childGroups.Add(child); 1751 {
1752 child.RootPart.ObjectSaleType = 0;
1753 child.RootPart.SalePrice = 10;
1754 childGroups.Add(child);
1755 }
1657 } 1756 }
1658 1757
1659 foreach (SceneObjectGroup child in childGroups) 1758 foreach (SceneObjectGroup child in childGroups)
@@ -1680,6 +1779,16 @@ namespace OpenSim.Region.Framework.Scenes
1680 } 1779 }
1681 finally 1780 finally
1682 { 1781 {
1782 lock (SceneObjectGroupsByLocalPartID)
1783 {
1784 foreach (SceneObjectPart part in parentGroup.Parts)
1785 SceneObjectGroupsByLocalPartID[part.LocalId] = parentGroup;
1786 }
1787
1788 parentGroup.areUpdatesSuspended = false;
1789 parentGroup.HasGroupChanged = true;
1790 parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true);
1791 parentGroup.ScheduleGroupForFullUpdate();
1683 Monitor.Exit(m_updateLock); 1792 Monitor.Exit(m_updateLock);
1684 } 1793 }
1685 } 1794 }
@@ -1702,6 +1811,11 @@ namespace OpenSim.Region.Framework.Scenes
1702 { 1811 {
1703 if (part != null) 1812 if (part != null)
1704 { 1813 {
1814 if (part.KeyframeMotion != null)
1815 {
1816 part.KeyframeMotion.Stop();
1817 part.KeyframeMotion = null;
1818 }
1705 if (part.ParentGroup.PrimCount != 1) // Skip single 1819 if (part.ParentGroup.PrimCount != 1) // Skip single
1706 { 1820 {
1707 if (part.LinkNum < 2) // Root 1821 if (part.LinkNum < 2) // Root
@@ -1716,21 +1830,24 @@ namespace OpenSim.Region.Framework.Scenes
1716 1830
1717 SceneObjectGroup group = part.ParentGroup; 1831 SceneObjectGroup group = part.ParentGroup;
1718 if (!affectedGroups.Contains(group)) 1832 if (!affectedGroups.Contains(group))
1833 {
1834 group.areUpdatesSuspended = true;
1719 affectedGroups.Add(group); 1835 affectedGroups.Add(group);
1836 }
1720 } 1837 }
1721 } 1838 }
1722 } 1839 }
1723 1840
1724 foreach (SceneObjectPart child in childParts) 1841 if (childParts.Count > 0)
1725 { 1842 {
1726 // Unlink all child parts from their groups 1843 foreach (SceneObjectPart child in childParts)
1727 // 1844 {
1728 child.ParentGroup.DelinkFromGroup(child, true); 1845 // Unlink all child parts from their groups
1729 1846 //
1730 // These are not in affected groups and will not be 1847 child.ParentGroup.DelinkFromGroup(child, true);
1731 // handled further. Do the honors here. 1848 child.ParentGroup.HasGroupChanged = true;
1732 child.ParentGroup.HasGroupChanged = true; 1849 child.ParentGroup.ScheduleGroupForFullUpdate();
1733 child.ParentGroup.ScheduleGroupForFullUpdate(); 1850 }
1734 } 1851 }
1735 1852
1736 foreach (SceneObjectPart root in rootParts) 1853 foreach (SceneObjectPart root in rootParts)
@@ -1740,56 +1857,68 @@ namespace OpenSim.Region.Framework.Scenes
1740 // However, editing linked parts and unlinking may be different 1857 // However, editing linked parts and unlinking may be different
1741 // 1858 //
1742 SceneObjectGroup group = root.ParentGroup; 1859 SceneObjectGroup group = root.ParentGroup;
1860 group.areUpdatesSuspended = true;
1743 1861
1744 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); 1862 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts);
1745 int numChildren = newSet.Count; 1863 int numChildren = newSet.Count;
1746 1864
1865 if (numChildren == 1)
1866 break;
1867
1747 // If there are prims left in a link set, but the root is 1868 // If there are prims left in a link set, but the root is
1748 // slated for unlink, we need to do this 1869 // slated for unlink, we need to do this
1870 // Unlink the remaining set
1749 // 1871 //
1750 if (numChildren != 1) 1872 bool sendEventsToRemainder = true;
1751 { 1873 if (numChildren > 1)
1752 // Unlink the remaining set 1874 sendEventsToRemainder = false;
1753 //
1754 bool sendEventsToRemainder = true;
1755 if (numChildren > 1)
1756 sendEventsToRemainder = false;
1757 1875
1758 foreach (SceneObjectPart p in newSet) 1876 foreach (SceneObjectPart p in newSet)
1877 {
1878 if (p != group.RootPart)
1759 { 1879 {
1760 if (p != group.RootPart) 1880 group.DelinkFromGroup(p, sendEventsToRemainder);
1761 group.DelinkFromGroup(p, sendEventsToRemainder); 1881 if (numChildren > 2)
1882 {
1883 p.ParentGroup.areUpdatesSuspended = true;
1884 }
1885 else
1886 {
1887 p.ParentGroup.HasGroupChanged = true;
1888 p.ParentGroup.ScheduleGroupForFullUpdate();
1889 }
1762 } 1890 }
1891 }
1892
1893 // If there is more than one prim remaining, we
1894 // need to re-link
1895 //
1896 if (numChildren > 2)
1897 {
1898 // Remove old root
1899 //
1900 if (newSet.Contains(root))
1901 newSet.Remove(root);
1763 1902
1764 // If there is more than one prim remaining, we 1903 // Preserve link ordering
1765 // need to re-link
1766 // 1904 //
1767 if (numChildren > 2) 1905 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1768 { 1906 {
1769 // Remove old root 1907 return a.LinkNum.CompareTo(b.LinkNum);
1770 // 1908 });
1771 if (newSet.Contains(root))
1772 newSet.Remove(root);
1773
1774 // Preserve link ordering
1775 //
1776 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1777 {
1778 return a.LinkNum.CompareTo(b.LinkNum);
1779 });
1780 1909
1781 // Determine new root 1910 // Determine new root
1782 // 1911 //
1783 SceneObjectPart newRoot = newSet[0]; 1912 SceneObjectPart newRoot = newSet[0];
1784 newSet.RemoveAt(0); 1913 newSet.RemoveAt(0);
1785 1914
1786 foreach (SceneObjectPart newChild in newSet) 1915 foreach (SceneObjectPart newChild in newSet)
1787 newChild.ClearUpdateSchedule(); 1916 newChild.ClearUpdateSchedule();
1788 1917
1789 LinkObjects(newRoot, newSet); 1918 newRoot.ParentGroup.areUpdatesSuspended = true;
1790 if (!affectedGroups.Contains(newRoot.ParentGroup)) 1919 LinkObjects(newRoot, newSet);
1791 affectedGroups.Add(newRoot.ParentGroup); 1920 if (!affectedGroups.Contains(newRoot.ParentGroup))
1792 } 1921 affectedGroups.Add(newRoot.ParentGroup);
1793 } 1922 }
1794 } 1923 }
1795 1924
@@ -1797,8 +1926,14 @@ namespace OpenSim.Region.Framework.Scenes
1797 // 1926 //
1798 foreach (SceneObjectGroup g in affectedGroups) 1927 foreach (SceneObjectGroup g in affectedGroups)
1799 { 1928 {
1929 // Child prims that have been unlinked and deleted will
1930 // return unless the root is deleted. This will remove them
1931 // from the database. They will be rewritten immediately,
1932 // minus the rows for the unlinked child prims.
1933 m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID);
1800 g.TriggerScriptChangedEvent(Changed.LINK); 1934 g.TriggerScriptChangedEvent(Changed.LINK);
1801 g.HasGroupChanged = true; // Persist 1935 g.HasGroupChanged = true; // Persist
1936 g.areUpdatesSuspended = false;
1802 g.ScheduleGroupForFullUpdate(); 1937 g.ScheduleGroupForFullUpdate();
1803 } 1938 }
1804 } 1939 }
@@ -1900,9 +2035,6 @@ namespace OpenSim.Region.Framework.Scenes
1900 child.ApplyNextOwnerPermissions(); 2035 child.ApplyNextOwnerPermissions();
1901 } 2036 }
1902 } 2037 }
1903
1904 copy.RootPart.ObjectSaleType = 0;
1905 copy.RootPart.SalePrice = 10;
1906 } 2038 }
1907 2039
1908 // 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()