diff options
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/SceneGraph.cs')
-rw-r--r-- | OpenSim/Region/Framework/Scenes/SceneGraph.cs | 293 |
1 files changed, 238 insertions, 55 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 0098add..cd4bd42 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(); |
@@ -337,6 +379,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
337 | /// </returns> | 379 | /// </returns> |
338 | protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) | 380 | protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) |
339 | { | 381 | { |
382 | if (sceneObject == null) | ||
383 | { | ||
384 | m_log.ErrorFormat("[SCENEGRAPH]: Tried to add null scene object"); | ||
385 | return false; | ||
386 | } | ||
340 | if (sceneObject.UUID == UUID.Zero) | 387 | if (sceneObject.UUID == UUID.Zero) |
341 | { | 388 | { |
342 | m_log.ErrorFormat( | 389 | m_log.ErrorFormat( |
@@ -471,6 +518,30 @@ namespace OpenSim.Region.Framework.Scenes | |||
471 | m_updateList[obj.UUID] = obj; | 518 | m_updateList[obj.UUID] = obj; |
472 | } | 519 | } |
473 | 520 | ||
521 | public void FireAttachToBackup(SceneObjectGroup obj) | ||
522 | { | ||
523 | if (OnAttachToBackup != null) | ||
524 | { | ||
525 | OnAttachToBackup(obj); | ||
526 | } | ||
527 | } | ||
528 | |||
529 | public void FireDetachFromBackup(SceneObjectGroup obj) | ||
530 | { | ||
531 | if (OnDetachFromBackup != null) | ||
532 | { | ||
533 | OnDetachFromBackup(obj); | ||
534 | } | ||
535 | } | ||
536 | |||
537 | public void FireChangeBackup(SceneObjectGroup obj) | ||
538 | { | ||
539 | if (OnChangeBackup != null) | ||
540 | { | ||
541 | OnChangeBackup(obj); | ||
542 | } | ||
543 | } | ||
544 | |||
474 | /// <summary> | 545 | /// <summary> |
475 | /// Process all pending updates | 546 | /// Process all pending updates |
476 | /// </summary> | 547 | /// </summary> |
@@ -588,7 +659,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
588 | 659 | ||
589 | Entities[presence.UUID] = presence; | 660 | Entities[presence.UUID] = presence; |
590 | 661 | ||
591 | lock (m_presenceLock) | 662 | m_scenePresencesLock.EnterWriteLock(); |
663 | try | ||
592 | { | 664 | { |
593 | Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); | 665 | Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); |
594 | List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); | 666 | List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); |
@@ -612,6 +684,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
612 | m_scenePresenceMap = newmap; | 684 | m_scenePresenceMap = newmap; |
613 | m_scenePresenceArray = newlist; | 685 | m_scenePresenceArray = newlist; |
614 | } | 686 | } |
687 | finally | ||
688 | { | ||
689 | m_scenePresencesLock.ExitWriteLock(); | ||
690 | } | ||
615 | } | 691 | } |
616 | 692 | ||
617 | /// <summary> | 693 | /// <summary> |
@@ -626,7 +702,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
626 | agentID); | 702 | agentID); |
627 | } | 703 | } |
628 | 704 | ||
629 | lock (m_presenceLock) | 705 | m_scenePresencesLock.EnterWriteLock(); |
706 | try | ||
630 | { | 707 | { |
631 | Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); | 708 | Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); |
632 | List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); | 709 | List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); |
@@ -648,6 +725,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
648 | m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); | 725 | m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); |
649 | } | 726 | } |
650 | } | 727 | } |
728 | finally | ||
729 | { | ||
730 | m_scenePresencesLock.ExitWriteLock(); | ||
731 | } | ||
651 | } | 732 | } |
652 | 733 | ||
653 | protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) | 734 | protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) |
@@ -1180,6 +1261,25 @@ namespace OpenSim.Region.Framework.Scenes | |||
1180 | 1261 | ||
1181 | #region Client Event handlers | 1262 | #region Client Event handlers |
1182 | 1263 | ||
1264 | protected internal void ClientChangeObject(uint localID, object odata, IClientAPI remoteClient) | ||
1265 | { | ||
1266 | SceneObjectPart part = GetSceneObjectPart(localID); | ||
1267 | ObjectChangeData data = (ObjectChangeData)odata; | ||
1268 | |||
1269 | if (part != null) | ||
1270 | { | ||
1271 | SceneObjectGroup grp = part.ParentGroup; | ||
1272 | if (grp != null) | ||
1273 | { | ||
1274 | if (m_parentScene.Permissions.CanEditObject(grp.UUID, remoteClient.AgentId)) | ||
1275 | { | ||
1276 | part.StoreUndoState(data.change); // lets test only saving what we changed | ||
1277 | grp.doChangeObject(part, (ObjectChangeData)data); | ||
1278 | } | ||
1279 | } | ||
1280 | } | ||
1281 | } | ||
1282 | |||
1183 | /// <summary> | 1283 | /// <summary> |
1184 | /// Update the scale of an individual prim. | 1284 | /// Update the scale of an individual prim. |
1185 | /// </summary> | 1285 | /// </summary> |
@@ -1194,7 +1294,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
1194 | { | 1294 | { |
1195 | if (m_parentScene.Permissions.CanEditObject(part.ParentGroup.UUID, remoteClient.AgentId)) | 1295 | if (m_parentScene.Permissions.CanEditObject(part.ParentGroup.UUID, remoteClient.AgentId)) |
1196 | { | 1296 | { |
1297 | bool physbuild = false; | ||
1298 | if (part.ParentGroup.RootPart.PhysActor != null) | ||
1299 | { | ||
1300 | part.ParentGroup.RootPart.PhysActor.Building = true; | ||
1301 | physbuild = true; | ||
1302 | } | ||
1303 | |||
1197 | part.Resize(scale); | 1304 | part.Resize(scale); |
1305 | |||
1306 | if (physbuild) | ||
1307 | part.ParentGroup.RootPart.PhysActor.Building = false; | ||
1198 | } | 1308 | } |
1199 | } | 1309 | } |
1200 | } | 1310 | } |
@@ -1206,7 +1316,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
1206 | { | 1316 | { |
1207 | if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) | 1317 | if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) |
1208 | { | 1318 | { |
1319 | bool physbuild = false; | ||
1320 | if (group.RootPart.PhysActor != null) | ||
1321 | { | ||
1322 | group.RootPart.PhysActor.Building = true; | ||
1323 | physbuild = true; | ||
1324 | } | ||
1325 | |||
1209 | group.GroupResize(scale); | 1326 | group.GroupResize(scale); |
1327 | |||
1328 | if (physbuild) | ||
1329 | group.RootPart.PhysActor.Building = false; | ||
1210 | } | 1330 | } |
1211 | } | 1331 | } |
1212 | } | 1332 | } |
@@ -1334,8 +1454,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
1334 | { | 1454 | { |
1335 | if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) | 1455 | if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) |
1336 | { | 1456 | { |
1337 | if (m_parentScene.AttachmentsModule != null) | 1457 | // Set the new attachment point data in the object |
1338 | m_parentScene.AttachmentsModule.UpdateAttachmentPosition(group, pos); | 1458 | byte attachmentPoint = group.GetAttachmentPoint(); |
1459 | group.UpdateGroupPosition(pos); | ||
1460 | group.IsAttachment = false; | ||
1461 | group.AbsolutePosition = group.RootPart.AttachedPos; | ||
1462 | group.AttachmentPoint = attachmentPoint; | ||
1463 | group.HasGroupChanged = true; | ||
1339 | } | 1464 | } |
1340 | else | 1465 | else |
1341 | { | 1466 | { |
@@ -1383,7 +1508,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1383 | /// <param name="SetPhantom"></param> | 1508 | /// <param name="SetPhantom"></param> |
1384 | /// <param name="remoteClient"></param> | 1509 | /// <param name="remoteClient"></param> |
1385 | protected internal void UpdatePrimFlags( | 1510 | protected internal void UpdatePrimFlags( |
1386 | uint localID, bool UsePhysics, bool SetTemporary, bool SetPhantom, IClientAPI remoteClient) | 1511 | uint localID, bool UsePhysics, bool SetTemporary, bool SetPhantom, ExtraPhysicsData PhysData, IClientAPI remoteClient) |
1387 | { | 1512 | { |
1388 | SceneObjectGroup group = GetGroupByPrim(localID); | 1513 | SceneObjectGroup group = GetGroupByPrim(localID); |
1389 | if (group != null) | 1514 | if (group != null) |
@@ -1391,7 +1516,18 @@ namespace OpenSim.Region.Framework.Scenes | |||
1391 | if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) | 1516 | if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) |
1392 | { | 1517 | { |
1393 | // VolumeDetect can't be set via UI and will always be off when a change is made there | 1518 | // VolumeDetect can't be set via UI and will always be off when a change is made there |
1394 | group.UpdatePrimFlags(localID, UsePhysics, SetTemporary, SetPhantom, false); | 1519 | if (PhysData.PhysShapeType == PhysShapeType.invalid) |
1520 | group.UpdatePrimFlags(localID, UsePhysics, SetTemporary, SetPhantom, false); | ||
1521 | else | ||
1522 | { | ||
1523 | SceneObjectPart part = GetSceneObjectPart(localID); | ||
1524 | if (part != null) | ||
1525 | { | ||
1526 | part.UpdateExtraPhysics(PhysData); | ||
1527 | if (part.UpdatePhysRequired) | ||
1528 | remoteClient.SendPartPhysicsProprieties(part); | ||
1529 | } | ||
1530 | } | ||
1395 | } | 1531 | } |
1396 | } | 1532 | } |
1397 | } | 1533 | } |
@@ -1535,6 +1671,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1535 | { | 1671 | { |
1536 | part.Material = Convert.ToByte(material); | 1672 | part.Material = Convert.ToByte(material); |
1537 | group.HasGroupChanged = true; | 1673 | group.HasGroupChanged = true; |
1674 | remoteClient.SendPartPhysicsProprieties(part); | ||
1538 | } | 1675 | } |
1539 | } | 1676 | } |
1540 | } | 1677 | } |
@@ -1599,6 +1736,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
1599 | /// <param name="childPrims"></param> | 1736 | /// <param name="childPrims"></param> |
1600 | protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children) | 1737 | protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children) |
1601 | { | 1738 | { |
1739 | if (root.KeyframeMotion != null) | ||
1740 | { | ||
1741 | root.KeyframeMotion.Stop(); | ||
1742 | root.KeyframeMotion = null; | ||
1743 | } | ||
1744 | |||
1602 | SceneObjectGroup parentGroup = root.ParentGroup; | 1745 | SceneObjectGroup parentGroup = root.ParentGroup; |
1603 | if (parentGroup == null) return; | 1746 | if (parentGroup == null) return; |
1604 | 1747 | ||
@@ -1607,8 +1750,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
1607 | return; | 1750 | return; |
1608 | 1751 | ||
1609 | Monitor.Enter(m_updateLock); | 1752 | Monitor.Enter(m_updateLock); |
1753 | |||
1610 | try | 1754 | try |
1611 | { | 1755 | { |
1756 | parentGroup.areUpdatesSuspended = true; | ||
1757 | |||
1612 | List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); | 1758 | List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); |
1613 | 1759 | ||
1614 | // We do this in reverse to get the link order of the prims correct | 1760 | // We do this in reverse to get the link order of the prims correct |
@@ -1623,9 +1769,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
1623 | // Make sure no child prim is set for sale | 1769 | // Make sure no child prim is set for sale |
1624 | // So that, on delink, no prims are unwittingly | 1770 | // So that, on delink, no prims are unwittingly |
1625 | // left for sale and sold off | 1771 | // left for sale and sold off |
1626 | child.RootPart.ObjectSaleType = 0; | 1772 | |
1627 | child.RootPart.SalePrice = 10; | 1773 | if (child != null) |
1628 | childGroups.Add(child); | 1774 | { |
1775 | child.RootPart.ObjectSaleType = 0; | ||
1776 | child.RootPart.SalePrice = 10; | ||
1777 | childGroups.Add(child); | ||
1778 | } | ||
1629 | } | 1779 | } |
1630 | 1780 | ||
1631 | foreach (SceneObjectGroup child in childGroups) | 1781 | foreach (SceneObjectGroup child in childGroups) |
@@ -1652,6 +1802,16 @@ namespace OpenSim.Region.Framework.Scenes | |||
1652 | } | 1802 | } |
1653 | finally | 1803 | finally |
1654 | { | 1804 | { |
1805 | lock (SceneObjectGroupsByLocalPartID) | ||
1806 | { | ||
1807 | foreach (SceneObjectPart part in parentGroup.Parts) | ||
1808 | SceneObjectGroupsByLocalPartID[part.LocalId] = parentGroup; | ||
1809 | } | ||
1810 | |||
1811 | parentGroup.areUpdatesSuspended = false; | ||
1812 | parentGroup.HasGroupChanged = true; | ||
1813 | parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true); | ||
1814 | parentGroup.ScheduleGroupForFullUpdate(); | ||
1655 | Monitor.Exit(m_updateLock); | 1815 | Monitor.Exit(m_updateLock); |
1656 | } | 1816 | } |
1657 | } | 1817 | } |
@@ -1674,6 +1834,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
1674 | { | 1834 | { |
1675 | if (part != null) | 1835 | if (part != null) |
1676 | { | 1836 | { |
1837 | if (part.KeyframeMotion != null) | ||
1838 | { | ||
1839 | part.KeyframeMotion.Stop(); | ||
1840 | part.KeyframeMotion = null; | ||
1841 | } | ||
1677 | if (part.ParentGroup.PrimCount != 1) // Skip single | 1842 | if (part.ParentGroup.PrimCount != 1) // Skip single |
1678 | { | 1843 | { |
1679 | if (part.LinkNum < 2) // Root | 1844 | if (part.LinkNum < 2) // Root |
@@ -1688,21 +1853,24 @@ namespace OpenSim.Region.Framework.Scenes | |||
1688 | 1853 | ||
1689 | SceneObjectGroup group = part.ParentGroup; | 1854 | SceneObjectGroup group = part.ParentGroup; |
1690 | if (!affectedGroups.Contains(group)) | 1855 | if (!affectedGroups.Contains(group)) |
1856 | { | ||
1857 | group.areUpdatesSuspended = true; | ||
1691 | affectedGroups.Add(group); | 1858 | affectedGroups.Add(group); |
1859 | } | ||
1692 | } | 1860 | } |
1693 | } | 1861 | } |
1694 | } | 1862 | } |
1695 | 1863 | ||
1696 | foreach (SceneObjectPart child in childParts) | 1864 | if (childParts.Count > 0) |
1697 | { | 1865 | { |
1698 | // Unlink all child parts from their groups | 1866 | foreach (SceneObjectPart child in childParts) |
1699 | // | 1867 | { |
1700 | child.ParentGroup.DelinkFromGroup(child, true); | 1868 | // Unlink all child parts from their groups |
1701 | 1869 | // | |
1702 | // These are not in affected groups and will not be | 1870 | child.ParentGroup.DelinkFromGroup(child, true); |
1703 | // handled further. Do the honors here. | 1871 | child.ParentGroup.HasGroupChanged = true; |
1704 | child.ParentGroup.HasGroupChanged = true; | 1872 | child.ParentGroup.ScheduleGroupForFullUpdate(); |
1705 | child.ParentGroup.ScheduleGroupForFullUpdate(); | 1873 | } |
1706 | } | 1874 | } |
1707 | 1875 | ||
1708 | foreach (SceneObjectPart root in rootParts) | 1876 | foreach (SceneObjectPart root in rootParts) |
@@ -1712,56 +1880,68 @@ namespace OpenSim.Region.Framework.Scenes | |||
1712 | // However, editing linked parts and unlinking may be different | 1880 | // However, editing linked parts and unlinking may be different |
1713 | // | 1881 | // |
1714 | SceneObjectGroup group = root.ParentGroup; | 1882 | SceneObjectGroup group = root.ParentGroup; |
1883 | group.areUpdatesSuspended = true; | ||
1715 | 1884 | ||
1716 | List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); | 1885 | List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); |
1717 | int numChildren = newSet.Count; | 1886 | int numChildren = newSet.Count; |
1718 | 1887 | ||
1888 | if (numChildren == 1) | ||
1889 | break; | ||
1890 | |||
1719 | // If there are prims left in a link set, but the root is | 1891 | // If there are prims left in a link set, but the root is |
1720 | // slated for unlink, we need to do this | 1892 | // slated for unlink, we need to do this |
1893 | // Unlink the remaining set | ||
1721 | // | 1894 | // |
1722 | if (numChildren != 1) | 1895 | bool sendEventsToRemainder = true; |
1723 | { | 1896 | if (numChildren > 1) |
1724 | // Unlink the remaining set | 1897 | sendEventsToRemainder = false; |
1725 | // | ||
1726 | bool sendEventsToRemainder = true; | ||
1727 | if (numChildren > 1) | ||
1728 | sendEventsToRemainder = false; | ||
1729 | 1898 | ||
1730 | foreach (SceneObjectPart p in newSet) | 1899 | foreach (SceneObjectPart p in newSet) |
1900 | { | ||
1901 | if (p != group.RootPart) | ||
1731 | { | 1902 | { |
1732 | if (p != group.RootPart) | 1903 | group.DelinkFromGroup(p, sendEventsToRemainder); |
1733 | group.DelinkFromGroup(p, sendEventsToRemainder); | 1904 | if (numChildren > 2) |
1905 | { | ||
1906 | p.ParentGroup.areUpdatesSuspended = true; | ||
1907 | } | ||
1908 | else | ||
1909 | { | ||
1910 | p.ParentGroup.HasGroupChanged = true; | ||
1911 | p.ParentGroup.ScheduleGroupForFullUpdate(); | ||
1912 | } | ||
1734 | } | 1913 | } |
1914 | } | ||
1915 | |||
1916 | // If there is more than one prim remaining, we | ||
1917 | // need to re-link | ||
1918 | // | ||
1919 | if (numChildren > 2) | ||
1920 | { | ||
1921 | // Remove old root | ||
1922 | // | ||
1923 | if (newSet.Contains(root)) | ||
1924 | newSet.Remove(root); | ||
1735 | 1925 | ||
1736 | // If there is more than one prim remaining, we | 1926 | // Preserve link ordering |
1737 | // need to re-link | ||
1738 | // | 1927 | // |
1739 | if (numChildren > 2) | 1928 | newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b) |
1740 | { | 1929 | { |
1741 | // Remove old root | 1930 | return a.LinkNum.CompareTo(b.LinkNum); |
1742 | // | 1931 | }); |
1743 | if (newSet.Contains(root)) | ||
1744 | newSet.Remove(root); | ||
1745 | |||
1746 | // Preserve link ordering | ||
1747 | // | ||
1748 | newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b) | ||
1749 | { | ||
1750 | return a.LinkNum.CompareTo(b.LinkNum); | ||
1751 | }); | ||
1752 | 1932 | ||
1753 | // Determine new root | 1933 | // Determine new root |
1754 | // | 1934 | // |
1755 | SceneObjectPart newRoot = newSet[0]; | 1935 | SceneObjectPart newRoot = newSet[0]; |
1756 | newSet.RemoveAt(0); | 1936 | newSet.RemoveAt(0); |
1757 | 1937 | ||
1758 | foreach (SceneObjectPart newChild in newSet) | 1938 | foreach (SceneObjectPart newChild in newSet) |
1759 | newChild.ClearUpdateSchedule(); | 1939 | newChild.ClearUpdateSchedule(); |
1760 | 1940 | ||
1761 | LinkObjects(newRoot, newSet); | 1941 | newRoot.ParentGroup.areUpdatesSuspended = true; |
1762 | if (!affectedGroups.Contains(newRoot.ParentGroup)) | 1942 | LinkObjects(newRoot, newSet); |
1763 | affectedGroups.Add(newRoot.ParentGroup); | 1943 | if (!affectedGroups.Contains(newRoot.ParentGroup)) |
1764 | } | 1944 | affectedGroups.Add(newRoot.ParentGroup); |
1765 | } | 1945 | } |
1766 | } | 1946 | } |
1767 | 1947 | ||
@@ -1769,8 +1949,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
1769 | // | 1949 | // |
1770 | foreach (SceneObjectGroup g in affectedGroups) | 1950 | foreach (SceneObjectGroup g in affectedGroups) |
1771 | { | 1951 | { |
1952 | // Child prims that have been unlinked and deleted will | ||
1953 | // return unless the root is deleted. This will remove them | ||
1954 | // from the database. They will be rewritten immediately, | ||
1955 | // minus the rows for the unlinked child prims. | ||
1956 | m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID); | ||
1772 | g.TriggerScriptChangedEvent(Changed.LINK); | 1957 | g.TriggerScriptChangedEvent(Changed.LINK); |
1773 | g.HasGroupChanged = true; // Persist | 1958 | g.HasGroupChanged = true; // Persist |
1959 | g.areUpdatesSuspended = false; | ||
1774 | g.ScheduleGroupForFullUpdate(); | 1960 | g.ScheduleGroupForFullUpdate(); |
1775 | } | 1961 | } |
1776 | } | 1962 | } |
@@ -1872,9 +2058,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
1872 | child.ApplyNextOwnerPermissions(); | 2058 | child.ApplyNextOwnerPermissions(); |
1873 | } | 2059 | } |
1874 | } | 2060 | } |
1875 | |||
1876 | copy.RootPart.ObjectSaleType = 0; | ||
1877 | copy.RootPart.SalePrice = 10; | ||
1878 | } | 2061 | } |
1879 | 2062 | ||
1880 | // FIXME: This section needs to be refactored so that it just calls AddSceneObject() | 2063 | // FIXME: This section needs to be refactored so that it just calls AddSceneObject() |