aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework/Scenes/SceneGraph.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/SceneGraph.cs')
-rwxr-xr-xOpenSim/Region/Framework/Scenes/SceneGraph.cs496
1 files changed, 366 insertions, 130 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index c2e9b61..3f6a7f8 100755
--- 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
@@ -129,13 +139,18 @@ namespace OpenSim.Region.Framework.Scenes
129 139
130 protected internal void Close() 140 protected internal void Close()
131 { 141 {
132 lock (m_presenceLock) 142 m_scenePresencesLock.EnterWriteLock();
143 try
133 { 144 {
134 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(); 145 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>();
135 List<ScenePresence> newlist = new List<ScenePresence>(); 146 List<ScenePresence> newlist = new List<ScenePresence>();
136 m_scenePresenceMap = newmap; 147 m_scenePresenceMap = newmap;
137 m_scenePresenceArray = newlist; 148 m_scenePresenceArray = newlist;
138 } 149 }
150 finally
151 {
152 m_scenePresencesLock.ExitWriteLock();
153 }
139 154
140 lock (SceneObjectGroupsByFullID) 155 lock (SceneObjectGroupsByFullID)
141 SceneObjectGroupsByFullID.Clear(); 156 SceneObjectGroupsByFullID.Clear();
@@ -256,13 +271,54 @@ namespace OpenSim.Region.Framework.Scenes
256 protected internal bool AddRestoredSceneObject( 271 protected internal bool AddRestoredSceneObject(
257 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 272 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
258 { 273 {
274 if (!m_parentScene.CombineRegions)
275 {
276 // temporary checks to remove after varsize suport
277 float regionSizeX = m_parentScene.RegionInfo.RegionSizeX;
278 if (regionSizeX == 0)
279 regionSizeX = Constants.RegionSize;
280 float regionSizeY = m_parentScene.RegionInfo.RegionSizeY;
281 if (regionSizeY == 0)
282 regionSizeY = Constants.RegionSize;
283
284 // KF: Check for out-of-region, move inside and make static.
285 Vector3 npos = new Vector3(sceneObject.RootPart.GroupPosition.X,
286 sceneObject.RootPart.GroupPosition.Y,
287 sceneObject.RootPart.GroupPosition.Z);
288 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 ||
289 npos.X > regionSizeX ||
290 npos.Y > regionSizeY))
291 {
292 if (npos.X < 0.0) npos.X = 1.0f;
293 if (npos.Y < 0.0) npos.Y = 1.0f;
294 if (npos.Z < 0.0) npos.Z = 0.0f;
295 if (npos.X > regionSizeX) npos.X = regionSizeX - 1.0f;
296 if (npos.Y > regionSizeY) npos.Y = regionSizeY - 1.0f;
297
298 SceneObjectPart rootpart = sceneObject.RootPart;
299 rootpart.GroupPosition = npos;
300
301 foreach (SceneObjectPart part in sceneObject.Parts)
302 {
303 if (part == rootpart)
304 continue;
305 part.GroupPosition = npos;
306 }
307 rootpart.Velocity = Vector3.Zero;
308 rootpart.AngularVelocity = Vector3.Zero;
309 rootpart.Acceleration = Vector3.Zero;
310 }
311 }
312
313 bool ret = AddSceneObject(sceneObject, attachToBackup, sendClientUpdates);
314
259 if (attachToBackup && (!alreadyPersisted)) 315 if (attachToBackup && (!alreadyPersisted))
260 { 316 {
261 sceneObject.ForceInventoryPersistence(); 317 sceneObject.ForceInventoryPersistence();
262 sceneObject.HasGroupChanged = true; 318 sceneObject.HasGroupChanged = true;
263 } 319 }
264 320
265 return AddSceneObject(sceneObject, attachToBackup, sendClientUpdates); 321 return ret;
266 } 322 }
267 323
268 /// <summary> 324 /// <summary>
@@ -279,12 +335,16 @@ namespace OpenSim.Region.Framework.Scenes
279 /// </returns> 335 /// </returns>
280 protected internal bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) 336 protected internal bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates)
281 { 337 {
282 // Ensure that we persist this new scene object if it's not an 338
339 bool ret = AddSceneObject(sceneObject, attachToBackup, sendClientUpdates);
340
341 // Ensure that we persist this new scene object if it's not an
283 // attachment 342 // attachment
343
284 if (attachToBackup) 344 if (attachToBackup)
285 sceneObject.HasGroupChanged = true; 345 sceneObject.HasGroupChanged = true;
286 346
287 return AddSceneObject(sceneObject, attachToBackup, sendClientUpdates); 347 return ret;
288 } 348 }
289 349
290 /// <summary> 350 /// <summary>
@@ -319,9 +379,8 @@ namespace OpenSim.Region.Framework.Scenes
319 if (pa != null && pa.IsPhysical && vel != Vector3.Zero) 379 if (pa != null && pa.IsPhysical && vel != Vector3.Zero)
320 { 380 {
321 sceneObject.RootPart.ApplyImpulse((vel * sceneObject.GetMass()), false); 381 sceneObject.RootPart.ApplyImpulse((vel * sceneObject.GetMass()), false);
322 sceneObject.Velocity = vel;
323 } 382 }
324 383
325 return true; 384 return true;
326 } 385 }
327 386
@@ -346,6 +405,11 @@ namespace OpenSim.Region.Framework.Scenes
346 /// </returns> 405 /// </returns>
347 protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) 406 protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates)
348 { 407 {
408 if (sceneObject == null)
409 {
410 m_log.ErrorFormat("[SCENEGRAPH]: Tried to add null scene object");
411 return false;
412 }
349 if (sceneObject.UUID == UUID.Zero) 413 if (sceneObject.UUID == UUID.Zero)
350 { 414 {
351 m_log.ErrorFormat( 415 m_log.ErrorFormat(
@@ -378,9 +442,9 @@ namespace OpenSim.Region.Framework.Scenes
378 { 442 {
379 Vector3 scale = part.Shape.Scale; 443 Vector3 scale = part.Shape.Scale;
380 444
381 scale.X = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.X)); 445 scale.X = Util.Clamp(scale.X, m_parentScene.m_minNonphys, m_parentScene.m_maxNonphys);
382 scale.Y = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.Y)); 446 scale.Y = Util.Clamp(scale.Y, m_parentScene.m_minNonphys, m_parentScene.m_maxNonphys);
383 scale.Z = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.Z)); 447 scale.Z = Util.Clamp(scale.Z, m_parentScene.m_minNonphys, m_parentScene.m_maxNonphys);
384 448
385 part.Shape.Scale = scale; 449 part.Shape.Scale = scale;
386 } 450 }
@@ -401,36 +465,39 @@ namespace OpenSim.Region.Framework.Scenes
401 465
402 sceneObject.AttachToScene(m_parentScene); 466 sceneObject.AttachToScene(m_parentScene);
403 467
404 if (sendClientUpdates)
405 sceneObject.ScheduleGroupForFullUpdate();
406
407 Entities.Add(sceneObject); 468 Entities.Add(sceneObject);
408 469
409 if (attachToBackup)
410 sceneObject.AttachToBackup();
411
412 lock (SceneObjectGroupsByFullID) 470 lock (SceneObjectGroupsByFullID)
413 SceneObjectGroupsByFullID[sceneObject.UUID] = sceneObject; 471 SceneObjectGroupsByFullID[sceneObject.UUID] = sceneObject;
414 472
415 lock (SceneObjectGroupsByFullPartID) 473 foreach (SceneObjectPart part in parts)
416 { 474 {
417 foreach (SceneObjectPart part in parts) 475 lock (SceneObjectGroupsByFullPartID)
418 SceneObjectGroupsByFullPartID[part.UUID] = sceneObject; 476 SceneObjectGroupsByFullPartID[part.UUID] = sceneObject;
419 }
420
421 lock (SceneObjectGroupsByLocalPartID)
422 {
423// m_log.DebugFormat(
424// "[SCENE GRAPH]: Adding scene object {0} {1} {2} to SceneObjectGroupsByLocalPartID in {3}",
425// sceneObject.Name, sceneObject.UUID, sceneObject.LocalId, m_parentScene.RegionInfo.RegionName);
426 477
427 foreach (SceneObjectPart part in parts) 478 lock (SceneObjectGroupsByLocalPartID)
428 SceneObjectGroupsByLocalPartID[part.LocalId] = sceneObject; 479 SceneObjectGroupsByLocalPartID[part.LocalId] = sceneObject;
429 } 480 }
430 481
482 if (sendClientUpdates)
483 sceneObject.ScheduleGroupForFullUpdate();
484
485 if (attachToBackup)
486 sceneObject.AttachToBackup();
487
431 return true; 488 return true;
432 } 489 }
433 490
491 public void updateScenePartGroup(SceneObjectPart part, SceneObjectGroup grp)
492 {
493 // no tests, caller has responsability...
494 lock (SceneObjectGroupsByFullPartID)
495 SceneObjectGroupsByFullPartID[part.UUID] = grp;
496
497 lock (SceneObjectGroupsByLocalPartID)
498 SceneObjectGroupsByLocalPartID[part.LocalId] = grp;
499 }
500
434 /// <summary> 501 /// <summary>
435 /// Delete an object from the scene 502 /// Delete an object from the scene
436 /// </summary> 503 /// </summary>
@@ -471,25 +538,23 @@ namespace OpenSim.Region.Framework.Scenes
471 if ((grp.RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics) 538 if ((grp.RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics)
472 RemovePhysicalPrim(grp.PrimCount); 539 RemovePhysicalPrim(grp.PrimCount);
473 } 540 }
474 541
542 bool ret = Entities.Remove(uuid);
543
475 lock (SceneObjectGroupsByFullID) 544 lock (SceneObjectGroupsByFullID)
476 SceneObjectGroupsByFullID.Remove(grp.UUID); 545 SceneObjectGroupsByFullID.Remove(grp.UUID);
477 546
478 lock (SceneObjectGroupsByFullPartID) 547 SceneObjectPart[] parts = grp.Parts;
548 for (int i = 0; i < parts.Length; i++)
479 { 549 {
480 SceneObjectPart[] parts = grp.Parts; 550 lock (SceneObjectGroupsByFullPartID)
481 for (int i = 0; i < parts.Length; i++)
482 SceneObjectGroupsByFullPartID.Remove(parts[i].UUID); 551 SceneObjectGroupsByFullPartID.Remove(parts[i].UUID);
483 }
484 552
485 lock (SceneObjectGroupsByLocalPartID) 553 lock (SceneObjectGroupsByLocalPartID)
486 {
487 SceneObjectPart[] parts = grp.Parts;
488 for (int i = 0; i < parts.Length; i++)
489 SceneObjectGroupsByLocalPartID.Remove(parts[i].LocalId); 554 SceneObjectGroupsByLocalPartID.Remove(parts[i].LocalId);
490 } 555 }
491 556
492 return Entities.Remove(uuid); 557 return ret;
493 } 558 }
494 559
495 /// <summary> 560 /// <summary>
@@ -504,6 +569,30 @@ namespace OpenSim.Region.Framework.Scenes
504 m_updateList[obj.UUID] = obj; 569 m_updateList[obj.UUID] = obj;
505 } 570 }
506 571
572 public void FireAttachToBackup(SceneObjectGroup obj)
573 {
574 if (OnAttachToBackup != null)
575 {
576 OnAttachToBackup(obj);
577 }
578 }
579
580 public void FireDetachFromBackup(SceneObjectGroup obj)
581 {
582 if (OnDetachFromBackup != null)
583 {
584 OnDetachFromBackup(obj);
585 }
586 }
587
588 public void FireChangeBackup(SceneObjectGroup obj)
589 {
590 if (OnChangeBackup != null)
591 {
592 OnChangeBackup(obj);
593 }
594 }
595
507 /// <summary> 596 /// <summary>
508 /// Process all pending updates 597 /// Process all pending updates
509 /// </summary> 598 /// </summary>
@@ -595,7 +684,8 @@ namespace OpenSim.Region.Framework.Scenes
595 684
596 Entities[presence.UUID] = presence; 685 Entities[presence.UUID] = presence;
597 686
598 lock (m_presenceLock) 687 m_scenePresencesLock.EnterWriteLock();
688 try
599 { 689 {
600 m_numChildAgents++; 690 m_numChildAgents++;
601 691
@@ -621,6 +711,10 @@ namespace OpenSim.Region.Framework.Scenes
621 m_scenePresenceMap = newmap; 711 m_scenePresenceMap = newmap;
622 m_scenePresenceArray = newlist; 712 m_scenePresenceArray = newlist;
623 } 713 }
714 finally
715 {
716 m_scenePresencesLock.ExitWriteLock();
717 }
624 718
625 return presence; 719 return presence;
626 } 720 }
@@ -637,7 +731,8 @@ namespace OpenSim.Region.Framework.Scenes
637 agentID); 731 agentID);
638 } 732 }
639 733
640 lock (m_presenceLock) 734 m_scenePresencesLock.EnterWriteLock();
735 try
641 { 736 {
642 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 737 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
643 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 738 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -659,6 +754,10 @@ namespace OpenSim.Region.Framework.Scenes
659 m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); 754 m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID);
660 } 755 }
661 } 756 }
757 finally
758 {
759 m_scenePresencesLock.ExitWriteLock();
760 }
662 } 761 }
663 762
664 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) 763 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F)
@@ -887,7 +986,7 @@ namespace OpenSim.Region.Framework.Scenes
887 m_log.WarnFormat( 986 m_log.WarnFormat(
888 "[SCENE GRAPH]: Found scene object {0} {1} {2} via SceneObjectGroupsByLocalPartID index but it doesn't contain part with local id {3}. Removing from entry from index in {4}.", 987 "[SCENE GRAPH]: Found scene object {0} {1} {2} via SceneObjectGroupsByLocalPartID index but it doesn't contain part with local id {3}. Removing from entry from index in {4}.",
889 sog.Name, sog.UUID, sog.LocalId, localID, m_parentScene.RegionInfo.RegionName); 988 sog.Name, sog.UUID, sog.LocalId, localID, m_parentScene.RegionInfo.RegionName);
890 989 m_log.WarnFormat("stack: {0}", Environment.StackTrace);
891 SceneObjectGroupsByLocalPartID.Remove(localID); 990 SceneObjectGroupsByLocalPartID.Remove(localID);
892 } 991 }
893 } 992 }
@@ -1223,6 +1322,52 @@ namespace OpenSim.Region.Framework.Scenes
1223 1322
1224 #region Client Event handlers 1323 #region Client Event handlers
1225 1324
1325 protected internal void ClientChangeObject(uint localID, object odata, IClientAPI remoteClient)
1326 {
1327 SceneObjectPart part = GetSceneObjectPart(localID);
1328 ObjectChangeData data = (ObjectChangeData)odata;
1329
1330 if (part != null)
1331 {
1332 SceneObjectGroup grp = part.ParentGroup;
1333 if (grp != null)
1334 {
1335 if (m_parentScene.Permissions.CanEditObject(grp.UUID, remoteClient.AgentId))
1336 {
1337 // These two are exceptions SL makes in the interpretation
1338 // of the change flags. Must check them here because otherwise
1339 // the group flag (see below) would be lost
1340 if (data.change == ObjectChangeType.groupS)
1341 data.change = ObjectChangeType.primS;
1342 if (data.change == ObjectChangeType.groupPS)
1343 data.change = ObjectChangeType.primPS;
1344 part.StoreUndoState(data.change); // lets test only saving what we changed
1345 grp.doChangeObject(part, (ObjectChangeData)data);
1346 }
1347 else
1348 {
1349 // Is this any kind of group operation?
1350 if ((data.change & ObjectChangeType.Group) != 0)
1351 {
1352 // Is a move and/or rotation requested?
1353 if ((data.change & (ObjectChangeType.Position | ObjectChangeType.Rotation)) != 0)
1354 {
1355 // Are we allowed to move it?
1356 if (m_parentScene.Permissions.CanMoveObject(grp.UUID, remoteClient.AgentId))
1357 {
1358 // Strip all but move and rotation from request
1359 data.change &= (ObjectChangeType.Group | ObjectChangeType.Position | ObjectChangeType.Rotation);
1360
1361 part.StoreUndoState(data.change);
1362 grp.doChangeObject(part, (ObjectChangeData)data);
1363 }
1364 }
1365 }
1366 }
1367 }
1368 }
1369 }
1370
1226 /// <summary> 1371 /// <summary>
1227 /// Update the scale of an individual prim. 1372 /// Update the scale of an individual prim.
1228 /// </summary> 1373 /// </summary>
@@ -1237,7 +1382,17 @@ namespace OpenSim.Region.Framework.Scenes
1237 { 1382 {
1238 if (m_parentScene.Permissions.CanEditObject(part.ParentGroup.UUID, remoteClient.AgentId)) 1383 if (m_parentScene.Permissions.CanEditObject(part.ParentGroup.UUID, remoteClient.AgentId))
1239 { 1384 {
1385 bool physbuild = false;
1386 if (part.ParentGroup.RootPart.PhysActor != null)
1387 {
1388 part.ParentGroup.RootPart.PhysActor.Building = true;
1389 physbuild = true;
1390 }
1391
1240 part.Resize(scale); 1392 part.Resize(scale);
1393
1394 if (physbuild)
1395 part.ParentGroup.RootPart.PhysActor.Building = false;
1241 } 1396 }
1242 } 1397 }
1243 } 1398 }
@@ -1249,7 +1404,17 @@ namespace OpenSim.Region.Framework.Scenes
1249 { 1404 {
1250 if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) 1405 if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId))
1251 { 1406 {
1407 bool physbuild = false;
1408 if (group.RootPart.PhysActor != null)
1409 {
1410 group.RootPart.PhysActor.Building = true;
1411 physbuild = true;
1412 }
1413
1252 group.GroupResize(scale); 1414 group.GroupResize(scale);
1415
1416 if (physbuild)
1417 group.RootPart.PhysActor.Building = false;
1253 } 1418 }
1254 } 1419 }
1255 } 1420 }
@@ -1388,8 +1553,13 @@ namespace OpenSim.Region.Framework.Scenes
1388 { 1553 {
1389 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) 1554 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0))
1390 { 1555 {
1391 if (m_parentScene.AttachmentsModule != null) 1556 // Set the new attachment point data in the object
1392 m_parentScene.AttachmentsModule.UpdateAttachmentPosition(group, pos); 1557 byte attachmentPoint = group.GetAttachmentPoint();
1558 group.UpdateGroupPosition(pos);
1559 group.IsAttachment = false;
1560 group.AbsolutePosition = group.RootPart.AttachedPos;
1561 group.AttachmentPoint = attachmentPoint;
1562 group.HasGroupChanged = true;
1393 } 1563 }
1394 else 1564 else
1395 { 1565 {
@@ -1447,6 +1617,7 @@ namespace OpenSim.Region.Framework.Scenes
1447 // VolumeDetect can't be set via UI and will always be off when a change is made there 1617 // VolumeDetect can't be set via UI and will always be off when a change is made there
1448 // now only change volume dtc if phantom off 1618 // now only change volume dtc if phantom off
1449 1619
1620 bool wantedPhys = UsePhysics;
1450 if (PhysData.PhysShapeType == PhysShapeType.invalid) // check for extraPhysics data 1621 if (PhysData.PhysShapeType == PhysShapeType.invalid) // check for extraPhysics data
1451 { 1622 {
1452 bool vdtc; 1623 bool vdtc;
@@ -1463,10 +1634,17 @@ namespace OpenSim.Region.Framework.Scenes
1463 if (part != null) 1634 if (part != null)
1464 { 1635 {
1465 part.UpdateExtraPhysics(PhysData); 1636 part.UpdateExtraPhysics(PhysData);
1466 if (part.UpdatePhysRequired) 1637 if (part.UpdatePhysRequired && remoteClient != null)
1467 remoteClient.SendPartPhysicsProprieties(part); 1638 remoteClient.SendPartPhysicsProprieties(part);
1468 } 1639 }
1469 } 1640 }
1641
1642 if (wantedPhys != group.UsesPhysics && remoteClient != null)
1643 {
1644 remoteClient.SendAlertMessage("Object physics canceled because exceeds the limit of " +
1645 m_parentScene.m_linksetPhysCapacity + " physical prims with shape type not set to None");
1646 group.RootPart.ScheduleFullUpdate();
1647 }
1470 } 1648 }
1471 } 1649 }
1472 } 1650 }
@@ -1611,6 +1789,7 @@ namespace OpenSim.Region.Framework.Scenes
1611 { 1789 {
1612 part.Material = Convert.ToByte(material); 1790 part.Material = Convert.ToByte(material);
1613 group.HasGroupChanged = true; 1791 group.HasGroupChanged = true;
1792 remoteClient.SendPartPhysicsProprieties(part);
1614 } 1793 }
1615 } 1794 }
1616 } 1795 }
@@ -1689,12 +1868,14 @@ namespace OpenSim.Region.Framework.Scenes
1689 return; 1868 return;
1690 1869
1691 Monitor.Enter(m_updateLock); 1870 Monitor.Enter(m_updateLock);
1871
1692 try 1872 try
1693 { 1873 {
1874
1694 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); 1875 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>();
1695 1876
1696 // We do this in reverse to get the link order of the prims correct 1877 // We do this in reverse to get the link order of the prims correct
1697 for (int i = 0 ; i < children.Count ; i++) 1878 for (int i = 0; i < children.Count; i++)
1698 { 1879 {
1699 SceneObjectGroup child = children[i].ParentGroup; 1880 SceneObjectGroup child = children[i].ParentGroup;
1700 1881
@@ -1705,9 +1886,13 @@ namespace OpenSim.Region.Framework.Scenes
1705 // Make sure no child prim is set for sale 1886 // Make sure no child prim is set for sale
1706 // So that, on delink, no prims are unwittingly 1887 // So that, on delink, no prims are unwittingly
1707 // left for sale and sold off 1888 // left for sale and sold off
1708 child.RootPart.ObjectSaleType = 0; 1889
1709 child.RootPart.SalePrice = 10; 1890 if (child != null)
1710 childGroups.Add(child); 1891 {
1892 child.RootPart.ObjectSaleType = 0;
1893 child.RootPart.SalePrice = 10;
1894 childGroups.Add(child);
1895 }
1711 } 1896 }
1712 1897
1713 foreach (SceneObjectGroup child in childGroups) 1898 foreach (SceneObjectGroup child in childGroups)
@@ -1736,6 +1921,17 @@ namespace OpenSim.Region.Framework.Scenes
1736 } 1921 }
1737 finally 1922 finally
1738 { 1923 {
1924/*
1925 lock (SceneObjectGroupsByLocalPartID)
1926 {
1927 foreach (SceneObjectPart part in parentGroup.Parts)
1928 SceneObjectGroupsByLocalPartID[part.LocalId] = parentGroup;
1929 }
1930*/
1931 parentGroup.AdjustChildPrimPermissions();
1932 parentGroup.HasGroupChanged = true;
1933 parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true);
1934 parentGroup.ScheduleGroupForFullUpdate();
1739 Monitor.Exit(m_updateLock); 1935 Monitor.Exit(m_updateLock);
1740 } 1936 }
1741 } 1937 }
@@ -1777,21 +1973,23 @@ namespace OpenSim.Region.Framework.Scenes
1777 1973
1778 SceneObjectGroup group = part.ParentGroup; 1974 SceneObjectGroup group = part.ParentGroup;
1779 if (!affectedGroups.Contains(group)) 1975 if (!affectedGroups.Contains(group))
1976 {
1780 affectedGroups.Add(group); 1977 affectedGroups.Add(group);
1978 }
1781 } 1979 }
1782 } 1980 }
1783 } 1981 }
1784 1982
1785 foreach (SceneObjectPart child in childParts) 1983 if (childParts.Count > 0)
1786 { 1984 {
1787 // Unlink all child parts from their groups 1985 foreach (SceneObjectPart child in childParts)
1788 // 1986 {
1789 child.ParentGroup.DelinkFromGroup(child, true); 1987 // Unlink all child parts from their groups
1790 1988 //
1791 // These are not in affected groups and will not be 1989 child.ParentGroup.DelinkFromGroup(child, true);
1792 // handled further. Do the honors here. 1990 child.ParentGroup.HasGroupChanged = true;
1793 child.ParentGroup.HasGroupChanged = true; 1991 child.ParentGroup.ScheduleGroupForFullUpdate();
1794 child.ParentGroup.ScheduleGroupForFullUpdate(); 1992 }
1795 } 1993 }
1796 1994
1797 foreach (SceneObjectPart root in rootParts) 1995 foreach (SceneObjectPart root in rootParts)
@@ -1805,52 +2003,58 @@ namespace OpenSim.Region.Framework.Scenes
1805 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); 2003 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts);
1806 int numChildren = newSet.Count; 2004 int numChildren = newSet.Count;
1807 2005
2006 if (numChildren == 1)
2007 break;
2008
1808 // If there are prims left in a link set, but the root is 2009 // If there are prims left in a link set, but the root is
1809 // slated for unlink, we need to do this 2010 // slated for unlink, we need to do this
2011 // Unlink the remaining set
1810 // 2012 //
1811 if (numChildren != 1) 2013 bool sendEventsToRemainder = false;
1812 { 2014 if (numChildren == 2) // only one child prim no re-link needed
1813 // Unlink the remaining set 2015 sendEventsToRemainder = true;
1814 //
1815 bool sendEventsToRemainder = true;
1816 if (numChildren > 1)
1817 sendEventsToRemainder = false;
1818 2016
1819 foreach (SceneObjectPart p in newSet) 2017 foreach (SceneObjectPart p in newSet)
2018 {
2019 if (p != group.RootPart)
1820 { 2020 {
1821 if (p != group.RootPart) 2021 group.DelinkFromGroup(p, sendEventsToRemainder);
1822 group.DelinkFromGroup(p, sendEventsToRemainder); 2022 if (sendEventsToRemainder) // finish single child prim now
2023 {
2024 p.ParentGroup.HasGroupChanged = true;
2025 p.ParentGroup.ScheduleGroupForFullUpdate();
2026 }
1823 } 2027 }
2028 }
1824 2029
1825 // If there is more than one prim remaining, we 2030 // If there is more than one prim remaining, we
1826 // need to re-link 2031 // need to re-link
2032 //
2033 if (numChildren > 2)
2034 {
2035 // Remove old root
1827 // 2036 //
1828 if (numChildren > 2) 2037 if (newSet.Contains(root))
2038 newSet.Remove(root);
2039
2040 // Preserve link ordering
2041 //
2042 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1829 { 2043 {
1830 // Remove old root 2044 return a.LinkNum.CompareTo(b.LinkNum);
1831 // 2045 });
1832 if (newSet.Contains(root))
1833 newSet.Remove(root);
1834
1835 // Preserve link ordering
1836 //
1837 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1838 {
1839 return a.LinkNum.CompareTo(b.LinkNum);
1840 });
1841 2046
1842 // Determine new root 2047 // Determine new root
1843 // 2048 //
1844 SceneObjectPart newRoot = newSet[0]; 2049 SceneObjectPart newRoot = newSet[0];
1845 newSet.RemoveAt(0); 2050 newSet.RemoveAt(0);
1846 2051
1847 foreach (SceneObjectPart newChild in newSet) 2052 foreach (SceneObjectPart newChild in newSet)
1848 newChild.ClearUpdateSchedule(); 2053 newChild.ClearUpdateSchedule();
1849 2054
1850 LinkObjects(newRoot, newSet); 2055 LinkObjects(newRoot, newSet);
1851 if (!affectedGroups.Contains(newRoot.ParentGroup)) 2056// if (!affectedGroups.Contains(newRoot.ParentGroup))
1852 affectedGroups.Add(newRoot.ParentGroup); 2057// affectedGroups.Add(newRoot.ParentGroup);
1853 }
1854 } 2058 }
1855 } 2059 }
1856 2060
@@ -1858,6 +2062,12 @@ namespace OpenSim.Region.Framework.Scenes
1858 // 2062 //
1859 foreach (SceneObjectGroup g in affectedGroups) 2063 foreach (SceneObjectGroup g in affectedGroups)
1860 { 2064 {
2065 // Child prims that have been unlinked and deleted will
2066 // return unless the root is deleted. This will remove them
2067 // from the database. They will be rewritten immediately,
2068 // minus the rows for the unlinked child prims.
2069 g.AdjustChildPrimPermissions();
2070 m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID);
1861 g.TriggerScriptChangedEvent(Changed.LINK); 2071 g.TriggerScriptChangedEvent(Changed.LINK);
1862 g.HasGroupChanged = true; // Persist 2072 g.HasGroupChanged = true; // Persist
1863 g.ScheduleGroupForFullUpdate(); 2073 g.ScheduleGroupForFullUpdate();
@@ -1931,54 +2141,63 @@ namespace OpenSim.Region.Framework.Scenes
1931 /// <param name="GroupID"></param> 2141 /// <param name="GroupID"></param>
1932 /// <param name="rot"></param> 2142 /// <param name="rot"></param>
1933 /// <returns>null if duplication fails, otherwise the duplicated object</returns> 2143 /// <returns>null if duplication fails, otherwise the duplicated object</returns>
1934 public SceneObjectGroup DuplicateObject( 2144 /// <summary>
1935 uint originalPrimID, Vector3 offset, uint flags, UUID AgentID, UUID GroupID, Quaternion rot) 2145 public SceneObjectGroup DuplicateObject(uint originalPrimID, Vector3 offset, uint flags, UUID AgentID, UUID GroupID, Quaternion rot)
1936 { 2146 {
1937 Monitor.Enter(m_updateLock); 2147// m_log.DebugFormat(
2148// "[SCENE]: Duplication of object {0} at offset {1} requested by agent {2}",
2149// originalPrimID, offset, AgentID);
1938 2150
1939 try 2151 SceneObjectGroup original = GetGroupByPrim(originalPrimID);
2152 if (original != null)
1940 { 2153 {
1941 // m_log.DebugFormat( 2154 if (m_parentScene.Permissions.CanDuplicateObject(
1942 // "[SCENE]: Duplication of object {0} at offset {1} requested by agent {2}", 2155 original.PrimCount, original.UUID, AgentID, original.AbsolutePosition))
1943 // originalPrimID, offset, AgentID);
1944
1945 SceneObjectGroup original = GetGroupByPrim(originalPrimID);
1946 if (original == null)
1947 { 2156 {
2157<<<<<<< HEAD
1948 m_log.WarnFormat( 2158 m_log.WarnFormat(
1949 "[SCENEGRAPH]: Attempt to duplicate nonexistent prim id {0} by {1}", originalPrimID, AgentID); 2159 "[SCENEGRAPH]: Attempt to duplicate nonexistent prim id {0} by {1}", originalPrimID, AgentID);
2160=======
2161 SceneObjectGroup copy = original.Copy(true);
2162 copy.AbsolutePosition = copy.AbsolutePosition + offset;
2163>>>>>>> avn/ubitvar
1950 2164
1951 return null; 2165 if (original.OwnerID != AgentID)
1952 } 2166 {
2167 copy.SetOwnerId(AgentID);
2168 copy.SetRootPartOwner(copy.RootPart, AgentID, GroupID);
1953 2169
1954 if (!m_parentScene.Permissions.CanDuplicateObject( 2170 SceneObjectPart[] partList = copy.Parts;
1955 original.PrimCount, original.UUID, AgentID, original.AbsolutePosition))
1956 return null;
1957 2171
1958 SceneObjectGroup copy = original.Copy(true); 2172 if (m_parentScene.Permissions.PropagatePermissions())
1959 copy.AbsolutePosition = copy.AbsolutePosition + offset; 2173 {
2174 foreach (SceneObjectPart child in partList)
2175 {
2176 child.Inventory.ChangeInventoryOwner(AgentID);
2177 child.TriggerScriptChangedEvent(Changed.OWNER);
2178 child.ApplyNextOwnerPermissions();
2179 }
2180 }
2181 }
1960 2182
1961 if (original.OwnerID != AgentID) 2183 // FIXME: This section needs to be refactored so that it just calls AddSceneObject()
1962 { 2184 Entities.Add(copy);
1963 copy.SetOwnerId(AgentID);
1964 copy.SetRootPartOwner(copy.RootPart, AgentID, GroupID);
1965 2185
1966 SceneObjectPart[] partList = copy.Parts; 2186 lock (SceneObjectGroupsByFullID)
2187 SceneObjectGroupsByFullID[copy.UUID] = copy;
1967 2188
1968 if (m_parentScene.Permissions.PropagatePermissions()) 2189 SceneObjectPart[] parts = copy.Parts;
2190 foreach (SceneObjectPart part in parts)
1969 { 2191 {
1970 foreach (SceneObjectPart child in partList) 2192 lock (SceneObjectGroupsByFullPartID)
1971 { 2193 SceneObjectGroupsByFullPartID[part.UUID] = copy;
1972 child.Inventory.ChangeInventoryOwner(AgentID); 2194 lock (SceneObjectGroupsByLocalPartID)
1973 child.TriggerScriptChangedEvent(Changed.OWNER); 2195 SceneObjectGroupsByLocalPartID[part.LocalId] = copy;
1974 child.ApplyNextOwnerPermissions();
1975 }
1976 } 2196 }
1977 2197
1978 copy.RootPart.ObjectSaleType = 0; 2198 // PROBABLE END OF FIXME
1979 copy.RootPart.SalePrice = 10;
1980 }
1981 2199
2200<<<<<<< HEAD
1982 // FIXME: This section needs to be refactored so that it just calls AddSceneObject() 2201 // FIXME: This section needs to be refactored so that it just calls AddSceneObject()
1983 Entities.Add(copy); 2202 Entities.Add(copy);
1984 2203
@@ -2027,24 +2246,41 @@ namespace OpenSim.Region.Framework.Scenes
2027 { 2246 {
2028 copy.UpdateGroupRotationR(rot); 2247 copy.UpdateGroupRotationR(rot);
2029 } 2248 }
2249=======
2250 // Since we copy from a source group that is in selected
2251 // state, but the copy is shown deselected in the viewer,
2252 // We need to clear the selection flag here, else that
2253 // prim never gets persisted at all. The client doesn't
2254 // think it's selected, so it will never send a deselect...
2255 copy.IsSelected = false;
2256>>>>>>> avn/ubitvar
2257
2258 m_numPrim += copy.Parts.Length;
2259
2260 if (rot != Quaternion.Identity)
2261 {
2262 copy.UpdateGroupRotationR(rot);
2263 }
2030 2264
2031 copy.CreateScriptInstances(0, false, m_parentScene.DefaultScriptEngine, 1); 2265 copy.CreateScriptInstances(0, false, m_parentScene.DefaultScriptEngine, 1);
2032 copy.HasGroupChanged = true; 2266 copy.HasGroupChanged = true;
2033 copy.ScheduleGroupForFullUpdate(); 2267 copy.ScheduleGroupForFullUpdate();
2034 copy.ResumeScripts(); 2268 copy.ResumeScripts();
2035 2269
2036 // required for physics to update it's position 2270 // required for physics to update it's position
2037 copy.AbsolutePosition = copy.AbsolutePosition; 2271 copy.AbsolutePosition = copy.AbsolutePosition;
2038 2272
2039 return copy; 2273 return copy;
2274 }
2040 } 2275 }
2041 finally 2276 else
2042 { 2277 {
2043 Monitor.Exit(m_updateLock); 2278 m_log.WarnFormat("[SCENE]: Attempted to duplicate nonexistant prim id {0}", GroupID);
2044 } 2279 }
2280
2281 return null;
2045 } 2282 }
2046 2283
2047 /// <summary>
2048 /// Calculates the distance between two Vector3s 2284 /// Calculates the distance between two Vector3s
2049 /// </summary> 2285 /// </summary>
2050 /// <param name="v1"></param> 2286 /// <param name="v1"></param>