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.cs224
1 files changed, 165 insertions, 59 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index caec704..13668ab 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -43,6 +43,12 @@ namespace OpenSim.Region.Framework.Scenes
43 43
44 public delegate void ObjectDuplicateDelegate(EntityBase original, EntityBase clone); 44 public delegate void ObjectDuplicateDelegate(EntityBase original, EntityBase clone);
45 45
46 public delegate void AttachToBackupDelegate(SceneObjectGroup sog);
47
48 public delegate void DetachFromBackupDelegate(SceneObjectGroup sog);
49
50 public delegate void ChangedBackupDelegate(SceneObjectGroup sog);
51
46 public delegate void ObjectCreateDelegate(EntityBase obj); 52 public delegate void ObjectCreateDelegate(EntityBase obj);
47 53
48 public delegate void ObjectDeleteDelegate(EntityBase obj); 54 public delegate void ObjectDeleteDelegate(EntityBase obj);
@@ -61,6 +67,9 @@ namespace OpenSim.Region.Framework.Scenes
61 private PhysicsCrash handlerPhysicsCrash = null; 67 private PhysicsCrash handlerPhysicsCrash = null;
62 68
63 public event ObjectDuplicateDelegate OnObjectDuplicate; 69 public event ObjectDuplicateDelegate OnObjectDuplicate;
70 public event AttachToBackupDelegate OnAttachToBackup;
71 public event DetachFromBackupDelegate OnDetachFromBackup;
72 public event ChangedBackupDelegate OnChangeBackup;
64 public event ObjectCreateDelegate OnObjectCreate; 73 public event ObjectCreateDelegate OnObjectCreate;
65 public event ObjectDeleteDelegate OnObjectRemove; 74 public event ObjectDeleteDelegate OnObjectRemove;
66 75
@@ -68,7 +77,7 @@ namespace OpenSim.Region.Framework.Scenes
68 77
69 #region Fields 78 #region Fields
70 79
71 protected object m_presenceLock = new object(); 80 protected OpenMetaverse.ReaderWriterLockSlim m_scenePresencesLock = new OpenMetaverse.ReaderWriterLockSlim();
72 protected Dictionary<UUID, ScenePresence> m_scenePresenceMap = new Dictionary<UUID, ScenePresence>(); 81 protected Dictionary<UUID, ScenePresence> m_scenePresenceMap = new Dictionary<UUID, ScenePresence>();
73 protected List<ScenePresence> m_scenePresenceArray = new List<ScenePresence>(); 82 protected List<ScenePresence> m_scenePresenceArray = new List<ScenePresence>();
74 83
@@ -132,13 +141,18 @@ namespace OpenSim.Region.Framework.Scenes
132 141
133 protected internal void Close() 142 protected internal void Close()
134 { 143 {
135 lock (m_presenceLock) 144 m_scenePresencesLock.EnterWriteLock();
145 try
136 { 146 {
137 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(); 147 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>();
138 List<ScenePresence> newlist = new List<ScenePresence>(); 148 List<ScenePresence> newlist = new List<ScenePresence>();
139 m_scenePresenceMap = newmap; 149 m_scenePresenceMap = newmap;
140 m_scenePresenceArray = newlist; 150 m_scenePresenceArray = newlist;
141 } 151 }
152 finally
153 {
154 m_scenePresencesLock.ExitWriteLock();
155 }
142 156
143 lock (SceneObjectGroupsByFullID) 157 lock (SceneObjectGroupsByFullID)
144 SceneObjectGroupsByFullID.Clear(); 158 SceneObjectGroupsByFullID.Clear();
@@ -281,6 +295,33 @@ namespace OpenSim.Region.Framework.Scenes
281 protected internal bool AddRestoredSceneObject( 295 protected internal bool AddRestoredSceneObject(
282 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 296 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
283 { 297 {
298 if (!m_parentScene.CombineRegions)
299 {
300 // KF: Check for out-of-region, move inside and make static.
301 Vector3 npos = new Vector3(sceneObject.RootPart.GroupPosition.X,
302 sceneObject.RootPart.GroupPosition.Y,
303 sceneObject.RootPart.GroupPosition.Z);
304 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 ||
305 npos.X > Constants.RegionSize ||
306 npos.Y > Constants.RegionSize))
307 {
308 if (npos.X < 0.0) npos.X = 1.0f;
309 if (npos.Y < 0.0) npos.Y = 1.0f;
310 if (npos.Z < 0.0) npos.Z = 0.0f;
311 if (npos.X > Constants.RegionSize) npos.X = Constants.RegionSize - 1.0f;
312 if (npos.Y > Constants.RegionSize) npos.Y = Constants.RegionSize - 1.0f;
313
314 foreach (SceneObjectPart part in sceneObject.Parts)
315 {
316 part.GroupPosition = npos;
317 }
318 sceneObject.RootPart.Velocity = Vector3.Zero;
319 sceneObject.RootPart.AngularVelocity = Vector3.Zero;
320 sceneObject.RootPart.Acceleration = Vector3.Zero;
321 sceneObject.RootPart.Velocity = Vector3.Zero;
322 }
323 }
324
284 if (attachToBackup && (!alreadyPersisted)) 325 if (attachToBackup && (!alreadyPersisted))
285 { 326 {
286 sceneObject.ForceInventoryPersistence(); 327 sceneObject.ForceInventoryPersistence();
@@ -498,6 +539,30 @@ namespace OpenSim.Region.Framework.Scenes
498 m_updateList[obj.UUID] = obj; 539 m_updateList[obj.UUID] = obj;
499 } 540 }
500 541
542 public void FireAttachToBackup(SceneObjectGroup obj)
543 {
544 if (OnAttachToBackup != null)
545 {
546 OnAttachToBackup(obj);
547 }
548 }
549
550 public void FireDetachFromBackup(SceneObjectGroup obj)
551 {
552 if (OnDetachFromBackup != null)
553 {
554 OnDetachFromBackup(obj);
555 }
556 }
557
558 public void FireChangeBackup(SceneObjectGroup obj)
559 {
560 if (OnChangeBackup != null)
561 {
562 OnChangeBackup(obj);
563 }
564 }
565
501 /// <summary> 566 /// <summary>
502 /// Process all pending updates 567 /// Process all pending updates
503 /// </summary> 568 /// </summary>
@@ -629,7 +694,8 @@ namespace OpenSim.Region.Framework.Scenes
629 694
630 Entities[presence.UUID] = presence; 695 Entities[presence.UUID] = presence;
631 696
632 lock (m_presenceLock) 697 m_scenePresencesLock.EnterWriteLock();
698 try
633 { 699 {
634 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 700 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
635 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 701 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -653,6 +719,10 @@ namespace OpenSim.Region.Framework.Scenes
653 m_scenePresenceMap = newmap; 719 m_scenePresenceMap = newmap;
654 m_scenePresenceArray = newlist; 720 m_scenePresenceArray = newlist;
655 } 721 }
722 finally
723 {
724 m_scenePresencesLock.ExitWriteLock();
725 }
656 } 726 }
657 727
658 /// <summary> 728 /// <summary>
@@ -667,7 +737,8 @@ namespace OpenSim.Region.Framework.Scenes
667 agentID); 737 agentID);
668 } 738 }
669 739
670 lock (m_presenceLock) 740 m_scenePresencesLock.EnterWriteLock();
741 try
671 { 742 {
672 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 743 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
673 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 744 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -689,6 +760,10 @@ namespace OpenSim.Region.Framework.Scenes
689 m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); 760 m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID);
690 } 761 }
691 } 762 }
763 finally
764 {
765 m_scenePresencesLock.ExitWriteLock();
766 }
692 } 767 }
693 768
694 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) 769 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F)
@@ -1388,8 +1463,13 @@ namespace OpenSim.Region.Framework.Scenes
1388 { 1463 {
1389 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) 1464 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0))
1390 { 1465 {
1391 if (m_parentScene.AttachmentsModule != null) 1466 // Set the new attachment point data in the object
1392 m_parentScene.AttachmentsModule.UpdateAttachmentPosition(group, pos); 1467 byte attachmentPoint = group.GetAttachmentPoint();
1468 group.UpdateGroupPosition(pos);
1469 group.IsAttachment = false;
1470 group.AbsolutePosition = group.RootPart.AttachedPos;
1471 group.AttachmentPoint = attachmentPoint;
1472 group.HasGroupChanged = true;
1393 } 1473 }
1394 else 1474 else
1395 { 1475 {
@@ -1653,10 +1733,13 @@ namespace OpenSim.Region.Framework.Scenes
1653 /// <param name="childPrims"></param> 1733 /// <param name="childPrims"></param>
1654 protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children) 1734 protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children)
1655 { 1735 {
1736 SceneObjectGroup parentGroup = root.ParentGroup;
1737 if (parentGroup == null) return;
1656 Monitor.Enter(m_updateLock); 1738 Monitor.Enter(m_updateLock);
1739
1657 try 1740 try
1658 { 1741 {
1659 SceneObjectGroup parentGroup = root.ParentGroup; 1742 parentGroup.areUpdatesSuspended = true;
1660 1743
1661 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); 1744 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>();
1662 1745
@@ -1668,9 +1751,13 @@ namespace OpenSim.Region.Framework.Scenes
1668 // Make sure no child prim is set for sale 1751 // Make sure no child prim is set for sale
1669 // So that, on delink, no prims are unwittingly 1752 // So that, on delink, no prims are unwittingly
1670 // left for sale and sold off 1753 // left for sale and sold off
1671 child.RootPart.ObjectSaleType = 0; 1754
1672 child.RootPart.SalePrice = 10; 1755 if (child != null)
1673 childGroups.Add(child); 1756 {
1757 child.RootPart.ObjectSaleType = 0;
1758 child.RootPart.SalePrice = 10;
1759 childGroups.Add(child);
1760 }
1674 } 1761 }
1675 1762
1676 foreach (SceneObjectGroup child in childGroups) 1763 foreach (SceneObjectGroup child in childGroups)
@@ -1686,12 +1773,13 @@ namespace OpenSim.Region.Framework.Scenes
1686 // occur on link to invoke this elsewhere (such as object selection) 1773 // occur on link to invoke this elsewhere (such as object selection)
1687 parentGroup.RootPart.CreateSelected = true; 1774 parentGroup.RootPart.CreateSelected = true;
1688 parentGroup.TriggerScriptChangedEvent(Changed.LINK); 1775 parentGroup.TriggerScriptChangedEvent(Changed.LINK);
1689 parentGroup.HasGroupChanged = true;
1690 parentGroup.ScheduleGroupForFullUpdate();
1691
1692 } 1776 }
1693 finally 1777 finally
1694 { 1778 {
1779 parentGroup.areUpdatesSuspended = false;
1780 parentGroup.HasGroupChanged = true;
1781 parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true);
1782 parentGroup.ScheduleGroupForFullUpdate();
1695 Monitor.Exit(m_updateLock); 1783 Monitor.Exit(m_updateLock);
1696 } 1784 }
1697 } 1785 }
@@ -1723,21 +1811,24 @@ namespace OpenSim.Region.Framework.Scenes
1723 1811
1724 SceneObjectGroup group = part.ParentGroup; 1812 SceneObjectGroup group = part.ParentGroup;
1725 if (!affectedGroups.Contains(group)) 1813 if (!affectedGroups.Contains(group))
1814 {
1815 group.areUpdatesSuspended = true;
1726 affectedGroups.Add(group); 1816 affectedGroups.Add(group);
1817 }
1727 } 1818 }
1728 } 1819 }
1729 } 1820 }
1730 1821
1731 foreach (SceneObjectPart child in childParts) 1822 if (childParts.Count > 0)
1732 { 1823 {
1733 // Unlink all child parts from their groups 1824 foreach (SceneObjectPart child in childParts)
1734 // 1825 {
1735 child.ParentGroup.DelinkFromGroup(child, true); 1826 // Unlink all child parts from their groups
1736 1827 //
1737 // These are not in affected groups and will not be 1828 child.ParentGroup.DelinkFromGroup(child, true);
1738 // handled further. Do the honors here. 1829 child.ParentGroup.HasGroupChanged = true;
1739 child.ParentGroup.HasGroupChanged = true; 1830 child.ParentGroup.ScheduleGroupForFullUpdate();
1740 child.ParentGroup.ScheduleGroupForFullUpdate(); 1831 }
1741 } 1832 }
1742 1833
1743 foreach (SceneObjectPart root in rootParts) 1834 foreach (SceneObjectPart root in rootParts)
@@ -1747,56 +1838,68 @@ namespace OpenSim.Region.Framework.Scenes
1747 // However, editing linked parts and unlinking may be different 1838 // However, editing linked parts and unlinking may be different
1748 // 1839 //
1749 SceneObjectGroup group = root.ParentGroup; 1840 SceneObjectGroup group = root.ParentGroup;
1841 group.areUpdatesSuspended = true;
1750 1842
1751 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); 1843 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts);
1752 int numChildren = newSet.Count; 1844 int numChildren = newSet.Count;
1753 1845
1846 if (numChildren == 1)
1847 break;
1848
1754 // If there are prims left in a link set, but the root is 1849 // If there are prims left in a link set, but the root is
1755 // slated for unlink, we need to do this 1850 // slated for unlink, we need to do this
1851 // Unlink the remaining set
1756 // 1852 //
1757 if (numChildren != 1) 1853 bool sendEventsToRemainder = true;
1758 { 1854 if (numChildren > 1)
1759 // Unlink the remaining set 1855 sendEventsToRemainder = false;
1760 //
1761 bool sendEventsToRemainder = true;
1762 if (numChildren > 1)
1763 sendEventsToRemainder = false;
1764 1856
1765 foreach (SceneObjectPart p in newSet) 1857 foreach (SceneObjectPart p in newSet)
1858 {
1859 if (p != group.RootPart)
1766 { 1860 {
1767 if (p != group.RootPart) 1861 group.DelinkFromGroup(p, sendEventsToRemainder);
1768 group.DelinkFromGroup(p, sendEventsToRemainder); 1862 if (numChildren > 2)
1863 {
1864 p.ParentGroup.areUpdatesSuspended = true;
1865 }
1866 else
1867 {
1868 p.ParentGroup.HasGroupChanged = true;
1869 p.ParentGroup.ScheduleGroupForFullUpdate();
1870 }
1769 } 1871 }
1872 }
1770 1873
1771 // If there is more than one prim remaining, we 1874 // If there is more than one prim remaining, we
1772 // need to re-link 1875 // need to re-link
1876 //
1877 if (numChildren > 2)
1878 {
1879 // Remove old root
1880 //
1881 if (newSet.Contains(root))
1882 newSet.Remove(root);
1883
1884 // Preserve link ordering
1773 // 1885 //
1774 if (numChildren > 2) 1886 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1775 { 1887 {
1776 // Remove old root 1888 return a.LinkNum.CompareTo(b.LinkNum);
1777 // 1889 });
1778 if (newSet.Contains(root))
1779 newSet.Remove(root);
1780
1781 // Preserve link ordering
1782 //
1783 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1784 {
1785 return a.LinkNum.CompareTo(b.LinkNum);
1786 });
1787 1890
1788 // Determine new root 1891 // Determine new root
1789 // 1892 //
1790 SceneObjectPart newRoot = newSet[0]; 1893 SceneObjectPart newRoot = newSet[0];
1791 newSet.RemoveAt(0); 1894 newSet.RemoveAt(0);
1792 1895
1793 foreach (SceneObjectPart newChild in newSet) 1896 foreach (SceneObjectPart newChild in newSet)
1794 newChild.UpdateFlag = 0; 1897 newChild.UpdateFlag = 0;
1795 1898
1796 LinkObjects(newRoot, newSet); 1899 newRoot.ParentGroup.areUpdatesSuspended = true;
1797 if (!affectedGroups.Contains(newRoot.ParentGroup)) 1900 LinkObjects(newRoot, newSet);
1798 affectedGroups.Add(newRoot.ParentGroup); 1901 if (!affectedGroups.Contains(newRoot.ParentGroup))
1799 } 1902 affectedGroups.Add(newRoot.ParentGroup);
1800 } 1903 }
1801 } 1904 }
1802 1905
@@ -1804,8 +1907,14 @@ namespace OpenSim.Region.Framework.Scenes
1804 // 1907 //
1805 foreach (SceneObjectGroup g in affectedGroups) 1908 foreach (SceneObjectGroup g in affectedGroups)
1806 { 1909 {
1910 // Child prims that have been unlinked and deleted will
1911 // return unless the root is deleted. This will remove them
1912 // from the database. They will be rewritten immediately,
1913 // minus the rows for the unlinked child prims.
1914 m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID);
1807 g.TriggerScriptChangedEvent(Changed.LINK); 1915 g.TriggerScriptChangedEvent(Changed.LINK);
1808 g.HasGroupChanged = true; // Persist 1916 g.HasGroupChanged = true; // Persist
1917 g.areUpdatesSuspended = false;
1809 g.ScheduleGroupForFullUpdate(); 1918 g.ScheduleGroupForFullUpdate();
1810 } 1919 }
1811 } 1920 }
@@ -1923,9 +2032,6 @@ namespace OpenSim.Region.Framework.Scenes
1923 child.ApplyNextOwnerPermissions(); 2032 child.ApplyNextOwnerPermissions();
1924 } 2033 }
1925 } 2034 }
1926
1927 copy.RootPart.ObjectSaleType = 0;
1928 copy.RootPart.SalePrice = 10;
1929 } 2035 }
1930 2036
1931 // FIXME: This section needs to be refactored so that it just calls AddSceneObject() 2037 // FIXME: This section needs to be refactored so that it just calls AddSceneObject()