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 1af8346..c4dd655 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);
@@ -60,11 +66,15 @@ namespace OpenSim.Region.Framework.Scenes
60 protected internal event PhysicsCrash UnRecoverableError; 66 protected internal event PhysicsCrash UnRecoverableError;
61 private PhysicsCrash handlerPhysicsCrash = null; 67 private PhysicsCrash handlerPhysicsCrash = null;
62 68
69 public event AttachToBackupDelegate OnAttachToBackup;
70 public event DetachFromBackupDelegate OnDetachFromBackup;
71 public event ChangedBackupDelegate OnChangeBackup;
72
63 #endregion 73 #endregion
64 74
65 #region Fields 75 #region Fields
66 76
67 protected object m_presenceLock = new object(); 77 protected OpenMetaverse.ReaderWriterLockSlim m_scenePresencesLock = new OpenMetaverse.ReaderWriterLockSlim();
68 protected Dictionary<UUID, ScenePresence> m_scenePresenceMap = new Dictionary<UUID, ScenePresence>(); 78 protected Dictionary<UUID, ScenePresence> m_scenePresenceMap = new Dictionary<UUID, ScenePresence>();
69 protected List<ScenePresence> m_scenePresenceArray = new List<ScenePresence>(); 79 protected List<ScenePresence> m_scenePresenceArray = new List<ScenePresence>();
70 80
@@ -126,13 +136,18 @@ namespace OpenSim.Region.Framework.Scenes
126 136
127 protected internal void Close() 137 protected internal void Close()
128 { 138 {
129 lock (m_presenceLock) 139 m_scenePresencesLock.EnterWriteLock();
140 try
130 { 141 {
131 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(); 142 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>();
132 List<ScenePresence> newlist = new List<ScenePresence>(); 143 List<ScenePresence> newlist = new List<ScenePresence>();
133 m_scenePresenceMap = newmap; 144 m_scenePresenceMap = newmap;
134 m_scenePresenceArray = newlist; 145 m_scenePresenceArray = newlist;
135 } 146 }
147 finally
148 {
149 m_scenePresencesLock.ExitWriteLock();
150 }
136 151
137 lock (SceneObjectGroupsByFullID) 152 lock (SceneObjectGroupsByFullID)
138 SceneObjectGroupsByFullID.Clear(); 153 SceneObjectGroupsByFullID.Clear();
@@ -271,6 +286,33 @@ namespace OpenSim.Region.Framework.Scenes
271 protected internal bool AddRestoredSceneObject( 286 protected internal bool AddRestoredSceneObject(
272 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 287 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
273 { 288 {
289 if (!m_parentScene.CombineRegions)
290 {
291 // KF: Check for out-of-region, move inside and make static.
292 Vector3 npos = new Vector3(sceneObject.RootPart.GroupPosition.X,
293 sceneObject.RootPart.GroupPosition.Y,
294 sceneObject.RootPart.GroupPosition.Z);
295 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 ||
296 npos.X > Constants.RegionSize ||
297 npos.Y > Constants.RegionSize))
298 {
299 if (npos.X < 0.0) npos.X = 1.0f;
300 if (npos.Y < 0.0) npos.Y = 1.0f;
301 if (npos.Z < 0.0) npos.Z = 0.0f;
302 if (npos.X > Constants.RegionSize) npos.X = Constants.RegionSize - 1.0f;
303 if (npos.Y > Constants.RegionSize) npos.Y = Constants.RegionSize - 1.0f;
304
305 foreach (SceneObjectPart part in sceneObject.Parts)
306 {
307 part.GroupPosition = npos;
308 }
309 sceneObject.RootPart.Velocity = Vector3.Zero;
310 sceneObject.RootPart.AngularVelocity = Vector3.Zero;
311 sceneObject.RootPart.Acceleration = Vector3.Zero;
312 sceneObject.RootPart.Velocity = Vector3.Zero;
313 }
314 }
315
274 if (attachToBackup && (!alreadyPersisted)) 316 if (attachToBackup && (!alreadyPersisted))
275 { 317 {
276 sceneObject.ForceInventoryPersistence(); 318 sceneObject.ForceInventoryPersistence();
@@ -481,6 +523,30 @@ namespace OpenSim.Region.Framework.Scenes
481 m_updateList[obj.UUID] = obj; 523 m_updateList[obj.UUID] = obj;
482 } 524 }
483 525
526 public void FireAttachToBackup(SceneObjectGroup obj)
527 {
528 if (OnAttachToBackup != null)
529 {
530 OnAttachToBackup(obj);
531 }
532 }
533
534 public void FireDetachFromBackup(SceneObjectGroup obj)
535 {
536 if (OnDetachFromBackup != null)
537 {
538 OnDetachFromBackup(obj);
539 }
540 }
541
542 public void FireChangeBackup(SceneObjectGroup obj)
543 {
544 if (OnChangeBackup != null)
545 {
546 OnChangeBackup(obj);
547 }
548 }
549
484 /// <summary> 550 /// <summary>
485 /// Process all pending updates 551 /// Process all pending updates
486 /// </summary> 552 /// </summary>
@@ -598,7 +664,8 @@ namespace OpenSim.Region.Framework.Scenes
598 664
599 Entities[presence.UUID] = presence; 665 Entities[presence.UUID] = presence;
600 666
601 lock (m_presenceLock) 667 m_scenePresencesLock.EnterWriteLock();
668 try
602 { 669 {
603 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 670 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
604 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 671 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -622,6 +689,10 @@ namespace OpenSim.Region.Framework.Scenes
622 m_scenePresenceMap = newmap; 689 m_scenePresenceMap = newmap;
623 m_scenePresenceArray = newlist; 690 m_scenePresenceArray = newlist;
624 } 691 }
692 finally
693 {
694 m_scenePresencesLock.ExitWriteLock();
695 }
625 } 696 }
626 697
627 /// <summary> 698 /// <summary>
@@ -636,7 +707,8 @@ namespace OpenSim.Region.Framework.Scenes
636 agentID); 707 agentID);
637 } 708 }
638 709
639 lock (m_presenceLock) 710 m_scenePresencesLock.EnterWriteLock();
711 try
640 { 712 {
641 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 713 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
642 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 714 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -658,6 +730,10 @@ namespace OpenSim.Region.Framework.Scenes
658 m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); 730 m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID);
659 } 731 }
660 } 732 }
733 finally
734 {
735 m_scenePresencesLock.ExitWriteLock();
736 }
661 } 737 }
662 738
663 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) 739 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F)
@@ -1371,8 +1447,13 @@ namespace OpenSim.Region.Framework.Scenes
1371 { 1447 {
1372 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) 1448 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0))
1373 { 1449 {
1374 if (m_parentScene.AttachmentsModule != null) 1450 // Set the new attachment point data in the object
1375 m_parentScene.AttachmentsModule.UpdateAttachmentPosition(group, pos); 1451 byte attachmentPoint = group.GetAttachmentPoint();
1452 group.UpdateGroupPosition(pos);
1453 group.IsAttachment = false;
1454 group.AbsolutePosition = group.RootPart.AttachedPos;
1455 group.AttachmentPoint = attachmentPoint;
1456 group.HasGroupChanged = true;
1376 } 1457 }
1377 else 1458 else
1378 { 1459 {
@@ -1644,8 +1725,11 @@ namespace OpenSim.Region.Framework.Scenes
1644 return; 1725 return;
1645 1726
1646 Monitor.Enter(m_updateLock); 1727 Monitor.Enter(m_updateLock);
1728
1647 try 1729 try
1648 { 1730 {
1731 parentGroup.areUpdatesSuspended = true;
1732
1649 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); 1733 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>();
1650 1734
1651 // We do this in reverse to get the link order of the prims correct 1735 // We do this in reverse to get the link order of the prims correct
@@ -1656,9 +1740,13 @@ namespace OpenSim.Region.Framework.Scenes
1656 // Make sure no child prim is set for sale 1740 // Make sure no child prim is set for sale
1657 // So that, on delink, no prims are unwittingly 1741 // So that, on delink, no prims are unwittingly
1658 // left for sale and sold off 1742 // left for sale and sold off
1659 child.RootPart.ObjectSaleType = 0; 1743
1660 child.RootPart.SalePrice = 10; 1744 if (child != null)
1661 childGroups.Add(child); 1745 {
1746 child.RootPart.ObjectSaleType = 0;
1747 child.RootPart.SalePrice = 10;
1748 childGroups.Add(child);
1749 }
1662 } 1750 }
1663 1751
1664 foreach (SceneObjectGroup child in childGroups) 1752 foreach (SceneObjectGroup child in childGroups)
@@ -1677,12 +1765,19 @@ namespace OpenSim.Region.Framework.Scenes
1677 // occur on link to invoke this elsewhere (such as object selection) 1765 // occur on link to invoke this elsewhere (such as object selection)
1678 parentGroup.RootPart.CreateSelected = true; 1766 parentGroup.RootPart.CreateSelected = true;
1679 parentGroup.TriggerScriptChangedEvent(Changed.LINK); 1767 parentGroup.TriggerScriptChangedEvent(Changed.LINK);
1680 parentGroup.HasGroupChanged = true;
1681 parentGroup.ScheduleGroupForFullUpdate();
1682
1683 } 1768 }
1684 finally 1769 finally
1685 { 1770 {
1771 lock (SceneObjectGroupsByLocalPartID)
1772 {
1773 foreach (SceneObjectPart part in parentGroup.Parts)
1774 SceneObjectGroupsByLocalPartID[part.LocalId] = parentGroup;
1775 }
1776
1777 parentGroup.areUpdatesSuspended = false;
1778 parentGroup.HasGroupChanged = true;
1779 parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true);
1780 parentGroup.ScheduleGroupForFullUpdate();
1686 Monitor.Exit(m_updateLock); 1781 Monitor.Exit(m_updateLock);
1687 } 1782 }
1688 } 1783 }
@@ -1719,21 +1814,24 @@ namespace OpenSim.Region.Framework.Scenes
1719 1814
1720 SceneObjectGroup group = part.ParentGroup; 1815 SceneObjectGroup group = part.ParentGroup;
1721 if (!affectedGroups.Contains(group)) 1816 if (!affectedGroups.Contains(group))
1817 {
1818 group.areUpdatesSuspended = true;
1722 affectedGroups.Add(group); 1819 affectedGroups.Add(group);
1820 }
1723 } 1821 }
1724 } 1822 }
1725 } 1823 }
1726 1824
1727 foreach (SceneObjectPart child in childParts) 1825 if (childParts.Count > 0)
1728 { 1826 {
1729 // Unlink all child parts from their groups 1827 foreach (SceneObjectPart child in childParts)
1730 // 1828 {
1731 child.ParentGroup.DelinkFromGroup(child, true); 1829 // Unlink all child parts from their groups
1732 1830 //
1733 // These are not in affected groups and will not be 1831 child.ParentGroup.DelinkFromGroup(child, true);
1734 // handled further. Do the honors here. 1832 child.ParentGroup.HasGroupChanged = true;
1735 child.ParentGroup.HasGroupChanged = true; 1833 child.ParentGroup.ScheduleGroupForFullUpdate();
1736 child.ParentGroup.ScheduleGroupForFullUpdate(); 1834 }
1737 } 1835 }
1738 1836
1739 foreach (SceneObjectPart root in rootParts) 1837 foreach (SceneObjectPart root in rootParts)
@@ -1743,56 +1841,68 @@ namespace OpenSim.Region.Framework.Scenes
1743 // However, editing linked parts and unlinking may be different 1841 // However, editing linked parts and unlinking may be different
1744 // 1842 //
1745 SceneObjectGroup group = root.ParentGroup; 1843 SceneObjectGroup group = root.ParentGroup;
1844 group.areUpdatesSuspended = true;
1746 1845
1747 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); 1846 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts);
1748 int numChildren = newSet.Count; 1847 int numChildren = newSet.Count;
1749 1848
1849 if (numChildren == 1)
1850 break;
1851
1750 // If there are prims left in a link set, but the root is 1852 // If there are prims left in a link set, but the root is
1751 // slated for unlink, we need to do this 1853 // slated for unlink, we need to do this
1854 // Unlink the remaining set
1752 // 1855 //
1753 if (numChildren != 1) 1856 bool sendEventsToRemainder = true;
1754 { 1857 if (numChildren > 1)
1755 // Unlink the remaining set 1858 sendEventsToRemainder = false;
1756 //
1757 bool sendEventsToRemainder = true;
1758 if (numChildren > 1)
1759 sendEventsToRemainder = false;
1760 1859
1761 foreach (SceneObjectPart p in newSet) 1860 foreach (SceneObjectPart p in newSet)
1861 {
1862 if (p != group.RootPart)
1762 { 1863 {
1763 if (p != group.RootPart) 1864 group.DelinkFromGroup(p, sendEventsToRemainder);
1764 group.DelinkFromGroup(p, sendEventsToRemainder); 1865 if (numChildren > 2)
1866 {
1867 p.ParentGroup.areUpdatesSuspended = true;
1868 }
1869 else
1870 {
1871 p.ParentGroup.HasGroupChanged = true;
1872 p.ParentGroup.ScheduleGroupForFullUpdate();
1873 }
1765 } 1874 }
1875 }
1876
1877 // If there is more than one prim remaining, we
1878 // need to re-link
1879 //
1880 if (numChildren > 2)
1881 {
1882 // Remove old root
1883 //
1884 if (newSet.Contains(root))
1885 newSet.Remove(root);
1766 1886
1767 // If there is more than one prim remaining, we 1887 // Preserve link ordering
1768 // need to re-link
1769 // 1888 //
1770 if (numChildren > 2) 1889 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1771 { 1890 {
1772 // Remove old root 1891 return a.LinkNum.CompareTo(b.LinkNum);
1773 // 1892 });
1774 if (newSet.Contains(root))
1775 newSet.Remove(root);
1776
1777 // Preserve link ordering
1778 //
1779 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1780 {
1781 return a.LinkNum.CompareTo(b.LinkNum);
1782 });
1783 1893
1784 // Determine new root 1894 // Determine new root
1785 // 1895 //
1786 SceneObjectPart newRoot = newSet[0]; 1896 SceneObjectPart newRoot = newSet[0];
1787 newSet.RemoveAt(0); 1897 newSet.RemoveAt(0);
1788 1898
1789 foreach (SceneObjectPart newChild in newSet) 1899 foreach (SceneObjectPart newChild in newSet)
1790 newChild.ClearUpdateSchedule(); 1900 newChild.ClearUpdateSchedule();
1791 1901
1792 LinkObjects(newRoot, newSet); 1902 newRoot.ParentGroup.areUpdatesSuspended = true;
1793 if (!affectedGroups.Contains(newRoot.ParentGroup)) 1903 LinkObjects(newRoot, newSet);
1794 affectedGroups.Add(newRoot.ParentGroup); 1904 if (!affectedGroups.Contains(newRoot.ParentGroup))
1795 } 1905 affectedGroups.Add(newRoot.ParentGroup);
1796 } 1906 }
1797 } 1907 }
1798 1908
@@ -1800,8 +1910,14 @@ namespace OpenSim.Region.Framework.Scenes
1800 // 1910 //
1801 foreach (SceneObjectGroup g in affectedGroups) 1911 foreach (SceneObjectGroup g in affectedGroups)
1802 { 1912 {
1913 // Child prims that have been unlinked and deleted will
1914 // return unless the root is deleted. This will remove them
1915 // from the database. They will be rewritten immediately,
1916 // minus the rows for the unlinked child prims.
1917 m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID);
1803 g.TriggerScriptChangedEvent(Changed.LINK); 1918 g.TriggerScriptChangedEvent(Changed.LINK);
1804 g.HasGroupChanged = true; // Persist 1919 g.HasGroupChanged = true; // Persist
1920 g.areUpdatesSuspended = false;
1805 g.ScheduleGroupForFullUpdate(); 1921 g.ScheduleGroupForFullUpdate();
1806 } 1922 }
1807 } 1923 }
@@ -1919,9 +2035,6 @@ namespace OpenSim.Region.Framework.Scenes
1919 child.ApplyNextOwnerPermissions(); 2035 child.ApplyNextOwnerPermissions();
1920 } 2036 }
1921 } 2037 }
1922
1923 copy.RootPart.ObjectSaleType = 0;
1924 copy.RootPart.SalePrice = 10;
1925 } 2038 }
1926 2039
1927 // 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()