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.cs443
1 files changed, 308 insertions, 135 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index bb7ae7f..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 {
@@ -1581,6 +1732,7 @@ namespace OpenSim.Region.Framework.Scenes
1581 { 1732 {
1582 part.Material = Convert.ToByte(material); 1733 part.Material = Convert.ToByte(material);
1583 group.HasGroupChanged = true; 1734 group.HasGroupChanged = true;
1735 remoteClient.SendPartPhysicsProprieties(part);
1584 } 1736 }
1585 } 1737 }
1586 } 1738 }
@@ -1659,8 +1811,10 @@ namespace OpenSim.Region.Framework.Scenes
1659 return; 1811 return;
1660 1812
1661 Monitor.Enter(m_updateLock); 1813 Monitor.Enter(m_updateLock);
1814
1662 try 1815 try
1663 { 1816 {
1817
1664 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); 1818 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>();
1665 1819
1666 // 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
@@ -1675,9 +1829,13 @@ namespace OpenSim.Region.Framework.Scenes
1675 // Make sure no child prim is set for sale 1829 // Make sure no child prim is set for sale
1676 // So that, on delink, no prims are unwittingly 1830 // So that, on delink, no prims are unwittingly
1677 // left for sale and sold off 1831 // left for sale and sold off
1678 child.RootPart.ObjectSaleType = 0; 1832
1679 child.RootPart.SalePrice = 10; 1833 if (child != null)
1680 childGroups.Add(child); 1834 {
1835 child.RootPart.ObjectSaleType = 0;
1836 child.RootPart.SalePrice = 10;
1837 childGroups.Add(child);
1838 }
1681 } 1839 }
1682 1840
1683 foreach (SceneObjectGroup child in childGroups) 1841 foreach (SceneObjectGroup child in childGroups)
@@ -1706,6 +1864,16 @@ namespace OpenSim.Region.Framework.Scenes
1706 } 1864 }
1707 finally 1865 finally
1708 { 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();
1709 Monitor.Exit(m_updateLock); 1877 Monitor.Exit(m_updateLock);
1710 } 1878 }
1711 } 1879 }
@@ -1747,21 +1915,23 @@ namespace OpenSim.Region.Framework.Scenes
1747 1915
1748 SceneObjectGroup group = part.ParentGroup; 1916 SceneObjectGroup group = part.ParentGroup;
1749 if (!affectedGroups.Contains(group)) 1917 if (!affectedGroups.Contains(group))
1918 {
1750 affectedGroups.Add(group); 1919 affectedGroups.Add(group);
1920 }
1751 } 1921 }
1752 } 1922 }
1753 } 1923 }
1754 1924
1755 foreach (SceneObjectPart child in childParts) 1925 if (childParts.Count > 0)
1756 { 1926 {
1757 // Unlink all child parts from their groups 1927 foreach (SceneObjectPart child in childParts)
1758 // 1928 {
1759 child.ParentGroup.DelinkFromGroup(child, true); 1929 // Unlink all child parts from their groups
1760 1930 //
1761 // These are not in affected groups and will not be 1931 child.ParentGroup.DelinkFromGroup(child, true);
1762 // handled further. Do the honors here. 1932 child.ParentGroup.HasGroupChanged = true;
1763 child.ParentGroup.HasGroupChanged = true; 1933 child.ParentGroup.ScheduleGroupForFullUpdate();
1764 child.ParentGroup.ScheduleGroupForFullUpdate(); 1934 }
1765 } 1935 }
1766 1936
1767 foreach (SceneObjectPart root in rootParts) 1937 foreach (SceneObjectPart root in rootParts)
@@ -1775,52 +1945,61 @@ namespace OpenSim.Region.Framework.Scenes
1775 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); 1945 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts);
1776 int numChildren = newSet.Count; 1946 int numChildren = newSet.Count;
1777 1947
1948 if (numChildren == 1)
1949 break;
1950
1778 // 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
1779 // slated for unlink, we need to do this 1952 // slated for unlink, we need to do this
1953 // Unlink the remaining set
1780 // 1954 //
1781 if (numChildren != 1) 1955 bool sendEventsToRemainder = true;
1782 { 1956 if (numChildren > 1)
1783 // Unlink the remaining set 1957 sendEventsToRemainder = false;
1784 //
1785 bool sendEventsToRemainder = true;
1786 if (numChildren > 1)
1787 sendEventsToRemainder = false;
1788 1958
1789 foreach (SceneObjectPart p in newSet) 1959 foreach (SceneObjectPart p in newSet)
1960 {
1961 if (p != group.RootPart)
1790 { 1962 {
1791 if (p != group.RootPart) 1963 group.DelinkFromGroup(p, sendEventsToRemainder);
1792 group.DelinkFromGroup(p, sendEventsToRemainder); 1964 if (numChildren > 2)
1965 {
1966 }
1967 else
1968 {
1969 p.ParentGroup.HasGroupChanged = true;
1970 p.ParentGroup.ScheduleGroupForFullUpdate();
1971 }
1793 } 1972 }
1973 }
1794 1974
1795 // If there is more than one prim remaining, we 1975 // If there is more than one prim remaining, we
1796 // need to re-link 1976 // need to re-link
1977 //
1978 if (numChildren > 2)
1979 {
1980 // Remove old root
1797 // 1981 //
1798 if (numChildren > 2) 1982 if (newSet.Contains(root))
1983 newSet.Remove(root);
1984
1985 // Preserve link ordering
1986 //
1987 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1799 { 1988 {
1800 // Remove old root 1989 return a.LinkNum.CompareTo(b.LinkNum);
1801 // 1990 });
1802 if (newSet.Contains(root))
1803 newSet.Remove(root);
1804
1805 // Preserve link ordering
1806 //
1807 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1808 {
1809 return a.LinkNum.CompareTo(b.LinkNum);
1810 });
1811 1991
1812 // Determine new root 1992 // Determine new root
1813 // 1993 //
1814 SceneObjectPart newRoot = newSet[0]; 1994 SceneObjectPart newRoot = newSet[0];
1815 newSet.RemoveAt(0); 1995 newSet.RemoveAt(0);
1816 1996
1817 foreach (SceneObjectPart newChild in newSet) 1997 foreach (SceneObjectPart newChild in newSet)
1818 newChild.ClearUpdateSchedule(); 1998 newChild.ClearUpdateSchedule();
1819 1999
1820 LinkObjects(newRoot, newSet); 2000 LinkObjects(newRoot, newSet);
1821 if (!affectedGroups.Contains(newRoot.ParentGroup)) 2001 if (!affectedGroups.Contains(newRoot.ParentGroup))
1822 affectedGroups.Add(newRoot.ParentGroup); 2002 affectedGroups.Add(newRoot.ParentGroup);
1823 }
1824 } 2003 }
1825 } 2004 }
1826 2005
@@ -1828,6 +2007,12 @@ namespace OpenSim.Region.Framework.Scenes
1828 // 2007 //
1829 foreach (SceneObjectGroup g in affectedGroups) 2008 foreach (SceneObjectGroup g in affectedGroups)
1830 { 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);
1831 g.TriggerScriptChangedEvent(Changed.LINK); 2016 g.TriggerScriptChangedEvent(Changed.LINK);
1832 g.HasGroupChanged = true; // Persist 2017 g.HasGroupChanged = true; // Persist
1833 g.ScheduleGroupForFullUpdate(); 2018 g.ScheduleGroupForFullUpdate();
@@ -1901,108 +2086,96 @@ namespace OpenSim.Region.Framework.Scenes
1901 /// <param name="GroupID"></param> 2086 /// <param name="GroupID"></param>
1902 /// <param name="rot"></param> 2087 /// <param name="rot"></param>
1903 /// <returns>null if duplication fails, otherwise the duplicated object</returns> 2088 /// <returns>null if duplication fails, otherwise the duplicated object</returns>
1904 public SceneObjectGroup DuplicateObject( 2089 /// <summary>
1905 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)
1906 { 2091 {
1907 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);
1908 2095
1909 try 2096 SceneObjectGroup original = GetGroupByPrim(originalPrimID);
2097 if (original != null)
1910 { 2098 {
1911 // m_log.DebugFormat( 2099 if (m_parentScene.Permissions.CanDuplicateObject(
1912 // "[SCENE]: Duplication of object {0} at offset {1} requested by agent {2}", 2100 original.PrimCount, original.UUID, AgentID, original.AbsolutePosition))
1913 // originalPrimID, offset, AgentID);
1914
1915 SceneObjectGroup original = GetGroupByPrim(originalPrimID);
1916 if (original == null)
1917 { 2101 {
1918 m_log.WarnFormat( 2102 SceneObjectGroup copy = original.Copy(true);
1919 "[SCENEGRAPH]: Attempt to duplicate nonexistant prim id {0} by {1}", originalPrimID, AgentID); 2103 copy.AbsolutePosition = copy.AbsolutePosition + offset;
1920 2104
1921 return null; 2105 if (original.OwnerID != AgentID)
1922 } 2106 {
2107 copy.SetOwnerId(AgentID);
2108 copy.SetRootPartOwner(copy.RootPart, AgentID, GroupID);
1923 2109
1924 if (!m_parentScene.Permissions.CanDuplicateObject( 2110 SceneObjectPart[] partList = copy.Parts;
1925 original.PrimCount, original.UUID, AgentID, original.AbsolutePosition)) 2111
1926 return null; 2112 if (m_parentScene.Permissions.PropagatePermissions())
2113 {
2114 foreach (SceneObjectPart child in partList)
2115 {
2116 child.Inventory.ChangeInventoryOwner(AgentID);
2117 child.TriggerScriptChangedEvent(Changed.OWNER);
2118 child.ApplyNextOwnerPermissions();
2119 }
2120 }
2121 }
1927 2122
1928 SceneObjectGroup copy = original.Copy(true); 2123 // FIXME: This section needs to be refactored so that it just calls AddSceneObject()
1929 copy.AbsolutePosition = copy.AbsolutePosition + offset; 2124 Entities.Add(copy);
1930 2125
1931 if (original.OwnerID != AgentID) 2126 lock (SceneObjectGroupsByFullID)
1932 { 2127 SceneObjectGroupsByFullID[copy.UUID] = copy;
1933 copy.SetOwnerId(AgentID);
1934 copy.SetRootPartOwner(copy.RootPart, AgentID, GroupID);
1935 2128
1936 SceneObjectPart[] partList = copy.Parts; 2129 SceneObjectPart[] children = copy.Parts;
1937 2130
1938 if (m_parentScene.Permissions.PropagatePermissions()) 2131 lock (SceneObjectGroupsByFullPartID)
1939 { 2132 {
1940 foreach (SceneObjectPart child in partList) 2133 SceneObjectGroupsByFullPartID[copy.UUID] = copy;
1941 { 2134 foreach (SceneObjectPart part in children)
1942 child.Inventory.ChangeInventoryOwner(AgentID); 2135 SceneObjectGroupsByFullPartID[part.UUID] = copy;
1943 child.TriggerScriptChangedEvent(Changed.OWNER);
1944 child.ApplyNextOwnerPermissions();
1945 }
1946 } 2136 }
1947 2137
1948 copy.RootPart.ObjectSaleType = 0; 2138 lock (SceneObjectGroupsByLocalPartID)
1949 copy.RootPart.SalePrice = 10; 2139 {
1950 } 2140 SceneObjectGroupsByLocalPartID[copy.LocalId] = copy;
2141 foreach (SceneObjectPart part in children)
2142 SceneObjectGroupsByLocalPartID[part.LocalId] = copy;
2143 }
2144 // PROBABLE END OF FIXME
1951 2145
1952 // 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
1953 Entities.Add(copy); 2147 // state, but the copy is shown deselected in the viewer,
1954 2148 // We need to clear the selection flag here, else that
1955 lock (SceneObjectGroupsByFullID) 2149 // prim never gets persisted at all. The client doesn't
1956 SceneObjectGroupsByFullID[copy.UUID] = copy; 2150 // think it's selected, so it will never send a deselect...
1957 2151 copy.IsSelected = false;
1958 SceneObjectPart[] children = copy.Parts; 2152
1959 2153 m_numPrim += copy.Parts.Length;
1960 lock (SceneObjectGroupsByFullPartID) 2154
1961 { 2155 if (rot != Quaternion.Identity)
1962 SceneObjectGroupsByFullPartID[copy.UUID] = copy; 2156 {
1963 foreach (SceneObjectPart part in children) 2157 copy.UpdateGroupRotationR(rot);
1964 SceneObjectGroupsByFullPartID[part.UUID] = copy; 2158 }
1965 }
1966
1967 lock (SceneObjectGroupsByLocalPartID)
1968 {
1969 SceneObjectGroupsByLocalPartID[copy.LocalId] = copy;
1970 foreach (SceneObjectPart part in children)
1971 SceneObjectGroupsByLocalPartID[part.LocalId] = copy;
1972 }
1973 // PROBABLE END OF FIXME
1974
1975 // Since we copy from a source group that is in selected
1976 // state, but the copy is shown deselected in the viewer,
1977 // We need to clear the selection flag here, else that
1978 // prim never gets persisted at all. The client doesn't
1979 // think it's selected, so it will never send a deselect...
1980 copy.IsSelected = false;
1981
1982 m_numPrim += copy.Parts.Length;
1983
1984 if (rot != Quaternion.Identity)
1985 {
1986 copy.UpdateGroupRotationR(rot);
1987 }
1988 2159
1989 copy.CreateScriptInstances(0, false, m_parentScene.DefaultScriptEngine, 1); 2160 copy.CreateScriptInstances(0, false, m_parentScene.DefaultScriptEngine, 1);
1990 copy.HasGroupChanged = true; 2161 copy.HasGroupChanged = true;
1991 copy.ScheduleGroupForFullUpdate(); 2162 copy.ScheduleGroupForFullUpdate();
1992 copy.ResumeScripts(); 2163 copy.ResumeScripts();
1993 2164
1994 // required for physics to update it's position 2165 // required for physics to update it's position
1995 copy.AbsolutePosition = copy.AbsolutePosition; 2166 copy.AbsolutePosition = copy.AbsolutePosition;
1996 2167
1997 return copy; 2168 return copy;
2169 }
1998 } 2170 }
1999 finally 2171 else
2000 { 2172 {
2001 Monitor.Exit(m_updateLock); 2173 m_log.WarnFormat("[SCENE]: Attempted to duplicate nonexistant prim id {0}", GroupID);
2002 } 2174 }
2175
2176 return null;
2003 } 2177 }
2004 2178
2005 /// <summary>
2006 /// Calculates the distance between two Vector3s 2179 /// Calculates the distance between two Vector3s
2007 /// </summary> 2180 /// </summary>
2008 /// <param name="v1"></param> 2181 /// <param name="v1"></param>