aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Environment
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Environment')
-rw-r--r--OpenSim/Region/Environment/Scenes/InnerScene.cs50
-rw-r--r--OpenSim/Region/Environment/Scenes/Scene.cs3
-rw-r--r--OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs105
-rw-r--r--OpenSim/Region/Environment/Scenes/ScenePresence.cs21
4 files changed, 167 insertions, 12 deletions
diff --git a/OpenSim/Region/Environment/Scenes/InnerScene.cs b/OpenSim/Region/Environment/Scenes/InnerScene.cs
index 90478c6..c8e9b73 100644
--- a/OpenSim/Region/Environment/Scenes/InnerScene.cs
+++ b/OpenSim/Region/Environment/Scenes/InnerScene.cs
@@ -536,6 +536,56 @@ namespace OpenSim.Region.Environment.Scenes
536 parenPrim.LinkToGroup(sceneObj); 536 parenPrim.LinkToGroup(sceneObj);
537 } 537 }
538 } 538 }
539
540 /// <summary>
541 /// Delink a linkset
542 /// </summary>
543 /// <param name="prims"></param>
544 public void DelinkObjects(List<uint> primIds)
545 {
546 //OpenSim.Framework.Console.MainLog.Instance.Verbose("DelinkObjects()");
547
548 SceneObjectGroup parenPrim = null;
549
550 // Need a list of the SceneObjectGroup local ids
551 // XXX I'm anticipating that building this dictionary once is more efficient than
552 // repeated scanning of the Entity.Values for a large number of primIds. However, it might
553 // be more efficient yet to keep this dictionary permanently on hand.
554 Dictionary<uint, SceneObjectGroup> sceneObjects = new Dictionary<uint, SceneObjectGroup>();
555 foreach (EntityBase ent in Entities.Values)
556 {
557 if (ent is SceneObjectGroup)
558 {
559 SceneObjectGroup obj = (SceneObjectGroup)ent;
560 sceneObjects.Add(obj.LocalId, obj);
561 }
562 }
563
564 // Find the root prim among the prim ids we've been given
565 for (int i = 0; i < primIds.Count; i++)
566 {
567 if (sceneObjects.ContainsKey(primIds[i]))
568 {
569 parenPrim = sceneObjects[primIds[i]];
570 primIds.RemoveAt(i);
571 break;
572 }
573 }
574
575 if (parenPrim != null)
576 {
577 foreach (uint childPrimId in primIds)
578 {
579 parenPrim.DelinkFromGroup(childPrimId);
580 }
581 }
582 else
583 {
584 OpenSim.Framework.Console.MainLog.Instance.Verbose(
585 "DelinkObjects(): Could not find a root prim out of {0} as given to a delink request!",
586 primIds);
587 }
588 }
539 589
540 /// <summary> 590 /// <summary>
541 /// 591 ///
diff --git a/OpenSim/Region/Environment/Scenes/Scene.cs b/OpenSim/Region/Environment/Scenes/Scene.cs
index 2d58b0e..bf56fe8 100644
--- a/OpenSim/Region/Environment/Scenes/Scene.cs
+++ b/OpenSim/Region/Environment/Scenes/Scene.cs
@@ -705,6 +705,7 @@ namespace OpenSim.Region.Environment.Scenes
705 client.OnObjectDescription += m_innerScene.PrimDescription; 705 client.OnObjectDescription += m_innerScene.PrimDescription;
706 client.OnObjectName += m_innerScene.PrimName; 706 client.OnObjectName += m_innerScene.PrimName;
707 client.OnLinkObjects += m_innerScene.LinkObjects; 707 client.OnLinkObjects += m_innerScene.LinkObjects;
708 client.OnDelinkObjects += m_innerScene.DelinkObjects;
708 client.OnObjectDuplicate += m_innerScene.DuplicateObject; 709 client.OnObjectDuplicate += m_innerScene.DuplicateObject;
709 client.OnUpdatePrimFlags += m_innerScene.UpdatePrimFlags; 710 client.OnUpdatePrimFlags += m_innerScene.UpdatePrimFlags;
710 711
@@ -1273,4 +1274,4 @@ namespace OpenSim.Region.Environment.Scenes
1273 1274
1274 #endregion 1275 #endregion
1275 } 1276 }
1276} \ No newline at end of file 1277}
diff --git a/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs
index e2415b9..a9f0bb3 100644
--- a/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs
@@ -222,6 +222,27 @@ namespace OpenSim.Region.Environment.Scenes
222 public SceneObjectGroup() 222 public SceneObjectGroup()
223 { 223 {
224 } 224 }
225
226 /// <summary>
227 /// This constructor creates a SceneObjectGroup using a pre-existing SceneObjectPart.
228 /// The original SceneObjectPart will be used rather than a copy, preserving
229 /// its existing localID and UUID.
230 /// </summary>
231 public SceneObjectGroup(Scene scene, ulong regionHandle, SceneObjectPart part)
232 {
233 m_scene = scene;
234 m_regionHandle = regionHandle;
235
236 part.SetParent(this);
237 part.ParentID = 0;
238
239 m_parts.Add(part.UUID, part);
240 SetPartAsRoot(part);
241
242 AttachToBackup();
243
244 ScheduleGroupForFullUpdate();
245 }
225 246
226 /// <summary> 247 /// <summary>
227 /// 248 ///
@@ -594,10 +615,10 @@ namespace OpenSim.Region.Environment.Scenes
594 #region SceneGroupPart Methods 615 #region SceneGroupPart Methods
595 616
596 /// <summary> 617 /// <summary>
597 /// 618 /// Get a child part with a given UUID
598 /// </summary> 619 /// </summary>
599 /// <param name="primID"></param> 620 /// <param name="primID"></param>
600 /// <returns></returns> 621 /// <returns>null if a child part with the primID was not found</returns>
601 public SceneObjectPart GetChildPart(LLUUID primID) 622 public SceneObjectPart GetChildPart(LLUUID primID)
602 { 623 {
603 SceneObjectPart childPart = null; 624 SceneObjectPart childPart = null;
@@ -609,10 +630,10 @@ namespace OpenSim.Region.Environment.Scenes
609 } 630 }
610 631
611 /// <summary> 632 /// <summary>
612 /// 633 /// Get a child part with a given local ID
613 /// </summary> 634 /// </summary>
614 /// <param name="localID"></param> 635 /// <param name="localID"></param>
615 /// <returns></returns> 636 /// <returns>null if a child part with the local ID was not found</returns>
616 public SceneObjectPart GetChildPart(uint localID) 637 public SceneObjectPart GetChildPart(uint localID)
617 { 638 {
618 foreach (SceneObjectPart part in m_parts.Values) 639 foreach (SceneObjectPart part in m_parts.Values)
@@ -717,13 +738,85 @@ namespace OpenSim.Region.Environment.Scenes
717 objectGroup.DeleteParts(); 738 objectGroup.DeleteParts();
718 ScheduleGroupForFullUpdate(); 739 ScheduleGroupForFullUpdate();
719 } 740 }
741
742 /// <summary>
743 /// Delink the given prim from this group. The delinked prim is established as
744 /// an independent SceneObjectGroup.
745 /// </summary>
746 /// <param name="partID"></param>
747 public void DelinkFromGroup(uint partID)
748 {
749 SceneObjectPart linkPart = GetChildPart(partID);
750
751 if (null != linkPart)
752 {
753 // Remove the part from this object
754 m_parts.Remove(linkPart.UUID);
755
756 // We need to reset the child part's position
757 // ready for life as a separate object after being a part of another object
758 Quaternion parentRot
759 = new Quaternion(
760 m_rootPart.RotationOffset.W,
761 m_rootPart.RotationOffset.X,
762 m_rootPart.RotationOffset.Y,
763 m_rootPart.RotationOffset.Z);
764
765 Vector3 axPos
766 = new Vector3(
767 linkPart.OffsetPosition.X,
768 linkPart.OffsetPosition.Y,
769 linkPart.OffsetPosition.Z);
770
771 axPos = parentRot * axPos;
772 linkPart.OffsetPosition = new LLVector3(axPos.x, axPos.y, axPos.z);
773 linkPart.GroupPosition = AbsolutePosition + linkPart.OffsetPosition;
774 linkPart.OffsetPosition = new LLVector3(0, 0, 0);
775
776 Quaternion oldRot
777 = new Quaternion(
778 linkPart.RotationOffset.W,
779 linkPart.RotationOffset.X,
780 linkPart.RotationOffset.Y,
781 linkPart.RotationOffset.Z);
782 Quaternion newRot = parentRot * oldRot;
783 linkPart.RotationOffset = new LLQuaternion(newRot.x, newRot.y, newRot.z, newRot.w);
784
785 // Add physics information back to delinked part if appropriate
786 // XXX This is messy and should be refactorable with the similar section in
787 // SceneObjectPart.UpdatePrimFlags()
788 if (m_rootPart.PhysActor != null)
789 {
790 linkPart.PhysActor = m_scene.PhysScene.AddPrimShape(
791 linkPart.Name,
792 linkPart.Shape,
793 new PhysicsVector(linkPart.AbsolutePosition.X, linkPart.AbsolutePosition.Y,
794 linkPart.AbsolutePosition.Z),
795 new PhysicsVector(linkPart.Scale.X, linkPart.Scale.Y, linkPart.Scale.Z),
796 new Quaternion(linkPart.RotationOffset.W, linkPart.RotationOffset.X,
797 linkPart.RotationOffset.Y, linkPart.RotationOffset.Z),
798 m_rootPart.PhysActor.IsPhysical);
799 }
800
801 SceneObjectGroup objectGroup = new SceneObjectGroup(m_scene, m_regionHandle, linkPart);
802
803 m_scene.AddEntity(objectGroup);
804
805 ScheduleGroupForFullUpdate();
806 }
807 else
808 {
809 OpenSim.Framework.Console.MainLog.Instance.Verbose(
810 "DelinkFromGroup(): Child prim local id {0} not found in object with root prim id {1}",
811 partID, LocalId);
812 }
813 }
720 814
721 private void DetachFromBackup(SceneObjectGroup objectGroup) 815 private void DetachFromBackup(SceneObjectGroup objectGroup)
722 { 816 {
723 m_scene.EventManager.OnBackup -= objectGroup.ProcessBackup; 817 m_scene.EventManager.OnBackup -= objectGroup.ProcessBackup;
724 } 818 }
725 819
726
727 private void LinkNonRootPart(SceneObjectPart part, Vector3 oldGroupPosition, Quaternion oldGroupRotation) 820 private void LinkNonRootPart(SceneObjectPart part, Vector3 oldGroupPosition, Quaternion oldGroupRotation)
728 { 821 {
729 part.SetParent(this); 822 part.SetParent(this);
@@ -1431,4 +1524,4 @@ namespace OpenSim.Region.Environment.Scenes
1431 Text = text; 1524 Text = text;
1432 } 1525 }
1433 } 1526 }
1434} \ No newline at end of file 1527}
diff --git a/OpenSim/Region/Environment/Scenes/ScenePresence.cs b/OpenSim/Region/Environment/Scenes/ScenePresence.cs
index 20ec72e..c9c24fe 100644
--- a/OpenSim/Region/Environment/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Environment/Scenes/ScenePresence.cs
@@ -328,17 +328,28 @@ namespace OpenSim.Region.Environment.Scenes
328 if (m_updateTimes.ContainsKey(part.UUID)) 328 if (m_updateTimes.ContainsKey(part.UUID))
329 { 329 {
330 ScenePartUpdate update = m_updateTimes[part.UUID]; 330 ScenePartUpdate update = m_updateTimes[part.UUID];
331 if (update.LastFullUpdateTime < part.TimeStampFull) 331
332 // Two updates can occur with the same timestamp (especially
333 // since our timestamp resolution is to the nearest second). The first
334 // could have been sent in the last update - we still need to send the
335 // second here.
336 if (update.LastFullUpdateTime <= part.TimeStampFull)
332 { 337 {
333 //need to do a full update 338 //need to do a full update
334 part.SendFullUpdate(ControllingClient); 339 part.SendFullUpdate(ControllingClient);
335 update.LastFullUpdateTime = (uint) Util.UnixTimeSinceEpoch(); 340
341 // We'll update to the part's timestamp rather than the current to
342 // avoid the race condition whereby the next tick occurs while we are
343 // doing this update. If this happened, then subsequent updates which occurred
344 // on the same tick or the next tick of the last update would be ignored.
345 update.LastFullUpdateTime = part.TimeStampFull;
346
336 updateCount++; 347 updateCount++;
337 } 348 }
338 else if (update.LastTerseUpdateTime < part.TimeStampTerse) 349 else if (update.LastTerseUpdateTime <= part.TimeStampTerse)
339 { 350 {
340 part.SendTerseUpdate(ControllingClient); 351 part.SendTerseUpdate(ControllingClient);
341 update.LastTerseUpdateTime = (uint) Util.UnixTimeSinceEpoch(); 352 update.LastTerseUpdateTime = part.TimeStampTerse;
342 updateCount++; 353 updateCount++;
343 } 354 }
344 } 355 }
@@ -348,7 +359,7 @@ namespace OpenSim.Region.Environment.Scenes
348 part.SendFullUpdate(ControllingClient); 359 part.SendFullUpdate(ControllingClient);
349 ScenePartUpdate update = new ScenePartUpdate(); 360 ScenePartUpdate update = new ScenePartUpdate();
350 update.FullID = part.UUID; 361 update.FullID = part.UUID;
351 update.LastFullUpdateTime = (uint) Util.UnixTimeSinceEpoch(); 362 update.LastFullUpdateTime = part.TimeStampFull;
352 m_updateTimes.Add(part.UUID, update); 363 m_updateTimes.Add(part.UUID, update);
353 updateCount++; 364 updateCount++;
354 } 365 }