diff options
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/SceneGraph.cs')
-rw-r--r-- | OpenSim/Region/Framework/Scenes/SceneGraph.cs | 479 |
1 files changed, 342 insertions, 137 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index a4383fd..e599e90 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 | ||
@@ -127,13 +137,18 @@ namespace OpenSim.Region.Framework.Scenes | |||
127 | 137 | ||
128 | protected internal void Close() | 138 | protected internal void Close() |
129 | { | 139 | { |
130 | lock (m_presenceLock) | 140 | m_scenePresencesLock.EnterWriteLock(); |
141 | try | ||
131 | { | 142 | { |
132 | Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(); | 143 | Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(); |
133 | List<ScenePresence> newlist = new List<ScenePresence>(); | 144 | List<ScenePresence> newlist = new List<ScenePresence>(); |
134 | m_scenePresenceMap = newmap; | 145 | m_scenePresenceMap = newmap; |
135 | m_scenePresenceArray = newlist; | 146 | m_scenePresenceArray = newlist; |
136 | } | 147 | } |
148 | finally | ||
149 | { | ||
150 | m_scenePresencesLock.ExitWriteLock(); | ||
151 | } | ||
137 | 152 | ||
138 | lock (SceneObjectGroupsByFullID) | 153 | lock (SceneObjectGroupsByFullID) |
139 | SceneObjectGroupsByFullID.Clear(); | 154 | SceneObjectGroupsByFullID.Clear(); |
@@ -254,6 +269,33 @@ namespace OpenSim.Region.Framework.Scenes | |||
254 | protected internal bool AddRestoredSceneObject( | 269 | protected internal bool AddRestoredSceneObject( |
255 | SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) | 270 | SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) |
256 | { | 271 | { |
272 | if (!m_parentScene.CombineRegions) | ||
273 | { | ||
274 | // KF: Check for out-of-region, move inside and make static. | ||
275 | Vector3 npos = new Vector3(sceneObject.RootPart.GroupPosition.X, | ||
276 | sceneObject.RootPart.GroupPosition.Y, | ||
277 | sceneObject.RootPart.GroupPosition.Z); | ||
278 | 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 || | ||
279 | npos.X > Constants.RegionSize || | ||
280 | npos.Y > Constants.RegionSize)) | ||
281 | { | ||
282 | if (npos.X < 0.0) npos.X = 1.0f; | ||
283 | if (npos.Y < 0.0) npos.Y = 1.0f; | ||
284 | if (npos.Z < 0.0) npos.Z = 0.0f; | ||
285 | if (npos.X > Constants.RegionSize) npos.X = Constants.RegionSize - 1.0f; | ||
286 | if (npos.Y > Constants.RegionSize) npos.Y = Constants.RegionSize - 1.0f; | ||
287 | |||
288 | foreach (SceneObjectPart part in sceneObject.Parts) | ||
289 | { | ||
290 | part.GroupPosition = npos; | ||
291 | } | ||
292 | sceneObject.RootPart.Velocity = Vector3.Zero; | ||
293 | sceneObject.RootPart.AngularVelocity = Vector3.Zero; | ||
294 | sceneObject.RootPart.Acceleration = Vector3.Zero; | ||
295 | sceneObject.RootPart.Velocity = Vector3.Zero; | ||
296 | } | ||
297 | } | ||
298 | |||
257 | if (attachToBackup && (!alreadyPersisted)) | 299 | if (attachToBackup && (!alreadyPersisted)) |
258 | { | 300 | { |
259 | sceneObject.ForceInventoryPersistence(); | 301 | sceneObject.ForceInventoryPersistence(); |
@@ -317,9 +359,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
317 | if (pa != null && pa.IsPhysical && vel != Vector3.Zero) | 359 | if (pa != null && pa.IsPhysical && vel != Vector3.Zero) |
318 | { | 360 | { |
319 | sceneObject.RootPart.ApplyImpulse((vel * sceneObject.GetMass()), false); | 361 | sceneObject.RootPart.ApplyImpulse((vel * sceneObject.GetMass()), false); |
320 | sceneObject.Velocity = vel; | ||
321 | } | 362 | } |
322 | 363 | ||
323 | return true; | 364 | return true; |
324 | } | 365 | } |
325 | 366 | ||
@@ -344,6 +385,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
344 | /// </returns> | 385 | /// </returns> |
345 | protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) | 386 | protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) |
346 | { | 387 | { |
388 | if (sceneObject == null) | ||
389 | { | ||
390 | m_log.ErrorFormat("[SCENEGRAPH]: Tried to add null scene object"); | ||
391 | return false; | ||
392 | } | ||
347 | if (sceneObject.UUID == UUID.Zero) | 393 | if (sceneObject.UUID == UUID.Zero) |
348 | { | 394 | { |
349 | m_log.ErrorFormat( | 395 | m_log.ErrorFormat( |
@@ -475,6 +521,30 @@ namespace OpenSim.Region.Framework.Scenes | |||
475 | m_updateList[obj.UUID] = obj; | 521 | m_updateList[obj.UUID] = obj; |
476 | } | 522 | } |
477 | 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 | |||
478 | /// <summary> | 548 | /// <summary> |
479 | /// Process all pending updates | 549 | /// Process all pending updates |
480 | /// </summary> | 550 | /// </summary> |
@@ -519,12 +589,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
519 | 589 | ||
520 | protected internal void AddPhysicalPrim(int number) | 590 | protected internal void AddPhysicalPrim(int number) |
521 | { | 591 | { |
522 | m_physicalPrim++; | 592 | m_physicalPrim += number; |
523 | } | 593 | } |
524 | 594 | ||
525 | protected internal void RemovePhysicalPrim(int number) | 595 | protected internal void RemovePhysicalPrim(int number) |
526 | { | 596 | { |
527 | m_physicalPrim--; | 597 | m_physicalPrim -= number; |
528 | } | 598 | } |
529 | 599 | ||
530 | protected internal void AddToScriptLPS(int number) | 600 | protected internal void AddToScriptLPS(int number) |
@@ -592,7 +662,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
592 | 662 | ||
593 | Entities[presence.UUID] = presence; | 663 | Entities[presence.UUID] = presence; |
594 | 664 | ||
595 | lock (m_presenceLock) | 665 | m_scenePresencesLock.EnterWriteLock(); |
666 | try | ||
596 | { | 667 | { |
597 | Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); | 668 | Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); |
598 | List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); | 669 | List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); |
@@ -616,6 +687,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
616 | m_scenePresenceMap = newmap; | 687 | m_scenePresenceMap = newmap; |
617 | m_scenePresenceArray = newlist; | 688 | m_scenePresenceArray = newlist; |
618 | } | 689 | } |
690 | finally | ||
691 | { | ||
692 | m_scenePresencesLock.ExitWriteLock(); | ||
693 | } | ||
619 | } | 694 | } |
620 | 695 | ||
621 | /// <summary> | 696 | /// <summary> |
@@ -630,7 +705,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
630 | agentID); | 705 | agentID); |
631 | } | 706 | } |
632 | 707 | ||
633 | lock (m_presenceLock) | 708 | m_scenePresencesLock.EnterWriteLock(); |
709 | try | ||
634 | { | 710 | { |
635 | Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); | 711 | Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); |
636 | List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); | 712 | List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); |
@@ -652,6 +728,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
652 | 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); |
653 | } | 729 | } |
654 | } | 730 | } |
731 | finally | ||
732 | { | ||
733 | m_scenePresencesLock.ExitWriteLock(); | ||
734 | } | ||
655 | } | 735 | } |
656 | 736 | ||
657 | protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) | 737 | protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) |
@@ -1205,6 +1285,52 @@ namespace OpenSim.Region.Framework.Scenes | |||
1205 | 1285 | ||
1206 | #region Client Event handlers | 1286 | #region Client Event handlers |
1207 | 1287 | ||
1288 | protected internal void ClientChangeObject(uint localID, object odata, IClientAPI remoteClient) | ||
1289 | { | ||
1290 | SceneObjectPart part = GetSceneObjectPart(localID); | ||
1291 | ObjectChangeData data = (ObjectChangeData)odata; | ||
1292 | |||
1293 | if (part != null) | ||
1294 | { | ||
1295 | SceneObjectGroup grp = part.ParentGroup; | ||
1296 | if (grp != null) | ||
1297 | { | ||
1298 | if (m_parentScene.Permissions.CanEditObject(grp.UUID, remoteClient.AgentId)) | ||
1299 | { | ||
1300 | // These two are exceptions SL makes in the interpretation | ||
1301 | // of the change flags. Must check them here because otherwise | ||
1302 | // the group flag (see below) would be lost | ||
1303 | if (data.change == ObjectChangeType.groupS) | ||
1304 | data.change = ObjectChangeType.primS; | ||
1305 | if (data.change == ObjectChangeType.groupPS) | ||
1306 | data.change = ObjectChangeType.primPS; | ||
1307 | part.StoreUndoState(data.change); // lets test only saving what we changed | ||
1308 | grp.doChangeObject(part, (ObjectChangeData)data); | ||
1309 | } | ||
1310 | else | ||
1311 | { | ||
1312 | // Is this any kind of group operation? | ||
1313 | if ((data.change & ObjectChangeType.Group) != 0) | ||
1314 | { | ||
1315 | // Is a move and/or rotation requested? | ||
1316 | if ((data.change & (ObjectChangeType.Position | ObjectChangeType.Rotation)) != 0) | ||
1317 | { | ||
1318 | // Are we allowed to move it? | ||
1319 | if (m_parentScene.Permissions.CanMoveObject(grp.UUID, remoteClient.AgentId)) | ||
1320 | { | ||
1321 | // Strip all but move and rotation from request | ||
1322 | data.change &= (ObjectChangeType.Group | ObjectChangeType.Position | ObjectChangeType.Rotation); | ||
1323 | |||
1324 | part.StoreUndoState(data.change); | ||
1325 | grp.doChangeObject(part, (ObjectChangeData)data); | ||
1326 | } | ||
1327 | } | ||
1328 | } | ||
1329 | } | ||
1330 | } | ||
1331 | } | ||
1332 | } | ||
1333 | |||
1208 | /// <summary> | 1334 | /// <summary> |
1209 | /// Update the scale of an individual prim. | 1335 | /// Update the scale of an individual prim. |
1210 | /// </summary> | 1336 | /// </summary> |
@@ -1219,7 +1345,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
1219 | { | 1345 | { |
1220 | if (m_parentScene.Permissions.CanEditObject(part.ParentGroup.UUID, remoteClient.AgentId)) | 1346 | if (m_parentScene.Permissions.CanEditObject(part.ParentGroup.UUID, remoteClient.AgentId)) |
1221 | { | 1347 | { |
1348 | bool physbuild = false; | ||
1349 | if (part.ParentGroup.RootPart.PhysActor != null) | ||
1350 | { | ||
1351 | part.ParentGroup.RootPart.PhysActor.Building = true; | ||
1352 | physbuild = true; | ||
1353 | } | ||
1354 | |||
1222 | part.Resize(scale); | 1355 | part.Resize(scale); |
1356 | |||
1357 | if (physbuild) | ||
1358 | part.ParentGroup.RootPart.PhysActor.Building = false; | ||
1223 | } | 1359 | } |
1224 | } | 1360 | } |
1225 | } | 1361 | } |
@@ -1231,7 +1367,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
1231 | { | 1367 | { |
1232 | if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) | 1368 | if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) |
1233 | { | 1369 | { |
1370 | bool physbuild = false; | ||
1371 | if (group.RootPart.PhysActor != null) | ||
1372 | { | ||
1373 | group.RootPart.PhysActor.Building = true; | ||
1374 | physbuild = true; | ||
1375 | } | ||
1376 | |||
1234 | group.GroupResize(scale); | 1377 | group.GroupResize(scale); |
1378 | |||
1379 | if (physbuild) | ||
1380 | group.RootPart.PhysActor.Building = false; | ||
1235 | } | 1381 | } |
1236 | } | 1382 | } |
1237 | } | 1383 | } |
@@ -1359,8 +1505,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
1359 | { | 1505 | { |
1360 | if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) | 1506 | if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) |
1361 | { | 1507 | { |
1362 | if (m_parentScene.AttachmentsModule != null) | 1508 | // Set the new attachment point data in the object |
1363 | m_parentScene.AttachmentsModule.UpdateAttachmentPosition(group, pos); | 1509 | byte attachmentPoint = group.GetAttachmentPoint(); |
1510 | group.UpdateGroupPosition(pos); | ||
1511 | group.IsAttachment = false; | ||
1512 | group.AbsolutePosition = group.RootPart.AttachedPos; | ||
1513 | group.AttachmentPoint = attachmentPoint; | ||
1514 | group.HasGroupChanged = true; | ||
1364 | } | 1515 | } |
1365 | else | 1516 | else |
1366 | { | 1517 | { |
@@ -1408,7 +1559,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1408 | /// <param name="SetPhantom"></param> | 1559 | /// <param name="SetPhantom"></param> |
1409 | /// <param name="remoteClient"></param> | 1560 | /// <param name="remoteClient"></param> |
1410 | protected internal void UpdatePrimFlags( | 1561 | protected internal void UpdatePrimFlags( |
1411 | uint localID, bool UsePhysics, bool SetTemporary, bool SetPhantom, IClientAPI remoteClient) | 1562 | uint localID, bool UsePhysics, bool SetTemporary, bool SetPhantom, ExtraPhysicsData PhysData, IClientAPI remoteClient) |
1412 | { | 1563 | { |
1413 | SceneObjectGroup group = GetGroupByPrim(localID); | 1564 | SceneObjectGroup group = GetGroupByPrim(localID); |
1414 | if (group != null) | 1565 | if (group != null) |
@@ -1416,7 +1567,28 @@ namespace OpenSim.Region.Framework.Scenes | |||
1416 | if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) | 1567 | if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) |
1417 | { | 1568 | { |
1418 | // VolumeDetect can't be set via UI and will always be off when a change is made there | 1569 | // VolumeDetect can't be set via UI and will always be off when a change is made there |
1419 | group.UpdatePrimFlags(localID, UsePhysics, SetTemporary, SetPhantom, false); | 1570 | // now only change volume dtc if phantom off |
1571 | |||
1572 | if (PhysData.PhysShapeType == PhysShapeType.invalid) // check for extraPhysics data | ||
1573 | { | ||
1574 | bool vdtc; | ||
1575 | if (SetPhantom) // if phantom keep volumedtc | ||
1576 | vdtc = group.RootPart.VolumeDetectActive; | ||
1577 | else // else turn it off | ||
1578 | vdtc = false; | ||
1579 | |||
1580 | group.UpdatePrimFlags(localID, UsePhysics, SetTemporary, SetPhantom, vdtc); | ||
1581 | } | ||
1582 | else | ||
1583 | { | ||
1584 | SceneObjectPart part = GetSceneObjectPart(localID); | ||
1585 | if (part != null) | ||
1586 | { | ||
1587 | part.UpdateExtraPhysics(PhysData); | ||
1588 | if (part.UpdatePhysRequired) | ||
1589 | remoteClient.SendPartPhysicsProprieties(part); | ||
1590 | } | ||
1591 | } | ||
1420 | } | 1592 | } |
1421 | } | 1593 | } |
1422 | } | 1594 | } |
@@ -1560,6 +1732,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1560 | { | 1732 | { |
1561 | part.Material = Convert.ToByte(material); | 1733 | part.Material = Convert.ToByte(material); |
1562 | group.HasGroupChanged = true; | 1734 | group.HasGroupChanged = true; |
1735 | remoteClient.SendPartPhysicsProprieties(part); | ||
1563 | } | 1736 | } |
1564 | } | 1737 | } |
1565 | } | 1738 | } |
@@ -1624,6 +1797,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
1624 | /// <param name="childPrims"></param> | 1797 | /// <param name="childPrims"></param> |
1625 | protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children) | 1798 | protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children) |
1626 | { | 1799 | { |
1800 | if (root.KeyframeMotion != null) | ||
1801 | { | ||
1802 | root.KeyframeMotion.Stop(); | ||
1803 | root.KeyframeMotion = null; | ||
1804 | } | ||
1805 | |||
1627 | SceneObjectGroup parentGroup = root.ParentGroup; | 1806 | SceneObjectGroup parentGroup = root.ParentGroup; |
1628 | if (parentGroup == null) return; | 1807 | if (parentGroup == null) return; |
1629 | 1808 | ||
@@ -1632,8 +1811,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
1632 | return; | 1811 | return; |
1633 | 1812 | ||
1634 | Monitor.Enter(m_updateLock); | 1813 | Monitor.Enter(m_updateLock); |
1814 | |||
1635 | try | 1815 | try |
1636 | { | 1816 | { |
1817 | |||
1637 | List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); | 1818 | List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); |
1638 | 1819 | ||
1639 | // We do this in reverse to get the link order of the prims correct | 1820 | // We do this in reverse to get the link order of the prims correct |
@@ -1648,9 +1829,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
1648 | // Make sure no child prim is set for sale | 1829 | // Make sure no child prim is set for sale |
1649 | // So that, on delink, no prims are unwittingly | 1830 | // So that, on delink, no prims are unwittingly |
1650 | // left for sale and sold off | 1831 | // left for sale and sold off |
1651 | child.RootPart.ObjectSaleType = 0; | 1832 | |
1652 | child.RootPart.SalePrice = 10; | 1833 | if (child != null) |
1653 | childGroups.Add(child); | 1834 | { |
1835 | child.RootPart.ObjectSaleType = 0; | ||
1836 | child.RootPart.SalePrice = 10; | ||
1837 | childGroups.Add(child); | ||
1838 | } | ||
1654 | } | 1839 | } |
1655 | 1840 | ||
1656 | foreach (SceneObjectGroup child in childGroups) | 1841 | foreach (SceneObjectGroup child in childGroups) |
@@ -1679,6 +1864,16 @@ namespace OpenSim.Region.Framework.Scenes | |||
1679 | } | 1864 | } |
1680 | finally | 1865 | finally |
1681 | { | 1866 | { |
1867 | lock (SceneObjectGroupsByLocalPartID) | ||
1868 | { | ||
1869 | foreach (SceneObjectPart part in parentGroup.Parts) | ||
1870 | SceneObjectGroupsByLocalPartID[part.LocalId] = parentGroup; | ||
1871 | } | ||
1872 | |||
1873 | parentGroup.AdjustChildPrimPermissions(); | ||
1874 | parentGroup.HasGroupChanged = true; | ||
1875 | parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true); | ||
1876 | parentGroup.ScheduleGroupForFullUpdate(); | ||
1682 | Monitor.Exit(m_updateLock); | 1877 | Monitor.Exit(m_updateLock); |
1683 | } | 1878 | } |
1684 | } | 1879 | } |
@@ -1701,6 +1896,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
1701 | { | 1896 | { |
1702 | if (part != null) | 1897 | if (part != null) |
1703 | { | 1898 | { |
1899 | if (part.KeyframeMotion != null) | ||
1900 | { | ||
1901 | part.KeyframeMotion.Stop(); | ||
1902 | part.KeyframeMotion = null; | ||
1903 | } | ||
1704 | if (part.ParentGroup.PrimCount != 1) // Skip single | 1904 | if (part.ParentGroup.PrimCount != 1) // Skip single |
1705 | { | 1905 | { |
1706 | if (part.LinkNum < 2) // Root | 1906 | if (part.LinkNum < 2) // Root |
@@ -1715,21 +1915,23 @@ namespace OpenSim.Region.Framework.Scenes | |||
1715 | 1915 | ||
1716 | SceneObjectGroup group = part.ParentGroup; | 1916 | SceneObjectGroup group = part.ParentGroup; |
1717 | if (!affectedGroups.Contains(group)) | 1917 | if (!affectedGroups.Contains(group)) |
1918 | { | ||
1718 | affectedGroups.Add(group); | 1919 | affectedGroups.Add(group); |
1920 | } | ||
1719 | } | 1921 | } |
1720 | } | 1922 | } |
1721 | } | 1923 | } |
1722 | 1924 | ||
1723 | foreach (SceneObjectPart child in childParts) | 1925 | if (childParts.Count > 0) |
1724 | { | 1926 | { |
1725 | // Unlink all child parts from their groups | 1927 | foreach (SceneObjectPart child in childParts) |
1726 | // | 1928 | { |
1727 | child.ParentGroup.DelinkFromGroup(child, true); | 1929 | // Unlink all child parts from their groups |
1728 | 1930 | // | |
1729 | // These are not in affected groups and will not be | 1931 | child.ParentGroup.DelinkFromGroup(child, true); |
1730 | // handled further. Do the honors here. | 1932 | child.ParentGroup.HasGroupChanged = true; |
1731 | child.ParentGroup.HasGroupChanged = true; | 1933 | child.ParentGroup.ScheduleGroupForFullUpdate(); |
1732 | child.ParentGroup.ScheduleGroupForFullUpdate(); | 1934 | } |
1733 | } | 1935 | } |
1734 | 1936 | ||
1735 | foreach (SceneObjectPart root in rootParts) | 1937 | foreach (SceneObjectPart root in rootParts) |
@@ -1743,52 +1945,61 @@ namespace OpenSim.Region.Framework.Scenes | |||
1743 | List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); | 1945 | List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); |
1744 | int numChildren = newSet.Count; | 1946 | int numChildren = newSet.Count; |
1745 | 1947 | ||
1948 | if (numChildren == 1) | ||
1949 | break; | ||
1950 | |||
1746 | // If there are prims left in a link set, but the root is | 1951 | // If there are prims left in a link set, but the root is |
1747 | // slated for unlink, we need to do this | 1952 | // slated for unlink, we need to do this |
1953 | // Unlink the remaining set | ||
1748 | // | 1954 | // |
1749 | if (numChildren != 1) | 1955 | bool sendEventsToRemainder = true; |
1750 | { | 1956 | if (numChildren > 1) |
1751 | // Unlink the remaining set | 1957 | sendEventsToRemainder = false; |
1752 | // | ||
1753 | bool sendEventsToRemainder = true; | ||
1754 | if (numChildren > 1) | ||
1755 | sendEventsToRemainder = false; | ||
1756 | 1958 | ||
1757 | foreach (SceneObjectPart p in newSet) | 1959 | foreach (SceneObjectPart p in newSet) |
1960 | { | ||
1961 | if (p != group.RootPart) | ||
1758 | { | 1962 | { |
1759 | if (p != group.RootPart) | 1963 | group.DelinkFromGroup(p, sendEventsToRemainder); |
1760 | group.DelinkFromGroup(p, sendEventsToRemainder); | 1964 | if (numChildren > 2) |
1965 | { | ||
1966 | } | ||
1967 | else | ||
1968 | { | ||
1969 | p.ParentGroup.HasGroupChanged = true; | ||
1970 | p.ParentGroup.ScheduleGroupForFullUpdate(); | ||
1971 | } | ||
1761 | } | 1972 | } |
1973 | } | ||
1974 | |||
1975 | // If there is more than one prim remaining, we | ||
1976 | // need to re-link | ||
1977 | // | ||
1978 | if (numChildren > 2) | ||
1979 | { | ||
1980 | // Remove old root | ||
1981 | // | ||
1982 | if (newSet.Contains(root)) | ||
1983 | newSet.Remove(root); | ||
1762 | 1984 | ||
1763 | // If there is more than one prim remaining, we | 1985 | // Preserve link ordering |
1764 | // need to re-link | ||
1765 | // | 1986 | // |
1766 | if (numChildren > 2) | 1987 | newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b) |
1767 | { | 1988 | { |
1768 | // Remove old root | 1989 | return a.LinkNum.CompareTo(b.LinkNum); |
1769 | // | 1990 | }); |
1770 | if (newSet.Contains(root)) | ||
1771 | newSet.Remove(root); | ||
1772 | |||
1773 | // Preserve link ordering | ||
1774 | // | ||
1775 | newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b) | ||
1776 | { | ||
1777 | return a.LinkNum.CompareTo(b.LinkNum); | ||
1778 | }); | ||
1779 | 1991 | ||
1780 | // Determine new root | 1992 | // Determine new root |
1781 | // | 1993 | // |
1782 | SceneObjectPart newRoot = newSet[0]; | 1994 | SceneObjectPart newRoot = newSet[0]; |
1783 | newSet.RemoveAt(0); | 1995 | newSet.RemoveAt(0); |
1784 | 1996 | ||
1785 | foreach (SceneObjectPart newChild in newSet) | 1997 | foreach (SceneObjectPart newChild in newSet) |
1786 | newChild.ClearUpdateSchedule(); | 1998 | newChild.ClearUpdateSchedule(); |
1787 | 1999 | ||
1788 | LinkObjects(newRoot, newSet); | 2000 | LinkObjects(newRoot, newSet); |
1789 | if (!affectedGroups.Contains(newRoot.ParentGroup)) | 2001 | if (!affectedGroups.Contains(newRoot.ParentGroup)) |
1790 | affectedGroups.Add(newRoot.ParentGroup); | 2002 | affectedGroups.Add(newRoot.ParentGroup); |
1791 | } | ||
1792 | } | 2003 | } |
1793 | } | 2004 | } |
1794 | 2005 | ||
@@ -1796,6 +2007,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
1796 | // | 2007 | // |
1797 | foreach (SceneObjectGroup g in affectedGroups) | 2008 | foreach (SceneObjectGroup g in affectedGroups) |
1798 | { | 2009 | { |
2010 | // Child prims that have been unlinked and deleted will | ||
2011 | // return unless the root is deleted. This will remove them | ||
2012 | // from the database. They will be rewritten immediately, | ||
2013 | // minus the rows for the unlinked child prims. | ||
2014 | g.AdjustChildPrimPermissions(); | ||
2015 | m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID); | ||
1799 | g.TriggerScriptChangedEvent(Changed.LINK); | 2016 | g.TriggerScriptChangedEvent(Changed.LINK); |
1800 | g.HasGroupChanged = true; // Persist | 2017 | g.HasGroupChanged = true; // Persist |
1801 | g.ScheduleGroupForFullUpdate(); | 2018 | g.ScheduleGroupForFullUpdate(); |
@@ -1869,108 +2086,96 @@ namespace OpenSim.Region.Framework.Scenes | |||
1869 | /// <param name="GroupID"></param> | 2086 | /// <param name="GroupID"></param> |
1870 | /// <param name="rot"></param> | 2087 | /// <param name="rot"></param> |
1871 | /// <returns>null if duplication fails, otherwise the duplicated object</returns> | 2088 | /// <returns>null if duplication fails, otherwise the duplicated object</returns> |
1872 | public SceneObjectGroup DuplicateObject( | 2089 | /// <summary> |
1873 | uint originalPrimID, Vector3 offset, uint flags, UUID AgentID, UUID GroupID, Quaternion rot) | 2090 | public SceneObjectGroup DuplicateObject(uint originalPrimID, Vector3 offset, uint flags, UUID AgentID, UUID GroupID, Quaternion rot) |
1874 | { | 2091 | { |
1875 | Monitor.Enter(m_updateLock); | 2092 | // m_log.DebugFormat( |
2093 | // "[SCENE]: Duplication of object {0} at offset {1} requested by agent {2}", | ||
2094 | // originalPrimID, offset, AgentID); | ||
1876 | 2095 | ||
1877 | try | 2096 | SceneObjectGroup original = GetGroupByPrim(originalPrimID); |
2097 | if (original != null) | ||
1878 | { | 2098 | { |
1879 | // m_log.DebugFormat( | 2099 | if (m_parentScene.Permissions.CanDuplicateObject( |
1880 | // "[SCENE]: Duplication of object {0} at offset {1} requested by agent {2}", | 2100 | original.PrimCount, original.UUID, AgentID, original.AbsolutePosition)) |
1881 | // originalPrimID, offset, AgentID); | ||
1882 | |||
1883 | SceneObjectGroup original = GetGroupByPrim(originalPrimID); | ||
1884 | if (original == null) | ||
1885 | { | 2101 | { |
1886 | m_log.WarnFormat( | 2102 | SceneObjectGroup copy = original.Copy(true); |
1887 | "[SCENEGRAPH]: Attempt to duplicate nonexistant prim id {0} by {1}", originalPrimID, AgentID); | 2103 | copy.AbsolutePosition = copy.AbsolutePosition + offset; |
1888 | 2104 | ||
1889 | return null; | 2105 | if (original.OwnerID != AgentID) |
1890 | } | 2106 | { |
2107 | copy.SetOwnerId(AgentID); | ||
2108 | copy.SetRootPartOwner(copy.RootPart, AgentID, GroupID); | ||
1891 | 2109 | ||
1892 | if (!m_parentScene.Permissions.CanDuplicateObject( | 2110 | SceneObjectPart[] partList = copy.Parts; |
1893 | original.PrimCount, original.UUID, AgentID, original.AbsolutePosition)) | ||
1894 | return null; | ||
1895 | 2111 | ||
1896 | SceneObjectGroup copy = original.Copy(true); | 2112 | if (m_parentScene.Permissions.PropagatePermissions()) |
1897 | copy.AbsolutePosition = copy.AbsolutePosition + offset; | 2113 | { |
2114 | foreach (SceneObjectPart child in partList) | ||
2115 | { | ||
2116 | child.Inventory.ChangeInventoryOwner(AgentID); | ||
2117 | child.TriggerScriptChangedEvent(Changed.OWNER); | ||
2118 | child.ApplyNextOwnerPermissions(); | ||
2119 | } | ||
2120 | } | ||
2121 | } | ||
1898 | 2122 | ||
1899 | if (original.OwnerID != AgentID) | 2123 | // FIXME: This section needs to be refactored so that it just calls AddSceneObject() |
1900 | { | 2124 | Entities.Add(copy); |
1901 | copy.SetOwnerId(AgentID); | ||
1902 | copy.SetRootPartOwner(copy.RootPart, AgentID, GroupID); | ||
1903 | 2125 | ||
1904 | SceneObjectPart[] partList = copy.Parts; | 2126 | lock (SceneObjectGroupsByFullID) |
2127 | SceneObjectGroupsByFullID[copy.UUID] = copy; | ||
1905 | 2128 | ||
1906 | if (m_parentScene.Permissions.PropagatePermissions()) | 2129 | SceneObjectPart[] children = copy.Parts; |
2130 | |||
2131 | lock (SceneObjectGroupsByFullPartID) | ||
1907 | { | 2132 | { |
1908 | foreach (SceneObjectPart child in partList) | 2133 | SceneObjectGroupsByFullPartID[copy.UUID] = copy; |
1909 | { | 2134 | foreach (SceneObjectPart part in children) |
1910 | child.Inventory.ChangeInventoryOwner(AgentID); | 2135 | SceneObjectGroupsByFullPartID[part.UUID] = copy; |
1911 | child.TriggerScriptChangedEvent(Changed.OWNER); | ||
1912 | child.ApplyNextOwnerPermissions(); | ||
1913 | } | ||
1914 | } | 2136 | } |
1915 | 2137 | ||
1916 | copy.RootPart.ObjectSaleType = 0; | 2138 | lock (SceneObjectGroupsByLocalPartID) |
1917 | copy.RootPart.SalePrice = 10; | 2139 | { |
1918 | } | 2140 | SceneObjectGroupsByLocalPartID[copy.LocalId] = copy; |
2141 | foreach (SceneObjectPart part in children) | ||
2142 | SceneObjectGroupsByLocalPartID[part.LocalId] = copy; | ||
2143 | } | ||
2144 | // PROBABLE END OF FIXME | ||
1919 | 2145 | ||
1920 | // FIXME: This section needs to be refactored so that it just calls AddSceneObject() | 2146 | // Since we copy from a source group that is in selected |
1921 | Entities.Add(copy); | 2147 | // state, but the copy is shown deselected in the viewer, |
1922 | 2148 | // We need to clear the selection flag here, else that | |
1923 | lock (SceneObjectGroupsByFullID) | 2149 | // prim never gets persisted at all. The client doesn't |
1924 | SceneObjectGroupsByFullID[copy.UUID] = copy; | 2150 | // think it's selected, so it will never send a deselect... |
1925 | 2151 | copy.IsSelected = false; | |
1926 | SceneObjectPart[] children = copy.Parts; | 2152 | |
1927 | 2153 | m_numPrim += copy.Parts.Length; | |
1928 | lock (SceneObjectGroupsByFullPartID) | 2154 | |
1929 | { | 2155 | if (rot != Quaternion.Identity) |
1930 | SceneObjectGroupsByFullPartID[copy.UUID] = copy; | 2156 | { |
1931 | foreach (SceneObjectPart part in children) | 2157 | copy.UpdateGroupRotationR(rot); |
1932 | SceneObjectGroupsByFullPartID[part.UUID] = copy; | 2158 | } |
1933 | } | ||
1934 | |||
1935 | lock (SceneObjectGroupsByLocalPartID) | ||
1936 | { | ||
1937 | SceneObjectGroupsByLocalPartID[copy.LocalId] = copy; | ||
1938 | foreach (SceneObjectPart part in children) | ||
1939 | SceneObjectGroupsByLocalPartID[part.LocalId] = copy; | ||
1940 | } | ||
1941 | // PROBABLE END OF FIXME | ||
1942 | |||
1943 | // Since we copy from a source group that is in selected | ||
1944 | // state, but the copy is shown deselected in the viewer, | ||
1945 | // We need to clear the selection flag here, else that | ||
1946 | // prim never gets persisted at all. The client doesn't | ||
1947 | // think it's selected, so it will never send a deselect... | ||
1948 | copy.IsSelected = false; | ||
1949 | |||
1950 | m_numPrim += copy.Parts.Length; | ||
1951 | |||
1952 | if (rot != Quaternion.Identity) | ||
1953 | { | ||
1954 | copy.UpdateGroupRotationR(rot); | ||
1955 | } | ||
1956 | 2159 | ||
1957 | copy.CreateScriptInstances(0, false, m_parentScene.DefaultScriptEngine, 1); | 2160 | copy.CreateScriptInstances(0, false, m_parentScene.DefaultScriptEngine, 1); |
1958 | copy.HasGroupChanged = true; | 2161 | copy.HasGroupChanged = true; |
1959 | copy.ScheduleGroupForFullUpdate(); | 2162 | copy.ScheduleGroupForFullUpdate(); |
1960 | copy.ResumeScripts(); | 2163 | copy.ResumeScripts(); |
1961 | 2164 | ||
1962 | // required for physics to update it's position | 2165 | // required for physics to update it's position |
1963 | copy.AbsolutePosition = copy.AbsolutePosition; | 2166 | copy.AbsolutePosition = copy.AbsolutePosition; |
1964 | 2167 | ||
1965 | return copy; | 2168 | return copy; |
2169 | } | ||
1966 | } | 2170 | } |
1967 | finally | 2171 | else |
1968 | { | 2172 | { |
1969 | Monitor.Exit(m_updateLock); | 2173 | m_log.WarnFormat("[SCENE]: Attempted to duplicate nonexistant prim id {0}", GroupID); |
1970 | } | 2174 | } |
2175 | |||
2176 | return null; | ||
1971 | } | 2177 | } |
1972 | 2178 | ||
1973 | /// <summary> | ||
1974 | /// Calculates the distance between two Vector3s | 2179 | /// Calculates the distance between two Vector3s |
1975 | /// </summary> | 2180 | /// </summary> |
1976 | /// <param name="v1"></param> | 2181 | /// <param name="v1"></param> |