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.cs225
1 files changed, 169 insertions, 56 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index 7f18140..5e8227d 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();
@@ -475,6 +517,30 @@ namespace OpenSim.Region.Framework.Scenes
475 m_updateList[obj.UUID] = obj; 517 m_updateList[obj.UUID] = obj;
476 } 518 }
477 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
478 /// <summary> 544 /// <summary>
479 /// Process all pending updates 545 /// Process all pending updates
480 /// </summary> 546 /// </summary>
@@ -592,7 +658,8 @@ namespace OpenSim.Region.Framework.Scenes
592 658
593 Entities[presence.UUID] = presence; 659 Entities[presence.UUID] = presence;
594 660
595 lock (m_presenceLock) 661 m_scenePresencesLock.EnterWriteLock();
662 try
596 { 663 {
597 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 664 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
598 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 665 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -616,6 +683,10 @@ namespace OpenSim.Region.Framework.Scenes
616 m_scenePresenceMap = newmap; 683 m_scenePresenceMap = newmap;
617 m_scenePresenceArray = newlist; 684 m_scenePresenceArray = newlist;
618 } 685 }
686 finally
687 {
688 m_scenePresencesLock.ExitWriteLock();
689 }
619 } 690 }
620 691
621 /// <summary> 692 /// <summary>
@@ -630,7 +701,8 @@ namespace OpenSim.Region.Framework.Scenes
630 agentID); 701 agentID);
631 } 702 }
632 703
633 lock (m_presenceLock) 704 m_scenePresencesLock.EnterWriteLock();
705 try
634 { 706 {
635 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 707 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
636 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 708 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -652,6 +724,10 @@ namespace OpenSim.Region.Framework.Scenes
652 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);
653 } 725 }
654 } 726 }
727 finally
728 {
729 m_scenePresencesLock.ExitWriteLock();
730 }
655 } 731 }
656 732
657 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) 733 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F)
@@ -1365,8 +1441,13 @@ namespace OpenSim.Region.Framework.Scenes
1365 { 1441 {
1366 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) 1442 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0))
1367 { 1443 {
1368 if (m_parentScene.AttachmentsModule != null) 1444 // Set the new attachment point data in the object
1369 m_parentScene.AttachmentsModule.UpdateAttachmentPosition(group, pos); 1445 byte attachmentPoint = group.GetAttachmentPoint();
1446 group.UpdateGroupPosition(pos);
1447 group.IsAttachment = false;
1448 group.AbsolutePosition = group.RootPart.AttachedPos;
1449 group.AttachmentPoint = attachmentPoint;
1450 group.HasGroupChanged = true;
1370 } 1451 }
1371 else 1452 else
1372 { 1453 {
@@ -1638,8 +1719,11 @@ namespace OpenSim.Region.Framework.Scenes
1638 return; 1719 return;
1639 1720
1640 Monitor.Enter(m_updateLock); 1721 Monitor.Enter(m_updateLock);
1722
1641 try 1723 try
1642 { 1724 {
1725 parentGroup.areUpdatesSuspended = true;
1726
1643 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); 1727 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>();
1644 1728
1645 // We do this in reverse to get the link order of the prims correct 1729 // We do this in reverse to get the link order of the prims correct
@@ -1650,9 +1734,13 @@ namespace OpenSim.Region.Framework.Scenes
1650 // Make sure no child prim is set for sale 1734 // Make sure no child prim is set for sale
1651 // So that, on delink, no prims are unwittingly 1735 // So that, on delink, no prims are unwittingly
1652 // left for sale and sold off 1736 // left for sale and sold off
1653 child.RootPart.ObjectSaleType = 0; 1737
1654 child.RootPart.SalePrice = 10; 1738 if (child != null)
1655 childGroups.Add(child); 1739 {
1740 child.RootPart.ObjectSaleType = 0;
1741 child.RootPart.SalePrice = 10;
1742 childGroups.Add(child);
1743 }
1656 } 1744 }
1657 1745
1658 foreach (SceneObjectGroup child in childGroups) 1746 foreach (SceneObjectGroup child in childGroups)
@@ -1671,12 +1759,19 @@ namespace OpenSim.Region.Framework.Scenes
1671 // occur on link to invoke this elsewhere (such as object selection) 1759 // occur on link to invoke this elsewhere (such as object selection)
1672 parentGroup.RootPart.CreateSelected = true; 1760 parentGroup.RootPart.CreateSelected = true;
1673 parentGroup.TriggerScriptChangedEvent(Changed.LINK); 1761 parentGroup.TriggerScriptChangedEvent(Changed.LINK);
1674 parentGroup.HasGroupChanged = true;
1675 parentGroup.ScheduleGroupForFullUpdate();
1676
1677 } 1762 }
1678 finally 1763 finally
1679 { 1764 {
1765 lock (SceneObjectGroupsByLocalPartID)
1766 {
1767 foreach (SceneObjectPart part in parentGroup.Parts)
1768 SceneObjectGroupsByLocalPartID[part.LocalId] = parentGroup;
1769 }
1770
1771 parentGroup.areUpdatesSuspended = false;
1772 parentGroup.HasGroupChanged = true;
1773 parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true);
1774 parentGroup.ScheduleGroupForFullUpdate();
1680 Monitor.Exit(m_updateLock); 1775 Monitor.Exit(m_updateLock);
1681 } 1776 }
1682 } 1777 }
@@ -1713,21 +1808,24 @@ namespace OpenSim.Region.Framework.Scenes
1713 1808
1714 SceneObjectGroup group = part.ParentGroup; 1809 SceneObjectGroup group = part.ParentGroup;
1715 if (!affectedGroups.Contains(group)) 1810 if (!affectedGroups.Contains(group))
1811 {
1812 group.areUpdatesSuspended = true;
1716 affectedGroups.Add(group); 1813 affectedGroups.Add(group);
1814 }
1717 } 1815 }
1718 } 1816 }
1719 } 1817 }
1720 1818
1721 foreach (SceneObjectPart child in childParts) 1819 if (childParts.Count > 0)
1722 { 1820 {
1723 // Unlink all child parts from their groups 1821 foreach (SceneObjectPart child in childParts)
1724 // 1822 {
1725 child.ParentGroup.DelinkFromGroup(child, true); 1823 // Unlink all child parts from their groups
1726 1824 //
1727 // These are not in affected groups and will not be 1825 child.ParentGroup.DelinkFromGroup(child, true);
1728 // handled further. Do the honors here. 1826 child.ParentGroup.HasGroupChanged = true;
1729 child.ParentGroup.HasGroupChanged = true; 1827 child.ParentGroup.ScheduleGroupForFullUpdate();
1730 child.ParentGroup.ScheduleGroupForFullUpdate(); 1828 }
1731 } 1829 }
1732 1830
1733 foreach (SceneObjectPart root in rootParts) 1831 foreach (SceneObjectPart root in rootParts)
@@ -1737,56 +1835,68 @@ namespace OpenSim.Region.Framework.Scenes
1737 // However, editing linked parts and unlinking may be different 1835 // However, editing linked parts and unlinking may be different
1738 // 1836 //
1739 SceneObjectGroup group = root.ParentGroup; 1837 SceneObjectGroup group = root.ParentGroup;
1838 group.areUpdatesSuspended = true;
1740 1839
1741 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); 1840 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts);
1742 int numChildren = newSet.Count; 1841 int numChildren = newSet.Count;
1743 1842
1843 if (numChildren == 1)
1844 break;
1845
1744 // If there are prims left in a link set, but the root is 1846 // If there are prims left in a link set, but the root is
1745 // slated for unlink, we need to do this 1847 // slated for unlink, we need to do this
1848 // Unlink the remaining set
1746 // 1849 //
1747 if (numChildren != 1) 1850 bool sendEventsToRemainder = true;
1748 { 1851 if (numChildren > 1)
1749 // Unlink the remaining set 1852 sendEventsToRemainder = false;
1750 //
1751 bool sendEventsToRemainder = true;
1752 if (numChildren > 1)
1753 sendEventsToRemainder = false;
1754 1853
1755 foreach (SceneObjectPart p in newSet) 1854 foreach (SceneObjectPart p in newSet)
1855 {
1856 if (p != group.RootPart)
1756 { 1857 {
1757 if (p != group.RootPart) 1858 group.DelinkFromGroup(p, sendEventsToRemainder);
1758 group.DelinkFromGroup(p, sendEventsToRemainder); 1859 if (numChildren > 2)
1860 {
1861 p.ParentGroup.areUpdatesSuspended = true;
1862 }
1863 else
1864 {
1865 p.ParentGroup.HasGroupChanged = true;
1866 p.ParentGroup.ScheduleGroupForFullUpdate();
1867 }
1759 } 1868 }
1869 }
1870
1871 // If there is more than one prim remaining, we
1872 // need to re-link
1873 //
1874 if (numChildren > 2)
1875 {
1876 // Remove old root
1877 //
1878 if (newSet.Contains(root))
1879 newSet.Remove(root);
1760 1880
1761 // If there is more than one prim remaining, we 1881 // Preserve link ordering
1762 // need to re-link
1763 // 1882 //
1764 if (numChildren > 2) 1883 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1765 { 1884 {
1766 // Remove old root 1885 return a.LinkNum.CompareTo(b.LinkNum);
1767 // 1886 });
1768 if (newSet.Contains(root))
1769 newSet.Remove(root);
1770
1771 // Preserve link ordering
1772 //
1773 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1774 {
1775 return a.LinkNum.CompareTo(b.LinkNum);
1776 });
1777 1887
1778 // Determine new root 1888 // Determine new root
1779 // 1889 //
1780 SceneObjectPart newRoot = newSet[0]; 1890 SceneObjectPart newRoot = newSet[0];
1781 newSet.RemoveAt(0); 1891 newSet.RemoveAt(0);
1782 1892
1783 foreach (SceneObjectPart newChild in newSet) 1893 foreach (SceneObjectPart newChild in newSet)
1784 newChild.ClearUpdateSchedule(); 1894 newChild.ClearUpdateSchedule();
1785 1895
1786 LinkObjects(newRoot, newSet); 1896 newRoot.ParentGroup.areUpdatesSuspended = true;
1787 if (!affectedGroups.Contains(newRoot.ParentGroup)) 1897 LinkObjects(newRoot, newSet);
1788 affectedGroups.Add(newRoot.ParentGroup); 1898 if (!affectedGroups.Contains(newRoot.ParentGroup))
1789 } 1899 affectedGroups.Add(newRoot.ParentGroup);
1790 } 1900 }
1791 } 1901 }
1792 1902
@@ -1794,8 +1904,14 @@ namespace OpenSim.Region.Framework.Scenes
1794 // 1904 //
1795 foreach (SceneObjectGroup g in affectedGroups) 1905 foreach (SceneObjectGroup g in affectedGroups)
1796 { 1906 {
1907 // Child prims that have been unlinked and deleted will
1908 // return unless the root is deleted. This will remove them
1909 // from the database. They will be rewritten immediately,
1910 // minus the rows for the unlinked child prims.
1911 m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID);
1797 g.TriggerScriptChangedEvent(Changed.LINK); 1912 g.TriggerScriptChangedEvent(Changed.LINK);
1798 g.HasGroupChanged = true; // Persist 1913 g.HasGroupChanged = true; // Persist
1914 g.areUpdatesSuspended = false;
1799 g.ScheduleGroupForFullUpdate(); 1915 g.ScheduleGroupForFullUpdate();
1800 } 1916 }
1801 } 1917 }
@@ -1913,9 +2029,6 @@ namespace OpenSim.Region.Framework.Scenes
1913 child.ApplyNextOwnerPermissions(); 2029 child.ApplyNextOwnerPermissions();
1914 } 2030 }
1915 } 2031 }
1916
1917 copy.RootPart.ObjectSaleType = 0;
1918 copy.RootPart.SalePrice = 10;
1919 } 2032 }
1920 2033
1921 // FIXME: This section needs to be refactored so that it just calls AddSceneObject() 2034 // FIXME: This section needs to be refactored so that it just calls AddSceneObject()