diff options
Diffstat (limited to 'OpenSim/Region/Environment')
-rw-r--r-- | OpenSim/Region/Environment/Scenes/InnerScene.cs | 50 | ||||
-rw-r--r-- | OpenSim/Region/Environment/Scenes/Scene.cs | 3 | ||||
-rw-r--r-- | OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs | 105 | ||||
-rw-r--r-- | OpenSim/Region/Environment/Scenes/ScenePresence.cs | 21 |
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 | } |