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 5c542d6..ccc3f32 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)
@@ -1179,6 +1260,25 @@ namespace OpenSim.Region.Framework.Scenes
1179 1260
1180 #region Client Event handlers 1261 #region Client Event handlers
1181 1262
1263 protected internal void ClientChangeObject(uint localID, object odata, IClientAPI remoteClient)
1264 {
1265 SceneObjectPart part = GetSceneObjectPart(localID);
1266 ObjectChangeData data = (ObjectChangeData)odata;
1267
1268 if (part != null)
1269 {
1270 SceneObjectGroup grp = part.ParentGroup;
1271 if (grp != null)
1272 {
1273 if (m_parentScene.Permissions.CanEditObject(grp.UUID, remoteClient.AgentId))
1274 {
1275 part.StoreUndoState(data.change); // lets test only saving what we changed
1276 grp.doChangeObject(part, (ObjectChangeData)data);
1277 }
1278 }
1279 }
1280 }
1281
1182 /// <summary> 1282 /// <summary>
1183 /// Update the scale of an individual prim. 1283 /// Update the scale of an individual prim.
1184 /// </summary> 1284 /// </summary>
@@ -1193,7 +1293,17 @@ namespace OpenSim.Region.Framework.Scenes
1193 { 1293 {
1194 if (m_parentScene.Permissions.CanEditObject(part.ParentGroup.UUID, remoteClient.AgentId)) 1294 if (m_parentScene.Permissions.CanEditObject(part.ParentGroup.UUID, remoteClient.AgentId))
1195 { 1295 {
1296 bool physbuild = false;
1297 if (part.ParentGroup.RootPart.PhysActor != null)
1298 {
1299 part.ParentGroup.RootPart.PhysActor.Building = true;
1300 physbuild = true;
1301 }
1302
1196 part.Resize(scale); 1303 part.Resize(scale);
1304
1305 if (physbuild)
1306 part.ParentGroup.RootPart.PhysActor.Building = false;
1197 } 1307 }
1198 } 1308 }
1199 } 1309 }
@@ -1205,7 +1315,17 @@ namespace OpenSim.Region.Framework.Scenes
1205 { 1315 {
1206 if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) 1316 if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId))
1207 { 1317 {
1318 bool physbuild = false;
1319 if (group.RootPart.PhysActor != null)
1320 {
1321 group.RootPart.PhysActor.Building = true;
1322 physbuild = true;
1323 }
1324
1208 group.GroupResize(scale); 1325 group.GroupResize(scale);
1326
1327 if (physbuild)
1328 group.RootPart.PhysActor.Building = false;
1209 } 1329 }
1210 } 1330 }
1211 } 1331 }
@@ -1333,8 +1453,13 @@ namespace OpenSim.Region.Framework.Scenes
1333 { 1453 {
1334 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) 1454 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0))
1335 { 1455 {
1336 if (m_parentScene.AttachmentsModule != null) 1456 // Set the new attachment point data in the object
1337 m_parentScene.AttachmentsModule.UpdateAttachmentPosition(group, pos); 1457 byte attachmentPoint = group.GetAttachmentPoint();
1458 group.UpdateGroupPosition(pos);
1459 group.IsAttachment = false;
1460 group.AbsolutePosition = group.RootPart.AttachedPos;
1461 group.AttachmentPoint = attachmentPoint;
1462 group.HasGroupChanged = true;
1338 } 1463 }
1339 else 1464 else
1340 { 1465 {
@@ -1382,7 +1507,7 @@ namespace OpenSim.Region.Framework.Scenes
1382 /// <param name="SetPhantom"></param> 1507 /// <param name="SetPhantom"></param>
1383 /// <param name="remoteClient"></param> 1508 /// <param name="remoteClient"></param>
1384 protected internal void UpdatePrimFlags( 1509 protected internal void UpdatePrimFlags(
1385 uint localID, bool UsePhysics, bool SetTemporary, bool SetPhantom, IClientAPI remoteClient) 1510 uint localID, bool UsePhysics, bool SetTemporary, bool SetPhantom, ExtraPhysicsData PhysData, IClientAPI remoteClient)
1386 { 1511 {
1387 SceneObjectGroup group = GetGroupByPrim(localID); 1512 SceneObjectGroup group = GetGroupByPrim(localID);
1388 if (group != null) 1513 if (group != null)
@@ -1390,7 +1515,18 @@ namespace OpenSim.Region.Framework.Scenes
1390 if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) 1515 if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId))
1391 { 1516 {
1392 // VolumeDetect can't be set via UI and will always be off when a change is made there 1517 // VolumeDetect can't be set via UI and will always be off when a change is made there
1393 group.UpdatePrimFlags(localID, UsePhysics, SetTemporary, SetPhantom, false); 1518 if (PhysData.PhysShapeType == PhysShapeType.invalid)
1519 group.UpdatePrimFlags(localID, UsePhysics, SetTemporary, SetPhantom, false);
1520 else
1521 {
1522 SceneObjectPart part = GetSceneObjectPart(localID);
1523 if (part != null)
1524 {
1525 part.UpdateExtraPhysics(PhysData);
1526 if (part.UpdatePhysRequired)
1527 remoteClient.SendPartPhysicsProprieties(part);
1528 }
1529 }
1394 } 1530 }
1395 } 1531 }
1396 } 1532 }
@@ -1534,6 +1670,7 @@ namespace OpenSim.Region.Framework.Scenes
1534 { 1670 {
1535 part.Material = Convert.ToByte(material); 1671 part.Material = Convert.ToByte(material);
1536 group.HasGroupChanged = true; 1672 group.HasGroupChanged = true;
1673 remoteClient.SendPartPhysicsProprieties(part);
1537 } 1674 }
1538 } 1675 }
1539 } 1676 }
@@ -1598,6 +1735,12 @@ namespace OpenSim.Region.Framework.Scenes
1598 /// <param name="childPrims"></param> 1735 /// <param name="childPrims"></param>
1599 protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children) 1736 protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children)
1600 { 1737 {
1738 if (root.KeyframeMotion != null)
1739 {
1740 root.KeyframeMotion.Stop();
1741 root.KeyframeMotion = null;
1742 }
1743
1601 SceneObjectGroup parentGroup = root.ParentGroup; 1744 SceneObjectGroup parentGroup = root.ParentGroup;
1602 if (parentGroup == null) return; 1745 if (parentGroup == null) return;
1603 1746
@@ -1606,8 +1749,11 @@ namespace OpenSim.Region.Framework.Scenes
1606 return; 1749 return;
1607 1750
1608 Monitor.Enter(m_updateLock); 1751 Monitor.Enter(m_updateLock);
1752
1609 try 1753 try
1610 { 1754 {
1755 parentGroup.areUpdatesSuspended = true;
1756
1611 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); 1757 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>();
1612 1758
1613 // We do this in reverse to get the link order of the prims correct 1759 // We do this in reverse to get the link order of the prims correct
@@ -1622,9 +1768,13 @@ namespace OpenSim.Region.Framework.Scenes
1622 // Make sure no child prim is set for sale 1768 // Make sure no child prim is set for sale
1623 // So that, on delink, no prims are unwittingly 1769 // So that, on delink, no prims are unwittingly
1624 // left for sale and sold off 1770 // left for sale and sold off
1625 child.RootPart.ObjectSaleType = 0; 1771
1626 child.RootPart.SalePrice = 10; 1772 if (child != null)
1627 childGroups.Add(child); 1773 {
1774 child.RootPart.ObjectSaleType = 0;
1775 child.RootPart.SalePrice = 10;
1776 childGroups.Add(child);
1777 }
1628 } 1778 }
1629 1779
1630 foreach (SceneObjectGroup child in childGroups) 1780 foreach (SceneObjectGroup child in childGroups)
@@ -1651,6 +1801,16 @@ namespace OpenSim.Region.Framework.Scenes
1651 } 1801 }
1652 finally 1802 finally
1653 { 1803 {
1804 lock (SceneObjectGroupsByLocalPartID)
1805 {
1806 foreach (SceneObjectPart part in parentGroup.Parts)
1807 SceneObjectGroupsByLocalPartID[part.LocalId] = parentGroup;
1808 }
1809
1810 parentGroup.areUpdatesSuspended = false;
1811 parentGroup.HasGroupChanged = true;
1812 parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true);
1813 parentGroup.ScheduleGroupForFullUpdate();
1654 Monitor.Exit(m_updateLock); 1814 Monitor.Exit(m_updateLock);
1655 } 1815 }
1656 } 1816 }
@@ -1673,6 +1833,11 @@ namespace OpenSim.Region.Framework.Scenes
1673 { 1833 {
1674 if (part != null) 1834 if (part != null)
1675 { 1835 {
1836 if (part.KeyframeMotion != null)
1837 {
1838 part.KeyframeMotion.Stop();
1839 part.KeyframeMotion = null;
1840 }
1676 if (part.ParentGroup.PrimCount != 1) // Skip single 1841 if (part.ParentGroup.PrimCount != 1) // Skip single
1677 { 1842 {
1678 if (part.LinkNum < 2) // Root 1843 if (part.LinkNum < 2) // Root
@@ -1687,21 +1852,24 @@ namespace OpenSim.Region.Framework.Scenes
1687 1852
1688 SceneObjectGroup group = part.ParentGroup; 1853 SceneObjectGroup group = part.ParentGroup;
1689 if (!affectedGroups.Contains(group)) 1854 if (!affectedGroups.Contains(group))
1855 {
1856 group.areUpdatesSuspended = true;
1690 affectedGroups.Add(group); 1857 affectedGroups.Add(group);
1858 }
1691 } 1859 }
1692 } 1860 }
1693 } 1861 }
1694 1862
1695 foreach (SceneObjectPart child in childParts) 1863 if (childParts.Count > 0)
1696 { 1864 {
1697 // Unlink all child parts from their groups 1865 foreach (SceneObjectPart child in childParts)
1698 // 1866 {
1699 child.ParentGroup.DelinkFromGroup(child, true); 1867 // Unlink all child parts from their groups
1700 1868 //
1701 // These are not in affected groups and will not be 1869 child.ParentGroup.DelinkFromGroup(child, true);
1702 // handled further. Do the honors here. 1870 child.ParentGroup.HasGroupChanged = true;
1703 child.ParentGroup.HasGroupChanged = true; 1871 child.ParentGroup.ScheduleGroupForFullUpdate();
1704 child.ParentGroup.ScheduleGroupForFullUpdate(); 1872 }
1705 } 1873 }
1706 1874
1707 foreach (SceneObjectPart root in rootParts) 1875 foreach (SceneObjectPart root in rootParts)
@@ -1711,56 +1879,68 @@ namespace OpenSim.Region.Framework.Scenes
1711 // However, editing linked parts and unlinking may be different 1879 // However, editing linked parts and unlinking may be different
1712 // 1880 //
1713 SceneObjectGroup group = root.ParentGroup; 1881 SceneObjectGroup group = root.ParentGroup;
1882 group.areUpdatesSuspended = true;
1714 1883
1715 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); 1884 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts);
1716 int numChildren = newSet.Count; 1885 int numChildren = newSet.Count;
1717 1886
1887 if (numChildren == 1)
1888 break;
1889
1718 // If there are prims left in a link set, but the root is 1890 // If there are prims left in a link set, but the root is
1719 // slated for unlink, we need to do this 1891 // slated for unlink, we need to do this
1892 // Unlink the remaining set
1720 // 1893 //
1721 if (numChildren != 1) 1894 bool sendEventsToRemainder = true;
1722 { 1895 if (numChildren > 1)
1723 // Unlink the remaining set 1896 sendEventsToRemainder = false;
1724 //
1725 bool sendEventsToRemainder = true;
1726 if (numChildren > 1)
1727 sendEventsToRemainder = false;
1728 1897
1729 foreach (SceneObjectPart p in newSet) 1898 foreach (SceneObjectPart p in newSet)
1899 {
1900 if (p != group.RootPart)
1730 { 1901 {
1731 if (p != group.RootPart) 1902 group.DelinkFromGroup(p, sendEventsToRemainder);
1732 group.DelinkFromGroup(p, sendEventsToRemainder); 1903 if (numChildren > 2)
1904 {
1905 p.ParentGroup.areUpdatesSuspended = true;
1906 }
1907 else
1908 {
1909 p.ParentGroup.HasGroupChanged = true;
1910 p.ParentGroup.ScheduleGroupForFullUpdate();
1911 }
1733 } 1912 }
1913 }
1914
1915 // If there is more than one prim remaining, we
1916 // need to re-link
1917 //
1918 if (numChildren > 2)
1919 {
1920 // Remove old root
1921 //
1922 if (newSet.Contains(root))
1923 newSet.Remove(root);
1734 1924
1735 // If there is more than one prim remaining, we 1925 // Preserve link ordering
1736 // need to re-link
1737 // 1926 //
1738 if (numChildren > 2) 1927 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1739 { 1928 {
1740 // Remove old root 1929 return a.LinkNum.CompareTo(b.LinkNum);
1741 // 1930 });
1742 if (newSet.Contains(root))
1743 newSet.Remove(root);
1744
1745 // Preserve link ordering
1746 //
1747 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1748 {
1749 return a.LinkNum.CompareTo(b.LinkNum);
1750 });
1751 1931
1752 // Determine new root 1932 // Determine new root
1753 // 1933 //
1754 SceneObjectPart newRoot = newSet[0]; 1934 SceneObjectPart newRoot = newSet[0];
1755 newSet.RemoveAt(0); 1935 newSet.RemoveAt(0);
1756 1936
1757 foreach (SceneObjectPart newChild in newSet) 1937 foreach (SceneObjectPart newChild in newSet)
1758 newChild.ClearUpdateSchedule(); 1938 newChild.ClearUpdateSchedule();
1759 1939
1760 LinkObjects(newRoot, newSet); 1940 newRoot.ParentGroup.areUpdatesSuspended = true;
1761 if (!affectedGroups.Contains(newRoot.ParentGroup)) 1941 LinkObjects(newRoot, newSet);
1762 affectedGroups.Add(newRoot.ParentGroup); 1942 if (!affectedGroups.Contains(newRoot.ParentGroup))
1763 } 1943 affectedGroups.Add(newRoot.ParentGroup);
1764 } 1944 }
1765 } 1945 }
1766 1946
@@ -1768,8 +1948,14 @@ namespace OpenSim.Region.Framework.Scenes
1768 // 1948 //
1769 foreach (SceneObjectGroup g in affectedGroups) 1949 foreach (SceneObjectGroup g in affectedGroups)
1770 { 1950 {
1951 // Child prims that have been unlinked and deleted will
1952 // return unless the root is deleted. This will remove them
1953 // from the database. They will be rewritten immediately,
1954 // minus the rows for the unlinked child prims.
1955 m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID);
1771 g.TriggerScriptChangedEvent(Changed.LINK); 1956 g.TriggerScriptChangedEvent(Changed.LINK);
1772 g.HasGroupChanged = true; // Persist 1957 g.HasGroupChanged = true; // Persist
1958 g.areUpdatesSuspended = false;
1773 g.ScheduleGroupForFullUpdate(); 1959 g.ScheduleGroupForFullUpdate();
1774 } 1960 }
1775 } 1961 }
@@ -1871,9 +2057,6 @@ namespace OpenSim.Region.Framework.Scenes
1871 child.ApplyNextOwnerPermissions(); 2057 child.ApplyNextOwnerPermissions();
1872 } 2058 }
1873 } 2059 }
1874
1875 copy.RootPart.ObjectSaleType = 0;
1876 copy.RootPart.SalePrice = 10;
1877 } 2060 }
1878 2061
1879 // FIXME: This section needs to be refactored so that it just calls AddSceneObject() 2062 // FIXME: This section needs to be refactored so that it just calls AddSceneObject()