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.cs542
1 files changed, 364 insertions, 178 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index e0080f2..0879cce 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
@@ -134,13 +144,18 @@ namespace OpenSim.Region.Framework.Scenes
134 144
135 protected internal void Close() 145 protected internal void Close()
136 { 146 {
137 lock (m_presenceLock) 147 m_scenePresencesLock.EnterWriteLock();
148 try
138 { 149 {
139 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(); 150 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>();
140 List<ScenePresence> newlist = new List<ScenePresence>(); 151 List<ScenePresence> newlist = new List<ScenePresence>();
141 m_scenePresenceMap = newmap; 152 m_scenePresenceMap = newmap;
142 m_scenePresenceArray = newlist; 153 m_scenePresenceArray = newlist;
143 } 154 }
155 finally
156 {
157 m_scenePresencesLock.ExitWriteLock();
158 }
144 159
145 lock (SceneObjectGroupsByFullID) 160 lock (SceneObjectGroupsByFullID)
146 SceneObjectGroupsByFullID.Clear(); 161 SceneObjectGroupsByFullID.Clear();
@@ -207,6 +222,12 @@ namespace OpenSim.Region.Framework.Scenes
207 return PhysicsScene.Simulate((float)elapsed); 222 return PhysicsScene.Simulate((float)elapsed);
208 } 223 }
209 224
225 protected internal void ProcessPhysicsPreSimulation()
226 {
227 if(PhysicsScene != null)
228 PhysicsScene.ProcessPreSimulation();
229 }
230
210 protected internal void UpdateScenePresenceMovement() 231 protected internal void UpdateScenePresenceMovement()
211 { 232 {
212 ForEachScenePresence(delegate(ScenePresence presence) 233 ForEachScenePresence(delegate(ScenePresence presence)
@@ -261,13 +282,54 @@ namespace OpenSim.Region.Framework.Scenes
261 protected internal bool AddRestoredSceneObject( 282 protected internal bool AddRestoredSceneObject(
262 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 283 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
263 { 284 {
285 if (!m_parentScene.CombineRegions)
286 {
287 // temporary checks to remove after varsize suport
288 float regionSizeX = m_parentScene.RegionInfo.RegionSizeX;
289 if (regionSizeX == 0)
290 regionSizeX = Constants.RegionSize;
291 float regionSizeY = m_parentScene.RegionInfo.RegionSizeY;
292 if (regionSizeY == 0)
293 regionSizeY = Constants.RegionSize;
294
295 // KF: Check for out-of-region, move inside and make static.
296 Vector3 npos = new Vector3(sceneObject.RootPart.GroupPosition.X,
297 sceneObject.RootPart.GroupPosition.Y,
298 sceneObject.RootPart.GroupPosition.Z);
299 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 ||
300 npos.X > regionSizeX ||
301 npos.Y > regionSizeY))
302 {
303 if (npos.X < 0.0) npos.X = 1.0f;
304 if (npos.Y < 0.0) npos.Y = 1.0f;
305 if (npos.Z < 0.0) npos.Z = 0.0f;
306 if (npos.X > regionSizeX) npos.X = regionSizeX - 1.0f;
307 if (npos.Y > regionSizeY) npos.Y = regionSizeY - 1.0f;
308
309 SceneObjectPart rootpart = sceneObject.RootPart;
310 rootpart.GroupPosition = npos;
311
312 foreach (SceneObjectPart part in sceneObject.Parts)
313 {
314 if (part == rootpart)
315 continue;
316 part.GroupPosition = npos;
317 }
318 rootpart.Velocity = Vector3.Zero;
319 rootpart.AngularVelocity = Vector3.Zero;
320 rootpart.Acceleration = Vector3.Zero;
321 }
322 }
323
324 bool ret = AddSceneObject(sceneObject, attachToBackup, sendClientUpdates);
325
264 if (attachToBackup && (!alreadyPersisted)) 326 if (attachToBackup && (!alreadyPersisted))
265 { 327 {
266 sceneObject.ForceInventoryPersistence(); 328 sceneObject.ForceInventoryPersistence();
267 sceneObject.HasGroupChanged = true; 329 sceneObject.HasGroupChanged = true;
268 } 330 }
269 331
270 return AddSceneObject(sceneObject, attachToBackup, sendClientUpdates); 332 return ret;
271 } 333 }
272 334
273 /// <summary> 335 /// <summary>
@@ -284,12 +346,16 @@ namespace OpenSim.Region.Framework.Scenes
284 /// </returns> 346 /// </returns>
285 protected internal bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) 347 protected internal bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates)
286 { 348 {
287 // Ensure that we persist this new scene object if it's not an 349
350 bool ret = AddSceneObject(sceneObject, attachToBackup, sendClientUpdates);
351
352 // Ensure that we persist this new scene object if it's not an
288 // attachment 353 // attachment
354
289 if (attachToBackup) 355 if (attachToBackup)
290 sceneObject.HasGroupChanged = true; 356 sceneObject.HasGroupChanged = true;
291 357
292 return AddSceneObject(sceneObject, attachToBackup, sendClientUpdates); 358 return ret;
293 } 359 }
294 360
295 /// <summary> 361 /// <summary>
@@ -324,9 +390,8 @@ namespace OpenSim.Region.Framework.Scenes
324 if (pa != null && pa.IsPhysical && vel != Vector3.Zero) 390 if (pa != null && pa.IsPhysical && vel != Vector3.Zero)
325 { 391 {
326 sceneObject.RootPart.ApplyImpulse((vel * sceneObject.GetMass()), false); 392 sceneObject.RootPart.ApplyImpulse((vel * sceneObject.GetMass()), false);
327 sceneObject.Velocity = vel;
328 } 393 }
329 394
330 return true; 395 return true;
331 } 396 }
332 397
@@ -351,6 +416,11 @@ namespace OpenSim.Region.Framework.Scenes
351 /// </returns> 416 /// </returns>
352 protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) 417 protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates)
353 { 418 {
419 if (sceneObject == null)
420 {
421 m_log.ErrorFormat("[SCENEGRAPH]: Tried to add null scene object");
422 return false;
423 }
354 if (sceneObject.UUID == UUID.Zero) 424 if (sceneObject.UUID == UUID.Zero)
355 { 425 {
356 m_log.ErrorFormat( 426 m_log.ErrorFormat(
@@ -383,9 +453,9 @@ namespace OpenSim.Region.Framework.Scenes
383 { 453 {
384 Vector3 scale = part.Shape.Scale; 454 Vector3 scale = part.Shape.Scale;
385 455
386 scale.X = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.X)); 456 scale.X = Util.Clamp(scale.X, m_parentScene.m_minNonphys, m_parentScene.m_maxNonphys);
387 scale.Y = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.Y)); 457 scale.Y = Util.Clamp(scale.Y, m_parentScene.m_minNonphys, m_parentScene.m_maxNonphys);
388 scale.Z = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.Z)); 458 scale.Z = Util.Clamp(scale.Z, m_parentScene.m_minNonphys, m_parentScene.m_maxNonphys);
389 459
390 part.Shape.Scale = scale; 460 part.Shape.Scale = scale;
391 } 461 }
@@ -406,36 +476,39 @@ namespace OpenSim.Region.Framework.Scenes
406 476
407 sceneObject.AttachToScene(m_parentScene); 477 sceneObject.AttachToScene(m_parentScene);
408 478
409 if (sendClientUpdates)
410 sceneObject.ScheduleGroupForFullUpdate();
411
412 Entities.Add(sceneObject); 479 Entities.Add(sceneObject);
413 480
414 if (attachToBackup)
415 sceneObject.AttachToBackup();
416
417 lock (SceneObjectGroupsByFullID) 481 lock (SceneObjectGroupsByFullID)
418 SceneObjectGroupsByFullID[sceneObject.UUID] = sceneObject; 482 SceneObjectGroupsByFullID[sceneObject.UUID] = sceneObject;
419 483
420 lock (SceneObjectGroupsByFullPartID) 484 foreach (SceneObjectPart part in parts)
421 { 485 {
422 foreach (SceneObjectPart part in parts) 486 lock (SceneObjectGroupsByFullPartID)
423 SceneObjectGroupsByFullPartID[part.UUID] = sceneObject; 487 SceneObjectGroupsByFullPartID[part.UUID] = sceneObject;
424 }
425
426 lock (SceneObjectGroupsByLocalPartID)
427 {
428// m_log.DebugFormat(
429// "[SCENE GRAPH]: Adding scene object {0} {1} {2} to SceneObjectGroupsByLocalPartID in {3}",
430// sceneObject.Name, sceneObject.UUID, sceneObject.LocalId, m_parentScene.RegionInfo.RegionName);
431 488
432 foreach (SceneObjectPart part in parts) 489 lock (SceneObjectGroupsByLocalPartID)
433 SceneObjectGroupsByLocalPartID[part.LocalId] = sceneObject; 490 SceneObjectGroupsByLocalPartID[part.LocalId] = sceneObject;
434 } 491 }
435 492
493 if (sendClientUpdates)
494 sceneObject.ScheduleGroupForFullUpdate();
495
496 if (attachToBackup)
497 sceneObject.AttachToBackup();
498
436 return true; 499 return true;
437 } 500 }
438 501
502 public void updateScenePartGroup(SceneObjectPart part, SceneObjectGroup grp)
503 {
504 // no tests, caller has responsability...
505 lock (SceneObjectGroupsByFullPartID)
506 SceneObjectGroupsByFullPartID[part.UUID] = grp;
507
508 lock (SceneObjectGroupsByLocalPartID)
509 SceneObjectGroupsByLocalPartID[part.LocalId] = grp;
510 }
511
439 /// <summary> 512 /// <summary>
440 /// Delete an object from the scene 513 /// Delete an object from the scene
441 /// </summary> 514 /// </summary>
@@ -476,25 +549,23 @@ namespace OpenSim.Region.Framework.Scenes
476 if ((grp.RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics) 549 if ((grp.RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics)
477 RemovePhysicalPrim(grp.PrimCount); 550 RemovePhysicalPrim(grp.PrimCount);
478 } 551 }
479 552
553 bool ret = Entities.Remove(uuid);
554
480 lock (SceneObjectGroupsByFullID) 555 lock (SceneObjectGroupsByFullID)
481 SceneObjectGroupsByFullID.Remove(grp.UUID); 556 SceneObjectGroupsByFullID.Remove(grp.UUID);
482 557
483 lock (SceneObjectGroupsByFullPartID) 558 SceneObjectPart[] parts = grp.Parts;
559 for (int i = 0; i < parts.Length; i++)
484 { 560 {
485 SceneObjectPart[] parts = grp.Parts; 561 lock (SceneObjectGroupsByFullPartID)
486 for (int i = 0; i < parts.Length; i++)
487 SceneObjectGroupsByFullPartID.Remove(parts[i].UUID); 562 SceneObjectGroupsByFullPartID.Remove(parts[i].UUID);
488 }
489 563
490 lock (SceneObjectGroupsByLocalPartID) 564 lock (SceneObjectGroupsByLocalPartID)
491 {
492 SceneObjectPart[] parts = grp.Parts;
493 for (int i = 0; i < parts.Length; i++)
494 SceneObjectGroupsByLocalPartID.Remove(parts[i].LocalId); 565 SceneObjectGroupsByLocalPartID.Remove(parts[i].LocalId);
495 } 566 }
496 567
497 return Entities.Remove(uuid); 568 return ret;
498 } 569 }
499 570
500 /// <summary> 571 /// <summary>
@@ -509,6 +580,30 @@ namespace OpenSim.Region.Framework.Scenes
509 m_updateList[obj.UUID] = obj; 580 m_updateList[obj.UUID] = obj;
510 } 581 }
511 582
583 public void FireAttachToBackup(SceneObjectGroup obj)
584 {
585 if (OnAttachToBackup != null)
586 {
587 OnAttachToBackup(obj);
588 }
589 }
590
591 public void FireDetachFromBackup(SceneObjectGroup obj)
592 {
593 if (OnDetachFromBackup != null)
594 {
595 OnDetachFromBackup(obj);
596 }
597 }
598
599 public void FireChangeBackup(SceneObjectGroup obj)
600 {
601 if (OnChangeBackup != null)
602 {
603 OnChangeBackup(obj);
604 }
605 }
606
512 /// <summary> 607 /// <summary>
513 /// Process all pending updates 608 /// Process all pending updates
514 /// </summary> 609 /// </summary>
@@ -600,7 +695,8 @@ namespace OpenSim.Region.Framework.Scenes
600 695
601 Entities[presence.UUID] = presence; 696 Entities[presence.UUID] = presence;
602 697
603 lock (m_presenceLock) 698 m_scenePresencesLock.EnterWriteLock();
699 try
604 { 700 {
605 m_numChildAgents++; 701 m_numChildAgents++;
606 702
@@ -626,6 +722,10 @@ namespace OpenSim.Region.Framework.Scenes
626 m_scenePresenceMap = newmap; 722 m_scenePresenceMap = newmap;
627 m_scenePresenceArray = newlist; 723 m_scenePresenceArray = newlist;
628 } 724 }
725 finally
726 {
727 m_scenePresencesLock.ExitWriteLock();
728 }
629 729
630 return presence; 730 return presence;
631 } 731 }
@@ -642,7 +742,8 @@ namespace OpenSim.Region.Framework.Scenes
642 agentID); 742 agentID);
643 } 743 }
644 744
645 lock (m_presenceLock) 745 m_scenePresencesLock.EnterWriteLock();
746 try
646 { 747 {
647 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 748 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
648 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 749 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -664,6 +765,10 @@ namespace OpenSim.Region.Framework.Scenes
664 m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); 765 m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID);
665 } 766 }
666 } 767 }
768 finally
769 {
770 m_scenePresencesLock.ExitWriteLock();
771 }
667 } 772 }
668 773
669 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) 774 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F)
@@ -892,7 +997,7 @@ namespace OpenSim.Region.Framework.Scenes
892 m_log.WarnFormat( 997 m_log.WarnFormat(
893 "[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}.", 998 "[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}.",
894 sog.Name, sog.UUID, sog.LocalId, localID, m_parentScene.RegionInfo.RegionName); 999 sog.Name, sog.UUID, sog.LocalId, localID, m_parentScene.RegionInfo.RegionName);
895 1000 m_log.WarnFormat("stack: {0}", Environment.StackTrace);
896 SceneObjectGroupsByLocalPartID.Remove(localID); 1001 SceneObjectGroupsByLocalPartID.Remove(localID);
897 } 1002 }
898 } 1003 }
@@ -1228,6 +1333,52 @@ namespace OpenSim.Region.Framework.Scenes
1228 1333
1229 #region Client Event handlers 1334 #region Client Event handlers
1230 1335
1336 protected internal void ClientChangeObject(uint localID, object odata, IClientAPI remoteClient)
1337 {
1338 SceneObjectPart part = GetSceneObjectPart(localID);
1339 ObjectChangeData data = (ObjectChangeData)odata;
1340
1341 if (part != null)
1342 {
1343 SceneObjectGroup grp = part.ParentGroup;
1344 if (grp != null)
1345 {
1346 if (m_parentScene.Permissions.CanEditObject(grp.UUID, remoteClient.AgentId))
1347 {
1348 // These two are exceptions SL makes in the interpretation
1349 // of the change flags. Must check them here because otherwise
1350 // the group flag (see below) would be lost
1351 if (data.change == ObjectChangeType.groupS)
1352 data.change = ObjectChangeType.primS;
1353 if (data.change == ObjectChangeType.groupPS)
1354 data.change = ObjectChangeType.primPS;
1355 part.StoreUndoState(data.change); // lets test only saving what we changed
1356 grp.doChangeObject(part, (ObjectChangeData)data);
1357 }
1358 else
1359 {
1360 // Is this any kind of group operation?
1361 if ((data.change & ObjectChangeType.Group) != 0)
1362 {
1363 // Is a move and/or rotation requested?
1364 if ((data.change & (ObjectChangeType.Position | ObjectChangeType.Rotation)) != 0)
1365 {
1366 // Are we allowed to move it?
1367 if (m_parentScene.Permissions.CanMoveObject(grp.UUID, remoteClient.AgentId))
1368 {
1369 // Strip all but move and rotation from request
1370 data.change &= (ObjectChangeType.Group | ObjectChangeType.Position | ObjectChangeType.Rotation);
1371
1372 part.StoreUndoState(data.change);
1373 grp.doChangeObject(part, (ObjectChangeData)data);
1374 }
1375 }
1376 }
1377 }
1378 }
1379 }
1380 }
1381
1231 /// <summary> 1382 /// <summary>
1232 /// Update the scale of an individual prim. 1383 /// Update the scale of an individual prim.
1233 /// </summary> 1384 /// </summary>
@@ -1242,7 +1393,17 @@ namespace OpenSim.Region.Framework.Scenes
1242 { 1393 {
1243 if (m_parentScene.Permissions.CanEditObject(part.ParentGroup.UUID, remoteClient.AgentId)) 1394 if (m_parentScene.Permissions.CanEditObject(part.ParentGroup.UUID, remoteClient.AgentId))
1244 { 1395 {
1396 bool physbuild = false;
1397 if (part.ParentGroup.RootPart.PhysActor != null)
1398 {
1399 part.ParentGroup.RootPart.PhysActor.Building = true;
1400 physbuild = true;
1401 }
1402
1245 part.Resize(scale); 1403 part.Resize(scale);
1404
1405 if (physbuild)
1406 part.ParentGroup.RootPart.PhysActor.Building = false;
1246 } 1407 }
1247 } 1408 }
1248 } 1409 }
@@ -1254,7 +1415,17 @@ namespace OpenSim.Region.Framework.Scenes
1254 { 1415 {
1255 if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) 1416 if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId))
1256 { 1417 {
1418 bool physbuild = false;
1419 if (group.RootPart.PhysActor != null)
1420 {
1421 group.RootPart.PhysActor.Building = true;
1422 physbuild = true;
1423 }
1424
1257 group.GroupResize(scale); 1425 group.GroupResize(scale);
1426
1427 if (physbuild)
1428 group.RootPart.PhysActor.Building = false;
1258 } 1429 }
1259 } 1430 }
1260 } 1431 }
@@ -1393,8 +1564,13 @@ namespace OpenSim.Region.Framework.Scenes
1393 { 1564 {
1394 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) 1565 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0))
1395 { 1566 {
1396 if (m_parentScene.AttachmentsModule != null) 1567 // Set the new attachment point data in the object
1397 m_parentScene.AttachmentsModule.UpdateAttachmentPosition(group, pos); 1568 byte attachmentPoint = group.GetAttachmentPoint();
1569 group.UpdateGroupPosition(pos);
1570 group.IsAttachment = false;
1571 group.AbsolutePosition = group.RootPart.AttachedPos;
1572 group.AttachmentPoint = attachmentPoint;
1573 group.HasGroupChanged = true;
1398 } 1574 }
1399 else 1575 else
1400 { 1576 {
@@ -1452,6 +1628,7 @@ namespace OpenSim.Region.Framework.Scenes
1452 // VolumeDetect can't be set via UI and will always be off when a change is made there 1628 // VolumeDetect can't be set via UI and will always be off when a change is made there
1453 // now only change volume dtc if phantom off 1629 // now only change volume dtc if phantom off
1454 1630
1631 bool wantedPhys = UsePhysics;
1455 if (PhysData.PhysShapeType == PhysShapeType.invalid) // check for extraPhysics data 1632 if (PhysData.PhysShapeType == PhysShapeType.invalid) // check for extraPhysics data
1456 { 1633 {
1457 bool vdtc; 1634 bool vdtc;
@@ -1468,10 +1645,17 @@ namespace OpenSim.Region.Framework.Scenes
1468 if (part != null) 1645 if (part != null)
1469 { 1646 {
1470 part.UpdateExtraPhysics(PhysData); 1647 part.UpdateExtraPhysics(PhysData);
1471 if (part.UpdatePhysRequired) 1648 if (part.UpdatePhysRequired && remoteClient != null)
1472 remoteClient.SendPartPhysicsProprieties(part); 1649 remoteClient.SendPartPhysicsProprieties(part);
1473 } 1650 }
1474 } 1651 }
1652
1653 if (wantedPhys != group.UsesPhysics && remoteClient != null)
1654 {
1655 remoteClient.SendAlertMessage("Object physics canceled because exceeds the limit of " +
1656 m_parentScene.m_linksetPhysCapacity + " physical prims with shape type not set to None");
1657 group.RootPart.ScheduleFullUpdate();
1658 }
1475 } 1659 }
1476 } 1660 }
1477 } 1661 }
@@ -1616,6 +1800,7 @@ namespace OpenSim.Region.Framework.Scenes
1616 { 1800 {
1617 part.Material = Convert.ToByte(material); 1801 part.Material = Convert.ToByte(material);
1618 group.HasGroupChanged = true; 1802 group.HasGroupChanged = true;
1803 remoteClient.SendPartPhysicsProprieties(part);
1619 } 1804 }
1620 } 1805 }
1621 } 1806 }
@@ -1694,12 +1879,14 @@ namespace OpenSim.Region.Framework.Scenes
1694 return; 1879 return;
1695 1880
1696 Monitor.Enter(m_updateLock); 1881 Monitor.Enter(m_updateLock);
1882
1697 try 1883 try
1698 { 1884 {
1885
1699 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); 1886 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>();
1700 1887
1701 // We do this in reverse to get the link order of the prims correct 1888 // We do this in reverse to get the link order of the prims correct
1702 for (int i = 0 ; i < children.Count ; i++) 1889 for (int i = 0; i < children.Count; i++)
1703 { 1890 {
1704 SceneObjectGroup child = children[i].ParentGroup; 1891 SceneObjectGroup child = children[i].ParentGroup;
1705 1892
@@ -1710,9 +1897,13 @@ namespace OpenSim.Region.Framework.Scenes
1710 // Make sure no child prim is set for sale 1897 // Make sure no child prim is set for sale
1711 // So that, on delink, no prims are unwittingly 1898 // So that, on delink, no prims are unwittingly
1712 // left for sale and sold off 1899 // left for sale and sold off
1713 child.RootPart.ObjectSaleType = 0; 1900
1714 child.RootPart.SalePrice = 10; 1901 if (child != null)
1715 childGroups.Add(child); 1902 {
1903 child.RootPart.ObjectSaleType = 0;
1904 child.RootPart.SalePrice = 10;
1905 childGroups.Add(child);
1906 }
1716 } 1907 }
1717 1908
1718 foreach (SceneObjectGroup child in childGroups) 1909 foreach (SceneObjectGroup child in childGroups)
@@ -1741,6 +1932,17 @@ namespace OpenSim.Region.Framework.Scenes
1741 } 1932 }
1742 finally 1933 finally
1743 { 1934 {
1935/*
1936 lock (SceneObjectGroupsByLocalPartID)
1937 {
1938 foreach (SceneObjectPart part in parentGroup.Parts)
1939 SceneObjectGroupsByLocalPartID[part.LocalId] = parentGroup;
1940 }
1941*/
1942 parentGroup.AdjustChildPrimPermissions(false);
1943 parentGroup.HasGroupChanged = true;
1944 parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true);
1945 parentGroup.ScheduleGroupForFullUpdate();
1744 Monitor.Exit(m_updateLock); 1946 Monitor.Exit(m_updateLock);
1745 } 1947 }
1746 } 1948 }
@@ -1782,21 +1984,23 @@ namespace OpenSim.Region.Framework.Scenes
1782 1984
1783 SceneObjectGroup group = part.ParentGroup; 1985 SceneObjectGroup group = part.ParentGroup;
1784 if (!affectedGroups.Contains(group)) 1986 if (!affectedGroups.Contains(group))
1987 {
1785 affectedGroups.Add(group); 1988 affectedGroups.Add(group);
1989 }
1786 } 1990 }
1787 } 1991 }
1788 } 1992 }
1789 1993
1790 foreach (SceneObjectPart child in childParts) 1994 if (childParts.Count > 0)
1791 { 1995 {
1792 // Unlink all child parts from their groups 1996 foreach (SceneObjectPart child in childParts)
1793 // 1997 {
1794 child.ParentGroup.DelinkFromGroup(child, true); 1998 // Unlink all child parts from their groups
1795 1999 //
1796 // These are not in affected groups and will not be 2000 child.ParentGroup.DelinkFromGroup(child, true);
1797 // handled further. Do the honors here. 2001 child.ParentGroup.HasGroupChanged = true;
1798 child.ParentGroup.HasGroupChanged = true; 2002 child.ParentGroup.ScheduleGroupForFullUpdate();
1799 child.ParentGroup.ScheduleGroupForFullUpdate(); 2003 }
1800 } 2004 }
1801 2005
1802 foreach (SceneObjectPart root in rootParts) 2006 foreach (SceneObjectPart root in rootParts)
@@ -1810,52 +2014,58 @@ namespace OpenSim.Region.Framework.Scenes
1810 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); 2014 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts);
1811 int numChildren = newSet.Count; 2015 int numChildren = newSet.Count;
1812 2016
2017 if (numChildren == 1)
2018 break;
2019
1813 // If there are prims left in a link set, but the root is 2020 // If there are prims left in a link set, but the root is
1814 // slated for unlink, we need to do this 2021 // slated for unlink, we need to do this
2022 // Unlink the remaining set
1815 // 2023 //
1816 if (numChildren != 1) 2024 bool sendEventsToRemainder = false;
1817 { 2025 if (numChildren == 2) // only one child prim no re-link needed
1818 // Unlink the remaining set 2026 sendEventsToRemainder = true;
1819 //
1820 bool sendEventsToRemainder = true;
1821 if (numChildren > 1)
1822 sendEventsToRemainder = false;
1823 2027
1824 foreach (SceneObjectPart p in newSet) 2028 foreach (SceneObjectPart p in newSet)
2029 {
2030 if (p != group.RootPart)
1825 { 2031 {
1826 if (p != group.RootPart) 2032 group.DelinkFromGroup(p, sendEventsToRemainder);
1827 group.DelinkFromGroup(p, sendEventsToRemainder); 2033 if (sendEventsToRemainder) // finish single child prim now
2034 {
2035 p.ParentGroup.HasGroupChanged = true;
2036 p.ParentGroup.ScheduleGroupForFullUpdate();
2037 }
1828 } 2038 }
2039 }
2040
2041 // If there is more than one prim remaining, we
2042 // need to re-link
2043 //
2044 if (numChildren > 2)
2045 {
2046 // Remove old root
2047 //
2048 if (newSet.Contains(root))
2049 newSet.Remove(root);
1829 2050
1830 // If there is more than one prim remaining, we 2051 // Preserve link ordering
1831 // need to re-link
1832 // 2052 //
1833 if (numChildren > 2) 2053 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1834 { 2054 {
1835 // Remove old root 2055 return a.LinkNum.CompareTo(b.LinkNum);
1836 // 2056 });
1837 if (newSet.Contains(root))
1838 newSet.Remove(root);
1839
1840 // Preserve link ordering
1841 //
1842 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1843 {
1844 return a.LinkNum.CompareTo(b.LinkNum);
1845 });
1846 2057
1847 // Determine new root 2058 // Determine new root
1848 // 2059 //
1849 SceneObjectPart newRoot = newSet[0]; 2060 SceneObjectPart newRoot = newSet[0];
1850 newSet.RemoveAt(0); 2061 newSet.RemoveAt(0);
1851 2062
1852 foreach (SceneObjectPart newChild in newSet) 2063 foreach (SceneObjectPart newChild in newSet)
1853 newChild.ClearUpdateSchedule(); 2064 newChild.ClearUpdateSchedule();
1854 2065
1855 LinkObjects(newRoot, newSet); 2066 LinkObjects(newRoot, newSet);
1856 if (!affectedGroups.Contains(newRoot.ParentGroup)) 2067// if (!affectedGroups.Contains(newRoot.ParentGroup))
1857 affectedGroups.Add(newRoot.ParentGroup); 2068// affectedGroups.Add(newRoot.ParentGroup);
1858 }
1859 } 2069 }
1860 } 2070 }
1861 2071
@@ -1863,6 +2073,12 @@ namespace OpenSim.Region.Framework.Scenes
1863 // 2073 //
1864 foreach (SceneObjectGroup g in affectedGroups) 2074 foreach (SceneObjectGroup g in affectedGroups)
1865 { 2075 {
2076 // Child prims that have been unlinked and deleted will
2077 // return unless the root is deleted. This will remove them
2078 // from the database. They will be rewritten immediately,
2079 // minus the rows for the unlinked child prims.
2080 g.AdjustChildPrimPermissions(false);
2081 m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID);
1866 g.TriggerScriptChangedEvent(Changed.LINK); 2082 g.TriggerScriptChangedEvent(Changed.LINK);
1867 g.HasGroupChanged = true; // Persist 2083 g.HasGroupChanged = true; // Persist
1868 g.ScheduleGroupForFullUpdate(); 2084 g.ScheduleGroupForFullUpdate();
@@ -1936,120 +2152,90 @@ namespace OpenSim.Region.Framework.Scenes
1936 /// <param name="GroupID"></param> 2152 /// <param name="GroupID"></param>
1937 /// <param name="rot"></param> 2153 /// <param name="rot"></param>
1938 /// <returns>null if duplication fails, otherwise the duplicated object</returns> 2154 /// <returns>null if duplication fails, otherwise the duplicated object</returns>
1939 public SceneObjectGroup DuplicateObject( 2155 /// <summary>
1940 uint originalPrimID, Vector3 offset, uint flags, UUID AgentID, UUID GroupID, Quaternion rot) 2156 public SceneObjectGroup DuplicateObject(uint originalPrimID, Vector3 offset, uint flags, UUID AgentID, UUID GroupID, Quaternion rot)
1941 { 2157 {
1942 Monitor.Enter(m_updateLock); 2158// m_log.DebugFormat(
2159// "[SCENE]: Duplication of object {0} at offset {1} requested by agent {2}",
2160// originalPrimID, offset, AgentID);
1943 2161
1944 try 2162 SceneObjectGroup original = GetGroupByPrim(originalPrimID);
2163 if (original != null)
1945 { 2164 {
1946 // m_log.DebugFormat( 2165 if (m_parentScene.Permissions.CanDuplicateObject(
1947 // "[SCENE]: Duplication of object {0} at offset {1} requested by agent {2}",
1948 // originalPrimID, offset, AgentID);
1949
1950 SceneObjectGroup original = GetGroupByPrim(originalPrimID);
1951 if (original == null)
1952 {
1953 m_log.WarnFormat(
1954 "[SCENEGRAPH]: Attempt to duplicate nonexistent prim id {0} by {1}", originalPrimID, AgentID);
1955
1956 return null;
1957 }
1958
1959 if (!m_parentScene.Permissions.CanDuplicateObject(
1960 original.PrimCount, original.UUID, AgentID, original.AbsolutePosition)) 2166 original.PrimCount, original.UUID, AgentID, original.AbsolutePosition))
1961 return null;
1962
1963 SceneObjectGroup copy = original.Copy(true);
1964 copy.AbsolutePosition = copy.AbsolutePosition + offset;
1965
1966 if (original.OwnerID != AgentID)
1967 { 2167 {
1968 copy.SetOwnerId(AgentID); 2168 SceneObjectGroup copy = original.Copy(true);
1969 copy.SetRootPartOwner(copy.RootPart, AgentID, GroupID); 2169 copy.AbsolutePosition = copy.AbsolutePosition + offset;
1970
1971 SceneObjectPart[] partList = copy.Parts;
1972 2170
1973 if (m_parentScene.Permissions.PropagatePermissions()) 2171 if (original.OwnerID != AgentID)
1974 { 2172 {
1975 foreach (SceneObjectPart child in partList) 2173 copy.SetOwnerId(AgentID);
2174 copy.SetRootPartOwner(copy.RootPart, AgentID, GroupID);
2175
2176 SceneObjectPart[] partList = copy.Parts;
2177
2178 if (m_parentScene.Permissions.PropagatePermissions())
1976 { 2179 {
1977 child.Inventory.ChangeInventoryOwner(AgentID); 2180 foreach (SceneObjectPart child in partList)
1978 child.TriggerScriptChangedEvent(Changed.OWNER); 2181 {
1979 child.ApplyNextOwnerPermissions(); 2182 child.Inventory.ChangeInventoryOwner(AgentID);
2183 child.TriggerScriptChangedEvent(Changed.OWNER);
2184 child.ApplyNextOwnerPermissions();
2185 }
1980 } 2186 }
1981 } 2187 }
1982 2188
1983 copy.RootPart.ObjectSaleType = 0; 2189 // FIXME: This section needs to be refactored so that it just calls AddSceneObject()
1984 copy.RootPart.SalePrice = 10; 2190 Entities.Add(copy);
1985 }
1986 2191
1987 // FIXME: This section needs to be refactored so that it just calls AddSceneObject() 2192 lock (SceneObjectGroupsByFullID)
1988 Entities.Add(copy); 2193 SceneObjectGroupsByFullID[copy.UUID] = copy;
1989
1990 lock (SceneObjectGroupsByFullID)
1991 SceneObjectGroupsByFullID[copy.UUID] = copy;
1992
1993 SceneObjectPart[] children = copy.Parts;
1994
1995 lock (SceneObjectGroupsByFullPartID)
1996 {
1997 SceneObjectGroupsByFullPartID[copy.UUID] = copy;
1998 foreach (SceneObjectPart part in children)
1999 SceneObjectGroupsByFullPartID[part.UUID] = copy;
2000 }
2001
2002 lock (SceneObjectGroupsByLocalPartID)
2003 {
2004 SceneObjectGroupsByLocalPartID[copy.LocalId] = copy;
2005 foreach (SceneObjectPart part in children)
2006 SceneObjectGroupsByLocalPartID[part.LocalId] = copy;
2007 }
2008 // PROBABLE END OF FIXME
2009 2194
2010 // Since we copy from a source group that is in selected 2195 SceneObjectPart[] parts = copy.Parts;
2011 // state, but the copy is shown deselected in the viewer, 2196 foreach (SceneObjectPart part in parts)
2012 // We need to clear the selection flag here, else that 2197 {
2013 // prim never gets persisted at all. The client doesn't 2198 lock (SceneObjectGroupsByFullPartID)
2014 // think it's selected, so it will never send a deselect... 2199 SceneObjectGroupsByFullPartID[part.UUID] = copy;
2015 copy.IsSelected = false; 2200 lock (SceneObjectGroupsByLocalPartID)
2201 SceneObjectGroupsByLocalPartID[part.LocalId] = copy;
2202 }
2016 2203
2017 m_numTotalPrim += copy.Parts.Length; 2204 // PROBABLE END OF FIXME
2018 2205
2019 // Go through all parts (primitives and meshes) of this Scene Object 2206 // Since we copy from a source group that is in selected
2020 foreach (SceneObjectPart part in copy.Parts) 2207 // state, but the copy is shown deselected in the viewer,
2021 { 2208 // We need to clear the selection flag here, else that
2022 // Keep track of the total number of meshes or geometric primitives now in the scene; 2209 // prim never gets persisted at all. The client doesn't
2023 // determine which object this is based on its primitive type: sculpted (sculpt) prim refers to 2210 // think it's selected, so it will never send a deselect...
2024 // a mesh and all other prims (i.e. box, sphere, etc) are geometric primitives 2211 copy.IsSelected = false;
2025 if (part.GetPrimType() == PrimType.SCULPT)
2026 m_numMesh++;
2027 else
2028 m_numPrim++;
2029 }
2030 2212
2031 if (rot != Quaternion.Identity) 2213 m_numPrim += copy.Parts.Length;
2032 {
2033 copy.UpdateGroupRotationR(rot);
2034 }
2035 2214
2036 copy.CreateScriptInstances(0, false, m_parentScene.DefaultScriptEngine, 1); 2215 if (rot != Quaternion.Identity)
2037 copy.HasGroupChanged = true; 2216 {
2038 copy.ScheduleGroupForFullUpdate(); 2217 copy.UpdateGroupRotationR(rot);
2039 copy.ResumeScripts(); 2218 }
2219
2220 copy.CreateScriptInstances(0, false, m_parentScene.DefaultScriptEngine, 1);
2221 copy.HasGroupChanged = true;
2222 copy.ScheduleGroupForFullUpdate();
2223 copy.ResumeScripts();
2040 2224
2041 // required for physics to update it's position 2225 // required for physics to update it's position
2042 copy.AbsolutePosition = copy.AbsolutePosition; 2226 copy.AbsolutePosition = copy.AbsolutePosition;
2043 2227
2044 return copy; 2228 return copy;
2229 }
2045 } 2230 }
2046 finally 2231 else
2047 { 2232 {
2048 Monitor.Exit(m_updateLock); 2233 m_log.WarnFormat("[SCENE]: Attempted to duplicate nonexistant prim id {0}", GroupID);
2049 } 2234 }
2235
2236 return null;
2050 } 2237 }
2051 2238
2052 /// <summary>
2053 /// Calculates the distance between two Vector3s 2239 /// Calculates the distance between two Vector3s
2054 /// </summary> 2240 /// </summary>
2055 /// <param name="v1"></param> 2241 /// <param name="v1"></param>