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.cs293
1 files changed, 238 insertions, 55 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index 67eb0fe..0a1b921 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
@@ -123,13 +133,18 @@ namespace OpenSim.Region.Framework.Scenes
123 133
124 protected internal void Close() 134 protected internal void Close()
125 { 135 {
126 lock (m_presenceLock) 136 m_scenePresencesLock.EnterWriteLock();
137 try
127 { 138 {
128 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(); 139 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>();
129 List<ScenePresence> newlist = new List<ScenePresence>(); 140 List<ScenePresence> newlist = new List<ScenePresence>();
130 m_scenePresenceMap = newmap; 141 m_scenePresenceMap = newmap;
131 m_scenePresenceArray = newlist; 142 m_scenePresenceArray = newlist;
132 } 143 }
144 finally
145 {
146 m_scenePresencesLock.ExitWriteLock();
147 }
133 148
134 lock (SceneObjectGroupsByFullID) 149 lock (SceneObjectGroupsByFullID)
135 SceneObjectGroupsByFullID.Clear(); 150 SceneObjectGroupsByFullID.Clear();
@@ -250,6 +265,33 @@ namespace OpenSim.Region.Framework.Scenes
250 protected internal bool AddRestoredSceneObject( 265 protected internal bool AddRestoredSceneObject(
251 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 266 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
252 { 267 {
268 if (!m_parentScene.CombineRegions)
269 {
270 // KF: Check for out-of-region, move inside and make static.
271 Vector3 npos = new Vector3(sceneObject.RootPart.GroupPosition.X,
272 sceneObject.RootPart.GroupPosition.Y,
273 sceneObject.RootPart.GroupPosition.Z);
274 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 ||
275 npos.X > Constants.RegionSize ||
276 npos.Y > Constants.RegionSize))
277 {
278 if (npos.X < 0.0) npos.X = 1.0f;
279 if (npos.Y < 0.0) npos.Y = 1.0f;
280 if (npos.Z < 0.0) npos.Z = 0.0f;
281 if (npos.X > Constants.RegionSize) npos.X = Constants.RegionSize - 1.0f;
282 if (npos.Y > Constants.RegionSize) npos.Y = Constants.RegionSize - 1.0f;
283
284 foreach (SceneObjectPart part in sceneObject.Parts)
285 {
286 part.GroupPosition = npos;
287 }
288 sceneObject.RootPart.Velocity = Vector3.Zero;
289 sceneObject.RootPart.AngularVelocity = Vector3.Zero;
290 sceneObject.RootPart.Acceleration = Vector3.Zero;
291 sceneObject.RootPart.Velocity = Vector3.Zero;
292 }
293 }
294
253 if (attachToBackup && (!alreadyPersisted)) 295 if (attachToBackup && (!alreadyPersisted))
254 { 296 {
255 sceneObject.ForceInventoryPersistence(); 297 sceneObject.ForceInventoryPersistence();
@@ -340,6 +382,11 @@ namespace OpenSim.Region.Framework.Scenes
340 /// </returns> 382 /// </returns>
341 protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) 383 protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates)
342 { 384 {
385 if (sceneObject == null)
386 {
387 m_log.ErrorFormat("[SCENEGRAPH]: Tried to add null scene object");
388 return false;
389 }
343 if (sceneObject.UUID == UUID.Zero) 390 if (sceneObject.UUID == UUID.Zero)
344 { 391 {
345 m_log.ErrorFormat( 392 m_log.ErrorFormat(
@@ -474,6 +521,30 @@ namespace OpenSim.Region.Framework.Scenes
474 m_updateList[obj.UUID] = obj; 521 m_updateList[obj.UUID] = obj;
475 } 522 }
476 523
524 public void FireAttachToBackup(SceneObjectGroup obj)
525 {
526 if (OnAttachToBackup != null)
527 {
528 OnAttachToBackup(obj);
529 }
530 }
531
532 public void FireDetachFromBackup(SceneObjectGroup obj)
533 {
534 if (OnDetachFromBackup != null)
535 {
536 OnDetachFromBackup(obj);
537 }
538 }
539
540 public void FireChangeBackup(SceneObjectGroup obj)
541 {
542 if (OnChangeBackup != null)
543 {
544 OnChangeBackup(obj);
545 }
546 }
547
477 /// <summary> 548 /// <summary>
478 /// Process all pending updates 549 /// Process all pending updates
479 /// </summary> 550 /// </summary>
@@ -591,7 +662,8 @@ namespace OpenSim.Region.Framework.Scenes
591 662
592 Entities[presence.UUID] = presence; 663 Entities[presence.UUID] = presence;
593 664
594 lock (m_presenceLock) 665 m_scenePresencesLock.EnterWriteLock();
666 try
595 { 667 {
596 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 668 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
597 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 669 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -615,6 +687,10 @@ namespace OpenSim.Region.Framework.Scenes
615 m_scenePresenceMap = newmap; 687 m_scenePresenceMap = newmap;
616 m_scenePresenceArray = newlist; 688 m_scenePresenceArray = newlist;
617 } 689 }
690 finally
691 {
692 m_scenePresencesLock.ExitWriteLock();
693 }
618 } 694 }
619 695
620 /// <summary> 696 /// <summary>
@@ -629,7 +705,8 @@ namespace OpenSim.Region.Framework.Scenes
629 agentID); 705 agentID);
630 } 706 }
631 707
632 lock (m_presenceLock) 708 m_scenePresencesLock.EnterWriteLock();
709 try
633 { 710 {
634 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 711 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
635 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 712 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -651,6 +728,10 @@ namespace OpenSim.Region.Framework.Scenes
651 m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); 728 m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID);
652 } 729 }
653 } 730 }
731 finally
732 {
733 m_scenePresencesLock.ExitWriteLock();
734 }
654 } 735 }
655 736
656 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) 737 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F)
@@ -1183,6 +1264,25 @@ namespace OpenSim.Region.Framework.Scenes
1183 1264
1184 #region Client Event handlers 1265 #region Client Event handlers
1185 1266
1267 protected internal void ClientChangeObject(uint localID, object odata, IClientAPI remoteClient)
1268 {
1269 SceneObjectPart part = GetSceneObjectPart(localID);
1270 ObjectChangeData data = (ObjectChangeData)odata;
1271
1272 if (part != null)
1273 {
1274 SceneObjectGroup grp = part.ParentGroup;
1275 if (grp != null)
1276 {
1277 if (m_parentScene.Permissions.CanEditObject(grp.UUID, remoteClient.AgentId))
1278 {
1279 part.StoreUndoState(data.change); // lets test only saving what we changed
1280 grp.doChangeObject(part, (ObjectChangeData)data);
1281 }
1282 }
1283 }
1284 }
1285
1186 /// <summary> 1286 /// <summary>
1187 /// Update the scale of an individual prim. 1287 /// Update the scale of an individual prim.
1188 /// </summary> 1288 /// </summary>
@@ -1197,7 +1297,17 @@ namespace OpenSim.Region.Framework.Scenes
1197 { 1297 {
1198 if (m_parentScene.Permissions.CanEditObject(part.ParentGroup.UUID, remoteClient.AgentId)) 1298 if (m_parentScene.Permissions.CanEditObject(part.ParentGroup.UUID, remoteClient.AgentId))
1199 { 1299 {
1300 bool physbuild = false;
1301 if (part.ParentGroup.RootPart.PhysActor != null)
1302 {
1303 part.ParentGroup.RootPart.PhysActor.Building = true;
1304 physbuild = true;
1305 }
1306
1200 part.Resize(scale); 1307 part.Resize(scale);
1308
1309 if (physbuild)
1310 part.ParentGroup.RootPart.PhysActor.Building = false;
1201 } 1311 }
1202 } 1312 }
1203 } 1313 }
@@ -1209,7 +1319,17 @@ namespace OpenSim.Region.Framework.Scenes
1209 { 1319 {
1210 if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) 1320 if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId))
1211 { 1321 {
1322 bool physbuild = false;
1323 if (group.RootPart.PhysActor != null)
1324 {
1325 group.RootPart.PhysActor.Building = true;
1326 physbuild = true;
1327 }
1328
1212 group.GroupResize(scale); 1329 group.GroupResize(scale);
1330
1331 if (physbuild)
1332 group.RootPart.PhysActor.Building = false;
1213 } 1333 }
1214 } 1334 }
1215 } 1335 }
@@ -1337,8 +1457,13 @@ namespace OpenSim.Region.Framework.Scenes
1337 { 1457 {
1338 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) 1458 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0))
1339 { 1459 {
1340 if (m_parentScene.AttachmentsModule != null) 1460 // Set the new attachment point data in the object
1341 m_parentScene.AttachmentsModule.UpdateAttachmentPosition(group, pos); 1461 byte attachmentPoint = group.GetAttachmentPoint();
1462 group.UpdateGroupPosition(pos);
1463 group.IsAttachment = false;
1464 group.AbsolutePosition = group.RootPart.AttachedPos;
1465 group.AttachmentPoint = attachmentPoint;
1466 group.HasGroupChanged = true;
1342 } 1467 }
1343 else 1468 else
1344 { 1469 {
@@ -1386,7 +1511,7 @@ namespace OpenSim.Region.Framework.Scenes
1386 /// <param name="SetPhantom"></param> 1511 /// <param name="SetPhantom"></param>
1387 /// <param name="remoteClient"></param> 1512 /// <param name="remoteClient"></param>
1388 protected internal void UpdatePrimFlags( 1513 protected internal void UpdatePrimFlags(
1389 uint localID, bool UsePhysics, bool SetTemporary, bool SetPhantom, IClientAPI remoteClient) 1514 uint localID, bool UsePhysics, bool SetTemporary, bool SetPhantom, ExtraPhysicsData PhysData, IClientAPI remoteClient)
1390 { 1515 {
1391 SceneObjectGroup group = GetGroupByPrim(localID); 1516 SceneObjectGroup group = GetGroupByPrim(localID);
1392 if (group != null) 1517 if (group != null)
@@ -1394,7 +1519,18 @@ namespace OpenSim.Region.Framework.Scenes
1394 if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) 1519 if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId))
1395 { 1520 {
1396 // VolumeDetect can't be set via UI and will always be off when a change is made there 1521 // VolumeDetect can't be set via UI and will always be off when a change is made there
1397 group.UpdatePrimFlags(localID, UsePhysics, SetTemporary, SetPhantom, false); 1522 if (PhysData.PhysShapeType == PhysShapeType.invalid)
1523 group.UpdatePrimFlags(localID, UsePhysics, SetTemporary, SetPhantom, false);
1524 else
1525 {
1526 SceneObjectPart part = GetSceneObjectPart(localID);
1527 if (part != null)
1528 {
1529 part.UpdateExtraPhysics(PhysData);
1530 if (part.UpdatePhysRequired)
1531 remoteClient.SendPartPhysicsProprieties(part);
1532 }
1533 }
1398 } 1534 }
1399 } 1535 }
1400 } 1536 }
@@ -1538,6 +1674,7 @@ namespace OpenSim.Region.Framework.Scenes
1538 { 1674 {
1539 part.Material = Convert.ToByte(material); 1675 part.Material = Convert.ToByte(material);
1540 group.HasGroupChanged = true; 1676 group.HasGroupChanged = true;
1677 remoteClient.SendPartPhysicsProprieties(part);
1541 } 1678 }
1542 } 1679 }
1543 } 1680 }
@@ -1602,6 +1739,12 @@ namespace OpenSim.Region.Framework.Scenes
1602 /// <param name="childPrims"></param> 1739 /// <param name="childPrims"></param>
1603 protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children) 1740 protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children)
1604 { 1741 {
1742 if (root.KeyframeMotion != null)
1743 {
1744 root.KeyframeMotion.Stop();
1745 root.KeyframeMotion = null;
1746 }
1747
1605 SceneObjectGroup parentGroup = root.ParentGroup; 1748 SceneObjectGroup parentGroup = root.ParentGroup;
1606 if (parentGroup == null) return; 1749 if (parentGroup == null) return;
1607 1750
@@ -1610,8 +1753,11 @@ namespace OpenSim.Region.Framework.Scenes
1610 return; 1753 return;
1611 1754
1612 Monitor.Enter(m_updateLock); 1755 Monitor.Enter(m_updateLock);
1756
1613 try 1757 try
1614 { 1758 {
1759 parentGroup.areUpdatesSuspended = true;
1760
1615 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); 1761 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>();
1616 1762
1617 // We do this in reverse to get the link order of the prims correct 1763 // We do this in reverse to get the link order of the prims correct
@@ -1626,9 +1772,13 @@ namespace OpenSim.Region.Framework.Scenes
1626 // Make sure no child prim is set for sale 1772 // Make sure no child prim is set for sale
1627 // So that, on delink, no prims are unwittingly 1773 // So that, on delink, no prims are unwittingly
1628 // left for sale and sold off 1774 // left for sale and sold off
1629 child.RootPart.ObjectSaleType = 0; 1775
1630 child.RootPart.SalePrice = 10; 1776 if (child != null)
1631 childGroups.Add(child); 1777 {
1778 child.RootPart.ObjectSaleType = 0;
1779 child.RootPart.SalePrice = 10;
1780 childGroups.Add(child);
1781 }
1632 } 1782 }
1633 1783
1634 foreach (SceneObjectGroup child in childGroups) 1784 foreach (SceneObjectGroup child in childGroups)
@@ -1655,6 +1805,16 @@ namespace OpenSim.Region.Framework.Scenes
1655 } 1805 }
1656 finally 1806 finally
1657 { 1807 {
1808 lock (SceneObjectGroupsByLocalPartID)
1809 {
1810 foreach (SceneObjectPart part in parentGroup.Parts)
1811 SceneObjectGroupsByLocalPartID[part.LocalId] = parentGroup;
1812 }
1813
1814 parentGroup.areUpdatesSuspended = false;
1815 parentGroup.HasGroupChanged = true;
1816 parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true);
1817 parentGroup.ScheduleGroupForFullUpdate();
1658 Monitor.Exit(m_updateLock); 1818 Monitor.Exit(m_updateLock);
1659 } 1819 }
1660 } 1820 }
@@ -1677,6 +1837,11 @@ namespace OpenSim.Region.Framework.Scenes
1677 { 1837 {
1678 if (part != null) 1838 if (part != null)
1679 { 1839 {
1840 if (part.KeyframeMotion != null)
1841 {
1842 part.KeyframeMotion.Stop();
1843 part.KeyframeMotion = null;
1844 }
1680 if (part.ParentGroup.PrimCount != 1) // Skip single 1845 if (part.ParentGroup.PrimCount != 1) // Skip single
1681 { 1846 {
1682 if (part.LinkNum < 2) // Root 1847 if (part.LinkNum < 2) // Root
@@ -1691,21 +1856,24 @@ namespace OpenSim.Region.Framework.Scenes
1691 1856
1692 SceneObjectGroup group = part.ParentGroup; 1857 SceneObjectGroup group = part.ParentGroup;
1693 if (!affectedGroups.Contains(group)) 1858 if (!affectedGroups.Contains(group))
1859 {
1860 group.areUpdatesSuspended = true;
1694 affectedGroups.Add(group); 1861 affectedGroups.Add(group);
1862 }
1695 } 1863 }
1696 } 1864 }
1697 } 1865 }
1698 1866
1699 foreach (SceneObjectPart child in childParts) 1867 if (childParts.Count > 0)
1700 { 1868 {
1701 // Unlink all child parts from their groups 1869 foreach (SceneObjectPart child in childParts)
1702 // 1870 {
1703 child.ParentGroup.DelinkFromGroup(child, true); 1871 // Unlink all child parts from their groups
1704 1872 //
1705 // These are not in affected groups and will not be 1873 child.ParentGroup.DelinkFromGroup(child, true);
1706 // handled further. Do the honors here. 1874 child.ParentGroup.HasGroupChanged = true;
1707 child.ParentGroup.HasGroupChanged = true; 1875 child.ParentGroup.ScheduleGroupForFullUpdate();
1708 child.ParentGroup.ScheduleGroupForFullUpdate(); 1876 }
1709 } 1877 }
1710 1878
1711 foreach (SceneObjectPart root in rootParts) 1879 foreach (SceneObjectPart root in rootParts)
@@ -1715,56 +1883,68 @@ namespace OpenSim.Region.Framework.Scenes
1715 // However, editing linked parts and unlinking may be different 1883 // However, editing linked parts and unlinking may be different
1716 // 1884 //
1717 SceneObjectGroup group = root.ParentGroup; 1885 SceneObjectGroup group = root.ParentGroup;
1886 group.areUpdatesSuspended = true;
1718 1887
1719 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); 1888 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts);
1720 int numChildren = newSet.Count; 1889 int numChildren = newSet.Count;
1721 1890
1891 if (numChildren == 1)
1892 break;
1893
1722 // If there are prims left in a link set, but the root is 1894 // If there are prims left in a link set, but the root is
1723 // slated for unlink, we need to do this 1895 // slated for unlink, we need to do this
1896 // Unlink the remaining set
1724 // 1897 //
1725 if (numChildren != 1) 1898 bool sendEventsToRemainder = true;
1726 { 1899 if (numChildren > 1)
1727 // Unlink the remaining set 1900 sendEventsToRemainder = false;
1728 //
1729 bool sendEventsToRemainder = true;
1730 if (numChildren > 1)
1731 sendEventsToRemainder = false;
1732 1901
1733 foreach (SceneObjectPart p in newSet) 1902 foreach (SceneObjectPart p in newSet)
1903 {
1904 if (p != group.RootPart)
1734 { 1905 {
1735 if (p != group.RootPart) 1906 group.DelinkFromGroup(p, sendEventsToRemainder);
1736 group.DelinkFromGroup(p, sendEventsToRemainder); 1907 if (numChildren > 2)
1908 {
1909 p.ParentGroup.areUpdatesSuspended = true;
1910 }
1911 else
1912 {
1913 p.ParentGroup.HasGroupChanged = true;
1914 p.ParentGroup.ScheduleGroupForFullUpdate();
1915 }
1737 } 1916 }
1917 }
1918
1919 // If there is more than one prim remaining, we
1920 // need to re-link
1921 //
1922 if (numChildren > 2)
1923 {
1924 // Remove old root
1925 //
1926 if (newSet.Contains(root))
1927 newSet.Remove(root);
1738 1928
1739 // If there is more than one prim remaining, we 1929 // Preserve link ordering
1740 // need to re-link
1741 // 1930 //
1742 if (numChildren > 2) 1931 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1743 { 1932 {
1744 // Remove old root 1933 return a.LinkNum.CompareTo(b.LinkNum);
1745 // 1934 });
1746 if (newSet.Contains(root))
1747 newSet.Remove(root);
1748
1749 // Preserve link ordering
1750 //
1751 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1752 {
1753 return a.LinkNum.CompareTo(b.LinkNum);
1754 });
1755 1935
1756 // Determine new root 1936 // Determine new root
1757 // 1937 //
1758 SceneObjectPart newRoot = newSet[0]; 1938 SceneObjectPart newRoot = newSet[0];
1759 newSet.RemoveAt(0); 1939 newSet.RemoveAt(0);
1760 1940
1761 foreach (SceneObjectPart newChild in newSet) 1941 foreach (SceneObjectPart newChild in newSet)
1762 newChild.ClearUpdateSchedule(); 1942 newChild.ClearUpdateSchedule();
1763 1943
1764 LinkObjects(newRoot, newSet); 1944 newRoot.ParentGroup.areUpdatesSuspended = true;
1765 if (!affectedGroups.Contains(newRoot.ParentGroup)) 1945 LinkObjects(newRoot, newSet);
1766 affectedGroups.Add(newRoot.ParentGroup); 1946 if (!affectedGroups.Contains(newRoot.ParentGroup))
1767 } 1947 affectedGroups.Add(newRoot.ParentGroup);
1768 } 1948 }
1769 } 1949 }
1770 1950
@@ -1772,8 +1952,14 @@ namespace OpenSim.Region.Framework.Scenes
1772 // 1952 //
1773 foreach (SceneObjectGroup g in affectedGroups) 1953 foreach (SceneObjectGroup g in affectedGroups)
1774 { 1954 {
1955 // Child prims that have been unlinked and deleted will
1956 // return unless the root is deleted. This will remove them
1957 // from the database. They will be rewritten immediately,
1958 // minus the rows for the unlinked child prims.
1959 m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID);
1775 g.TriggerScriptChangedEvent(Changed.LINK); 1960 g.TriggerScriptChangedEvent(Changed.LINK);
1776 g.HasGroupChanged = true; // Persist 1961 g.HasGroupChanged = true; // Persist
1962 g.areUpdatesSuspended = false;
1777 g.ScheduleGroupForFullUpdate(); 1963 g.ScheduleGroupForFullUpdate();
1778 } 1964 }
1779 } 1965 }
@@ -1875,9 +2061,6 @@ namespace OpenSim.Region.Framework.Scenes
1875 child.ApplyNextOwnerPermissions(); 2061 child.ApplyNextOwnerPermissions();
1876 } 2062 }
1877 } 2063 }
1878
1879 copy.RootPart.ObjectSaleType = 0;
1880 copy.RootPart.SalePrice = 10;
1881 } 2064 }
1882 2065
1883 // FIXME: This section needs to be refactored so that it just calls AddSceneObject() 2066 // FIXME: This section needs to be refactored so that it just calls AddSceneObject()