aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/SceneObjectPart.cs')
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs301
1 files changed, 201 insertions, 100 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 2026c53..4629757 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -287,8 +287,8 @@ namespace OpenSim.Region.Framework.Scenes
287 private string m_sitAnimation = "SIT"; 287 private string m_sitAnimation = "SIT";
288 private string m_text = String.Empty; 288 private string m_text = String.Empty;
289 private string m_touchName = String.Empty; 289 private string m_touchName = String.Empty;
290 private readonly UndoStack<UndoState> m_undo = new UndoStack<UndoState>(5); 290 private readonly Stack<UndoState> m_undo = new Stack<UndoState>(5);
291 private readonly UndoStack<UndoState> m_redo = new UndoStack<UndoState>(5); 291 private readonly Stack<UndoState> m_redo = new Stack<UndoState>(5);
292 private UUID _creatorID; 292 private UUID _creatorID;
293 293
294 private bool m_passTouches; 294 private bool m_passTouches;
@@ -414,7 +414,6 @@ namespace OpenSim.Region.Framework.Scenes
414 CreateSelected = true; 414 CreateSelected = true;
415 415
416 TrimPermissions(); 416 TrimPermissions();
417 //m_undo = new UndoStack<UndoState>(ParentGroup.GetSceneMaxUndo());
418 417
419 m_inventory = new SceneObjectPartInventory(this); 418 m_inventory = new SceneObjectPartInventory(this);
420 } 419 }
@@ -789,7 +788,7 @@ namespace OpenSim.Region.Framework.Scenes
789 get { return m_offsetPosition; } 788 get { return m_offsetPosition; }
790 set 789 set
791 { 790 {
792 StoreUndoState(); 791// StoreUndoState();
793 m_offsetPosition = value; 792 m_offsetPosition = value;
794 793
795 if (ParentGroup != null && !ParentGroup.IsDeleted) 794 if (ParentGroup != null && !ParentGroup.IsDeleted)
@@ -1015,15 +1014,19 @@ namespace OpenSim.Region.Framework.Scenes
1015 get { return m_shape; } 1014 get { return m_shape; }
1016 set { m_shape = value; } 1015 set { m_shape = value; }
1017 } 1016 }
1018 1017
1018 /// <summary>
1019 /// Change the scale of this part.
1020 /// </summary>
1019 public Vector3 Scale 1021 public Vector3 Scale
1020 { 1022 {
1021 get { return m_shape.Scale; } 1023 get { return m_shape.Scale; }
1022 set 1024 set
1023 { 1025 {
1024 StoreUndoState();
1025 if (m_shape != null) 1026 if (m_shape != null)
1026 { 1027 {
1028 StoreUndoState();
1029
1027 m_shape.Scale = value; 1030 m_shape.Scale = value;
1028 1031
1029 PhysicsActor actor = PhysActor; 1032 PhysicsActor actor = PhysActor;
@@ -1034,11 +1037,16 @@ namespace OpenSim.Region.Framework.Scenes
1034 if (m_parentGroup.Scene.PhysicsScene != null) 1037 if (m_parentGroup.Scene.PhysicsScene != null)
1035 { 1038 {
1036 actor.Size = m_shape.Scale; 1039 actor.Size = m_shape.Scale;
1037 m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 1040
1041 if (((OpenMetaverse.SculptType)Shape.SculptType) == SculptType.Mesh)
1042 CheckSculptAndLoad();
1043 else
1044 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor);
1038 } 1045 }
1039 } 1046 }
1040 } 1047 }
1041 } 1048 }
1049
1042 TriggerScriptChangedEvent(Changed.SCALE); 1050 TriggerScriptChangedEvent(Changed.SCALE);
1043 } 1051 }
1044 } 1052 }
@@ -1588,17 +1596,23 @@ namespace OpenSim.Region.Framework.Scenes
1588 // or flexible 1596 // or flexible
1589 if (!isPhantom && !IsAttachment && !(Shape.PathCurve == (byte) Extrusion.Flexible)) 1597 if (!isPhantom && !IsAttachment && !(Shape.PathCurve == (byte) Extrusion.Flexible))
1590 { 1598 {
1591// m_log.DebugFormat("[SCENE OBJECT PART]: Creating PhysActor for {0} {1} {2}", Name, LocalId, UUID); 1599 try
1592 1600 {
1593 PhysActor = m_parentGroup.Scene.PhysicsScene.AddPrimShape( 1601 PhysActor = m_parentGroup.Scene.PhysicsScene.AddPrimShape(
1594 LocalId, 1602 string.Format("{0}/{1}", Name, UUID),
1595 string.Format("{0}/{1}", Name, UUID), 1603 Shape,
1596 Shape, 1604 AbsolutePosition,
1597 AbsolutePosition, 1605 Scale,
1598 Scale, 1606 RotationOffset,
1599 RotationOffset, 1607 RigidBody,
1600 RigidBody); 1608 m_localId);
1601 1609 PhysActor.SetMaterial(Material);
1610 }
1611 catch
1612 {
1613 m_log.ErrorFormat("[SCENE]: caught exception meshing object {0}. Object set to phantom.", m_uuid);
1614 PhysActor = null;
1615 }
1602 // Basic Physics returns null.. joy joy joy. 1616 // Basic Physics returns null.. joy joy joy.
1603 if (PhysActor != null) 1617 if (PhysActor != null)
1604 { 1618 {
@@ -1615,19 +1629,6 @@ namespace OpenSim.Region.Framework.Scenes
1615 } 1629 }
1616 } 1630 }
1617 1631
1618 public void ClearUndoState()
1619 {
1620 lock (m_undo)
1621 {
1622 m_undo.Clear();
1623 }
1624 lock (m_redo)
1625 {
1626 m_redo.Clear();
1627 }
1628 StoreUndoState();
1629 }
1630
1631 public byte ConvertScriptUintToByte(uint indata) 1632 public byte ConvertScriptUintToByte(uint indata)
1632 { 1633 {
1633 byte outdata = (byte)TextureAnimFlags.NONE; 1634 byte outdata = (byte)TextureAnimFlags.NONE;
@@ -1705,7 +1706,8 @@ namespace OpenSim.Region.Framework.Scenes
1705 { 1706 {
1706 if (dupe.m_shape.SculptEntry && dupe.m_shape.SculptTexture != UUID.Zero) 1707 if (dupe.m_shape.SculptEntry && dupe.m_shape.SculptTexture != UUID.Zero)
1707 { 1708 {
1708 m_parentGroup.Scene.AssetService.Get(dupe.m_shape.SculptTexture.ToString(), dupe, AssetReceived); 1709 ParentGroup.Scene.AssetService.Get(
1710 dupe.m_shape.SculptTexture.ToString(), dupe, dupe.AssetReceived);
1709 } 1711 }
1710 1712
1711 bool UsePhysics = ((dupe.Flags & PrimFlags.Physics) != 0); 1713 bool UsePhysics = ((dupe.Flags & PrimFlags.Physics) != 0);
@@ -1719,14 +1721,20 @@ namespace OpenSim.Region.Framework.Scenes
1719 return dupe; 1721 return dupe;
1720 } 1722 }
1721 1723
1724 /// <summary>
1725 /// Called back by asynchronous asset fetch.
1726 /// </summary>
1727 /// <param name="id">ID of asset received</param>
1728 /// <param name="sender">Register</param>
1729 /// <param name="asset"></param>
1722 protected void AssetReceived(string id, Object sender, AssetBase asset) 1730 protected void AssetReceived(string id, Object sender, AssetBase asset)
1723 { 1731 {
1724 if (asset != null) 1732 if (asset != null)
1725 { 1733 SculptTextureCallback(asset);
1726 SceneObjectPart sop = (SceneObjectPart)sender; 1734 else
1727 if (sop != null) 1735 m_log.WarnFormat(
1728 sop.SculptTextureCallback(asset.FullID, asset); 1736 "[SCENE OBJECT PART]: Part {0} {1} requested mesh/sculpt data for asset id {2} from asset service but received no data",
1729 } 1737 Name, LocalId, id);
1730 } 1738 }
1731 1739
1732 public static SceneObjectPart Create() 1740 public static SceneObjectPart Create()
@@ -1896,7 +1904,12 @@ namespace OpenSim.Region.Framework.Scenes
1896 } 1904 }
1897 } 1905 }
1898 1906
1899 m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor); 1907 // If this part is a sculpt then delay the physics update until we've asynchronously loaded the
1908 // mesh data.
1909 if (((OpenMetaverse.SculptType)Shape.SculptType) == SculptType.Mesh)
1910 CheckSculptAndLoad();
1911 else
1912 m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor);
1900 } 1913 }
1901 } 1914 }
1902 } 1915 }
@@ -2823,19 +2836,29 @@ namespace OpenSim.Region.Framework.Scenes
2823 } 2836 }
2824 2837
2825 /// <summary> 2838 /// <summary>
2826 /// Resize this part. 2839 /// Set the scale of this part.
2827 /// </summary> 2840 /// </summary>
2841 /// <remarks>
2842 /// Unlike the scale property, this checks the new size against scene limits and schedules a full property
2843 /// update to viewers.
2844 /// </remarks>
2828 /// <param name="scale"></param> 2845 /// <param name="scale"></param>
2829 public void Resize(Vector3 scale) 2846 public void Resize(Vector3 scale)
2830 { 2847 {
2831 StoreUndoState(); 2848 scale.X = Math.Min(scale.X, ParentGroup.Scene.m_maxNonphys);
2832 m_shape.Scale = scale; 2849 scale.Y = Math.Min(scale.Y, ParentGroup.Scene.m_maxNonphys);
2850 scale.Z = Math.Min(scale.Z, ParentGroup.Scene.m_maxNonphys);
2833 2851
2834 // If we're a mesh/sculpt, then we need to tell the physics engine about our new size. To do this, we 2852 if (PhysActor != null && PhysActor.IsPhysical)
2835 // need to reinsert the sculpt data into the shape, since the physics engine deletes it when done to 2853 {
2836 // save memory 2854 scale.X = Math.Min(scale.X, ParentGroup.Scene.m_maxPhys);
2837 if (PhysActor != null) 2855 scale.Y = Math.Min(scale.Y, ParentGroup.Scene.m_maxPhys);
2838 CheckSculptAndLoad(); 2856 scale.Z = Math.Min(scale.Z, ParentGroup.Scene.m_maxPhys);
2857 }
2858
2859// m_log.DebugFormat("[SCENE OBJECT PART]: Resizing {0} {1} to {2}", Name, LocalId, scale);
2860
2861 Scale = scale;
2839 2862
2840 ParentGroup.HasGroupChanged = true; 2863 ParentGroup.HasGroupChanged = true;
2841 ScheduleFullUpdate(); 2864 ScheduleFullUpdate();
@@ -2965,7 +2988,11 @@ namespace OpenSim.Region.Framework.Scenes
2965 } 2988 }
2966 } 2989 }
2967 2990
2968 public void SculptTextureCallback(UUID textureID, AssetBase texture) 2991 /// <summary>
2992 /// Set sculpt and mesh data, and tell the physics engine to process the change.
2993 /// </summary>
2994 /// <param name="texture">The mesh itself.</param>
2995 public void SculptTextureCallback(AssetBase texture)
2969 { 2996 {
2970 if (m_shape.SculptEntry) 2997 if (m_shape.SculptEntry)
2971 { 2998 {
@@ -2991,16 +3018,6 @@ namespace OpenSim.Region.Framework.Scenes
2991 } 3018 }
2992 } 3019 }
2993 3020
2994// /// <summary>
2995// ///
2996// /// </summary>
2997// /// <param name="remoteClient"></param>
2998// public void SendFullUpdate(IClientAPI remoteClient, uint clientFlags)
2999// {
3000// m_parentGroup.SendPartFullUpdate(remoteClient, this, clientFlags);
3001// }
3002
3003
3004 /// <summary> 3021 /// <summary>
3005 /// Send a full update to the client for the given part 3022 /// Send a full update to the client for the given part
3006 /// </summary> 3023 /// </summary>
@@ -3648,6 +3665,11 @@ namespace OpenSim.Region.Framework.Scenes
3648 3665
3649 public void StoreUndoState() 3666 public void StoreUndoState()
3650 { 3667 {
3668 StoreUndoState(false);
3669 }
3670
3671 public void StoreUndoState(bool forGroup)
3672 {
3651 if (!Undoing) 3673 if (!Undoing)
3652 { 3674 {
3653 if (!IgnoreUndoUpdate) 3675 if (!IgnoreUndoUpdate)
@@ -3661,24 +3683,138 @@ namespace OpenSim.Region.Framework.Scenes
3661 UndoState last = m_undo.Peek(); 3683 UndoState last = m_undo.Peek();
3662 if (last != null) 3684 if (last != null)
3663 { 3685 {
3686 // TODO: May need to fix for group comparison
3664 if (last.Compare(this)) 3687 if (last.Compare(this))
3688 {
3689// m_log.DebugFormat(
3690// "[SCENE OBJECT PART]: Not storing undo for {0} {1} since current state is same as last undo state, initial stack size {2}",
3691// Name, LocalId, m_undo.Count);
3692
3665 return; 3693 return;
3694 }
3666 } 3695 }
3667 } 3696 }
3668 3697
3698// m_log.DebugFormat(
3699// "[SCENE OBJECT PART]: Storing undo state for {0} {1}, forGroup {2}, initial stack size {3}",
3700// Name, LocalId, forGroup, m_undo.Count);
3701
3669 if (m_parentGroup.GetSceneMaxUndo() > 0) 3702 if (m_parentGroup.GetSceneMaxUndo() > 0)
3670 { 3703 {
3671 UndoState nUndo = new UndoState(this); 3704 UndoState nUndo = new UndoState(this, forGroup);
3672 3705
3673 m_undo.Push(nUndo); 3706 m_undo.Push(nUndo);
3707
3708 if (m_redo.Count > 0)
3709 m_redo.Clear();
3710
3711// m_log.DebugFormat(
3712// "[SCENE OBJECT PART]: Stored undo state for {0} {1}, forGroup {2}, stack size now {3}",
3713// Name, LocalId, forGroup, m_undo.Count);
3674 } 3714 }
3715 }
3716 }
3717 }
3718// else
3719// {
3720// m_log.DebugFormat("[SCENE OBJECT PART]: Ignoring undo store for {0} {1}", Name, LocalId);
3721// }
3722 }
3723// else
3724// {
3725// m_log.DebugFormat(
3726// "[SCENE OBJECT PART]: Ignoring undo store for {0} {1} since already undoing", Name, LocalId);
3727// }
3728 }
3729
3730 /// <summary>
3731 /// Return number of undos on the stack. Here temporarily pending a refactor.
3732 /// </summary>
3733 public int UndoCount
3734 {
3735 get
3736 {
3737 lock (m_undo)
3738 return m_undo.Count;
3739 }
3740 }
3675 3741
3742 public void Undo()
3743 {
3744 lock (m_undo)
3745 {
3746// m_log.DebugFormat(
3747// "[SCENE OBJECT PART]: Handling undo request for {0} {1}, stack size {2}",
3748// Name, LocalId, m_undo.Count);
3749
3750 if (m_undo.Count > 0)
3751 {
3752 UndoState goback = m_undo.Pop();
3753
3754 if (goback != null)
3755 {
3756 UndoState nUndo = null;
3757
3758 if (m_parentGroup.GetSceneMaxUndo() > 0)
3759 {
3760 nUndo = new UndoState(this, goback.ForGroup);
3761 }
3762
3763 goback.PlaybackState(this);
3764
3765 if (nUndo != null)
3766 m_redo.Push(nUndo);
3767 }
3768 }
3769
3770// m_log.DebugFormat(
3771// "[SCENE OBJECT PART]: Handled undo request for {0} {1}, stack size now {2}",
3772// Name, LocalId, m_undo.Count);
3773 }
3774 }
3775
3776 public void Redo()
3777 {
3778 lock (m_undo)
3779 {
3780// m_log.DebugFormat(
3781// "[SCENE OBJECT PART]: Handling redo request for {0} {1}, stack size {2}",
3782// Name, LocalId, m_redo.Count);
3783
3784 if (m_redo.Count > 0)
3785 {
3786 UndoState gofwd = m_redo.Pop();
3787
3788 if (gofwd != null)
3789 {
3790 if (m_parentGroup.GetSceneMaxUndo() > 0)
3791 {
3792 UndoState nUndo = new UndoState(this, gofwd.ForGroup);
3793
3794 m_undo.Push(nUndo);
3676 } 3795 }
3796
3797 gofwd.PlayfwdState(this);
3677 } 3798 }
3799
3800// m_log.DebugFormat(
3801// "[SCENE OBJECT PART]: Handled redo request for {0} {1}, stack size now {2}",
3802// Name, LocalId, m_redo.Count);
3678 } 3803 }
3679 } 3804 }
3680 } 3805 }
3681 3806
3807 public void ClearUndoState()
3808 {
3809// m_log.DebugFormat("[SCENE OBJECT PART]: Clearing undo and redo stacks in {0} {1}", Name, LocalId);
3810
3811 lock (m_undo)
3812 {
3813 m_undo.Clear();
3814 m_redo.Clear();
3815 }
3816 }
3817
3682 public EntityIntersection TestIntersection(Ray iray, Quaternion parentrot) 3818 public EntityIntersection TestIntersection(Ray iray, Quaternion parentrot)
3683 { 3819 {
3684 // In this case we're using a sphere with a radius of the largest dimension of the prim 3820 // In this case we're using a sphere with a radius of the largest dimension of the prim
@@ -4139,44 +4275,6 @@ namespace OpenSim.Region.Framework.Scenes
4139 _nextOwnerMask &= (uint)PermissionMask.All; 4275 _nextOwnerMask &= (uint)PermissionMask.All;
4140 } 4276 }
4141 4277
4142 public void Undo()
4143 {
4144 lock (m_undo)
4145 {
4146 if (m_undo.Count > 0)
4147 {
4148 UndoState nUndo = null;
4149 if (m_parentGroup.GetSceneMaxUndo() > 0)
4150 {
4151 nUndo = new UndoState(this);
4152 }
4153 UndoState goback = m_undo.Pop();
4154 if (goback != null)
4155 {
4156 goback.PlaybackState(this);
4157 if (nUndo != null)
4158 m_redo.Push(nUndo);
4159 }
4160 }
4161 }
4162 }
4163
4164 public void Redo()
4165 {
4166 lock (m_redo)
4167 {
4168 if (m_parentGroup.GetSceneMaxUndo() > 0)
4169 {
4170 UndoState nUndo = new UndoState(this);
4171
4172 m_undo.Push(nUndo);
4173 }
4174 UndoState gofwd = m_redo.Pop();
4175 if (gofwd != null)
4176 gofwd.PlayfwdState(this);
4177 }
4178 }
4179
4180 public void UpdateExtraParam(ushort type, bool inUse, byte[] data) 4278 public void UpdateExtraParam(ushort type, bool inUse, byte[] data)
4181 { 4279 {
4182 m_shape.ReadInUpdateExtraParam(type, inUse, data); 4280 m_shape.ReadInUpdateExtraParam(type, inUse, data);
@@ -4435,13 +4533,14 @@ namespace OpenSim.Region.Framework.Scenes
4435 { 4533 {
4436 // It's not phantom anymore. So make sure the physics engine get's knowledge of it 4534 // It's not phantom anymore. So make sure the physics engine get's knowledge of it
4437 PhysActor = m_parentGroup.Scene.PhysicsScene.AddPrimShape( 4535 PhysActor = m_parentGroup.Scene.PhysicsScene.AddPrimShape(
4438 LocalId,
4439 string.Format("{0}/{1}", Name, UUID), 4536 string.Format("{0}/{1}", Name, UUID),
4440 Shape, 4537 Shape,
4441 AbsolutePosition, 4538 AbsolutePosition,
4442 Scale, 4539 Scale,
4443 RotationOffset, 4540 RotationOffset,
4444 UsePhysics); 4541 UsePhysics,
4542 m_localId);
4543 PhysActor.SetMaterial(Material);
4445 4544
4446 pa = PhysActor; 4545 pa = PhysActor;
4447 if (pa != null) 4546 if (pa != null)
@@ -4600,7 +4699,7 @@ namespace OpenSim.Region.Framework.Scenes
4600 /// </remarks> 4699 /// </remarks>
4601 public void CheckSculptAndLoad() 4700 public void CheckSculptAndLoad()
4602 { 4701 {
4603// m_log.Debug("Processing CheckSculptAndLoad for {0} {1}", Name, LocalId); 4702// m_log.DebugFormat("Processing CheckSculptAndLoad for {0} {1}", Name, LocalId);
4604 4703
4605 if (ParentGroup.IsDeleted) 4704 if (ParentGroup.IsDeleted)
4606 return; 4705 return;
@@ -4611,9 +4710,11 @@ namespace OpenSim.Region.Framework.Scenes
4611 if (Shape.SculptEntry && Shape.SculptTexture != UUID.Zero) 4710 if (Shape.SculptEntry && Shape.SculptTexture != UUID.Zero)
4612 { 4711 {
4613 // check if a previously decoded sculpt map has been cached 4712 // check if a previously decoded sculpt map has been cached
4713 // We don't read the file here - the meshmerizer will do that later.
4714 // TODO: Could we simplify the meshmerizer code by reading and setting the data here?
4614 if (File.Exists(System.IO.Path.Combine("j2kDecodeCache", "smap_" + Shape.SculptTexture.ToString()))) 4715 if (File.Exists(System.IO.Path.Combine("j2kDecodeCache", "smap_" + Shape.SculptTexture.ToString())))
4615 { 4716 {
4616 SculptTextureCallback(Shape.SculptTexture, null); 4717 SculptTextureCallback(null);
4617 } 4718 }
4618 else 4719 else
4619 { 4720 {