diff options
Diffstat (limited to 'OpenSim/Region/Framework')
-rw-r--r-- | OpenSim/Region/Framework/Interfaces/ISoundModule.cs | 4 | ||||
-rw-r--r-- | OpenSim/Region/Framework/Interfaces/ITerrainModule.cs | 2 | ||||
-rw-r--r-- | OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs | 13 | ||||
-rw-r--r-- | OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 3 | ||||
-rw-r--r-- | OpenSim/Region/Framework/Scenes/Scene.cs | 35 | ||||
-rw-r--r-- | OpenSim/Region/Framework/Scenes/SceneGraph.cs | 9 | ||||
-rw-r--r-- | OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 139 | ||||
-rw-r--r-- | OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 340 | ||||
-rw-r--r-- | OpenSim/Region/Framework/Scenes/ScenePresence.cs | 91 | ||||
-rw-r--r-- | OpenSim/Region/Framework/Scenes/UndoState.cs | 79 |
10 files changed, 618 insertions, 97 deletions
diff --git a/OpenSim/Region/Framework/Interfaces/ISoundModule.cs b/OpenSim/Region/Framework/Interfaces/ISoundModule.cs index 379fabd..6117a80 100644 --- a/OpenSim/Region/Framework/Interfaces/ISoundModule.cs +++ b/OpenSim/Region/Framework/Interfaces/ISoundModule.cs | |||
@@ -32,9 +32,9 @@ namespace OpenSim.Region.Framework.Interfaces | |||
32 | { | 32 | { |
33 | public interface ISoundModule | 33 | public interface ISoundModule |
34 | { | 34 | { |
35 | void PlayAttachedSound(UUID soundID, UUID ownerID, UUID objectID, double gain, Vector3 position, byte flags); | 35 | void PlayAttachedSound(UUID soundID, UUID ownerID, UUID objectID, double gain, Vector3 position, byte flags, float radius); |
36 | 36 | ||
37 | void TriggerSound( | 37 | void TriggerSound( |
38 | UUID soundId, UUID ownerID, UUID objectID, UUID parentID, double gain, Vector3 position, UInt64 handle); | 38 | UUID soundId, UUID ownerID, UUID objectID, UUID parentID, double gain, Vector3 position, UInt64 handle, float radius); |
39 | } | 39 | } |
40 | } \ No newline at end of file | 40 | } \ No newline at end of file |
diff --git a/OpenSim/Region/Framework/Interfaces/ITerrainModule.cs b/OpenSim/Region/Framework/Interfaces/ITerrainModule.cs index 7caac55..5947afb 100644 --- a/OpenSim/Region/Framework/Interfaces/ITerrainModule.cs +++ b/OpenSim/Region/Framework/Interfaces/ITerrainModule.cs | |||
@@ -62,5 +62,7 @@ namespace OpenSim.Region.Framework.Interfaces | |||
62 | void SaveToStream(string filename, Stream stream); | 62 | void SaveToStream(string filename, Stream stream); |
63 | 63 | ||
64 | void InstallPlugin(string name, ITerrainEffect plug); | 64 | void InstallPlugin(string name, ITerrainEffect plug); |
65 | |||
66 | void UndoTerrain(ITerrainChannel channel); | ||
65 | } | 67 | } |
66 | } | 68 | } |
diff --git a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs index fd526eb..712dcc7 100644 --- a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs +++ b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs | |||
@@ -418,15 +418,12 @@ namespace OpenSim.Region.Framework.Scenes.Animation | |||
418 | { | 418 | { |
419 | if (m_scenePresence.IsChildAgent) | 419 | if (m_scenePresence.IsChildAgent) |
420 | return; | 420 | return; |
421 | |||
422 | UUID[] animIDs; | ||
423 | int[] sequenceNums; | ||
424 | UUID[] objectIDs; | ||
425 | 421 | ||
426 | m_animations.GetArrays(out animIDs, out sequenceNums, out objectIDs); | 422 | m_scenePresence.Scene.ForEachScenePresence( |
427 | 423 | delegate(ScenePresence SP) | |
428 | m_scenePresence.ControllingClient.SendAnimations( | 424 | { |
429 | animIDs, sequenceNums, m_scenePresence.ControllingClient.AgentId, objectIDs); | 425 | SP.Animator.SendAnimPack(); |
426 | }); | ||
430 | } | 427 | } |
431 | 428 | ||
432 | /// <summary> | 429 | /// <summary> |
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index e032a07..ded001b 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | |||
@@ -528,6 +528,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
528 | m_log.Error("[AGENT INVENTORY]: Failed to find item " + oldItemID.ToString()); | 528 | m_log.Error("[AGENT INVENTORY]: Failed to find item " + oldItemID.ToString()); |
529 | return; | 529 | return; |
530 | } | 530 | } |
531 | |||
532 | if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) | ||
533 | return; | ||
531 | } | 534 | } |
532 | 535 | ||
533 | AssetBase asset = AssetService.Get(item.AssetID.ToString()); | 536 | AssetBase asset = AssetService.Get(item.AssetID.ToString()); |
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 669720a..72ece10 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs | |||
@@ -2054,9 +2054,39 @@ namespace OpenSim.Region.Framework.Scenes | |||
2054 | if (grp.IsDeleted) | 2054 | if (grp.IsDeleted) |
2055 | return; | 2055 | return; |
2056 | 2056 | ||
2057 | if (grp.RootPart.DIE_AT_EDGE) | ||
2058 | { | ||
2059 | // We remove the object here | ||
2060 | try | ||
2061 | { | ||
2062 | DeleteSceneObject(grp, false); | ||
2063 | } | ||
2064 | catch (Exception) | ||
2065 | { | ||
2066 | m_log.Warn("[DATABASE]: exception when trying to remove the prim that crossed the border."); | ||
2067 | } | ||
2068 | return; | ||
2069 | } | ||
2070 | |||
2071 | if (grp.RootPart.RETURN_AT_EDGE) | ||
2072 | { | ||
2073 | // We remove the object here | ||
2074 | try | ||
2075 | { | ||
2076 | List<SceneObjectGroup> objects = new List<SceneObjectGroup>(); | ||
2077 | objects.Add(grp); | ||
2078 | SceneObjectGroup[] objectsArray = objects.ToArray(); | ||
2079 | returnObjects(objectsArray, UUID.Zero); | ||
2080 | } | ||
2081 | catch (Exception) | ||
2082 | { | ||
2083 | m_log.Warn("[DATABASE]: exception when trying to return the prim that crossed the border."); | ||
2084 | } | ||
2085 | return; | ||
2086 | } | ||
2087 | |||
2057 | if (m_teleportModule != null) | 2088 | if (m_teleportModule != null) |
2058 | m_teleportModule.Cross(grp, attemptedPosition, silent); | 2089 | m_teleportModule.Cross(grp, attemptedPosition, silent); |
2059 | |||
2060 | } | 2090 | } |
2061 | 2091 | ||
2062 | public Border GetCrossedBorder(Vector3 position, Cardinals gridline) | 2092 | public Border GetCrossedBorder(Vector3 position, Cardinals gridline) |
@@ -2552,6 +2582,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2552 | client.OnGrabUpdate += ProcessObjectGrabUpdate; | 2582 | client.OnGrabUpdate += ProcessObjectGrabUpdate; |
2553 | client.OnDeGrabObject += ProcessObjectDeGrab; | 2583 | client.OnDeGrabObject += ProcessObjectDeGrab; |
2554 | client.OnUndo += m_sceneGraph.HandleUndo; | 2584 | client.OnUndo += m_sceneGraph.HandleUndo; |
2585 | client.OnRedo += m_sceneGraph.HandleRedo; | ||
2555 | client.OnObjectDescription += m_sceneGraph.PrimDescription; | 2586 | client.OnObjectDescription += m_sceneGraph.PrimDescription; |
2556 | client.OnObjectDrop += m_sceneGraph.DropObject; | 2587 | client.OnObjectDrop += m_sceneGraph.DropObject; |
2557 | client.OnObjectSaleInfo += ObjectSaleInfo; | 2588 | client.OnObjectSaleInfo += ObjectSaleInfo; |
@@ -2705,6 +2736,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2705 | client.OnGrabObject -= ProcessObjectGrab; | 2736 | client.OnGrabObject -= ProcessObjectGrab; |
2706 | client.OnDeGrabObject -= ProcessObjectDeGrab; | 2737 | client.OnDeGrabObject -= ProcessObjectDeGrab; |
2707 | client.OnUndo -= m_sceneGraph.HandleUndo; | 2738 | client.OnUndo -= m_sceneGraph.HandleUndo; |
2739 | client.OnRedo -= m_sceneGraph.HandleRedo; | ||
2708 | client.OnObjectDescription -= m_sceneGraph.PrimDescription; | 2740 | client.OnObjectDescription -= m_sceneGraph.PrimDescription; |
2709 | client.OnObjectDrop -= m_sceneGraph.DropObject; | 2741 | client.OnObjectDrop -= m_sceneGraph.DropObject; |
2710 | client.OnObjectSaleInfo -= ObjectSaleInfo; | 2742 | client.OnObjectSaleInfo -= ObjectSaleInfo; |
@@ -2953,7 +2985,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
2953 | m_log.DebugFormat("[APPEARANCE]: Appearance not found in {0}, returning default", RegionInfo.RegionName); | 2985 | m_log.DebugFormat("[APPEARANCE]: Appearance not found in {0}, returning default", RegionInfo.RegionName); |
2954 | appearance = new AvatarAppearance(client.AgentId); | 2986 | appearance = new AvatarAppearance(client.AgentId); |
2955 | } | 2987 | } |
2956 | |||
2957 | } | 2988 | } |
2958 | 2989 | ||
2959 | /// <summary> | 2990 | /// <summary> |
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 7bd4329..0132252 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs | |||
@@ -453,6 +453,15 @@ namespace OpenSim.Region.Framework.Scenes | |||
453 | part.Undo(); | 453 | part.Undo(); |
454 | } | 454 | } |
455 | } | 455 | } |
456 | protected internal void HandleRedo(IClientAPI remoteClient, UUID primId) | ||
457 | { | ||
458 | if (primId != UUID.Zero) | ||
459 | { | ||
460 | SceneObjectPart part = m_parentScene.GetSceneObjectPart(primId); | ||
461 | if (part != null) | ||
462 | part.Redo(); | ||
463 | } | ||
464 | } | ||
456 | 465 | ||
457 | protected internal void HandleObjectGroupUpdate( | 466 | protected internal void HandleObjectGroupUpdate( |
458 | IClientAPI remoteClient, UUID GroupID, uint objectLocalID, UUID Garbage) | 467 | IClientAPI remoteClient, UUID GroupID, uint objectLocalID, UUID Garbage) |
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index af46659..fe9dd9b 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | |||
@@ -298,7 +298,16 @@ namespace OpenSim.Region.Framework.Scenes | |||
298 | { | 298 | { |
299 | m_scene.CrossPrimGroupIntoNewRegion(val, this, true); | 299 | m_scene.CrossPrimGroupIntoNewRegion(val, this, true); |
300 | } | 300 | } |
301 | 301 | if (RootPart.GetStatusSandbox()) | |
302 | { | ||
303 | if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) | ||
304 | { | ||
305 | RootPart.ScriptSetPhysicsStatus(false); | ||
306 | Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"), | ||
307 | ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false); | ||
308 | return; | ||
309 | } | ||
310 | } | ||
302 | lock (m_parts) | 311 | lock (m_parts) |
303 | { | 312 | { |
304 | foreach (SceneObjectPart part in m_parts.Values) | 313 | foreach (SceneObjectPart part in m_parts.Values) |
@@ -398,6 +407,34 @@ namespace OpenSim.Region.Framework.Scenes | |||
398 | } | 407 | } |
399 | } | 408 | } |
400 | 409 | ||
410 | private SceneObjectPart m_PlaySoundMasterPrim = null; | ||
411 | public SceneObjectPart PlaySoundMasterPrim | ||
412 | { | ||
413 | get { return m_PlaySoundMasterPrim; } | ||
414 | set { m_PlaySoundMasterPrim = value; } | ||
415 | } | ||
416 | |||
417 | private List<SceneObjectPart> m_PlaySoundSlavePrims = new List<SceneObjectPart>(); | ||
418 | public List<SceneObjectPart> PlaySoundSlavePrims | ||
419 | { | ||
420 | get { return m_LoopSoundSlavePrims; } | ||
421 | set { m_LoopSoundSlavePrims = value; } | ||
422 | } | ||
423 | |||
424 | private SceneObjectPart m_LoopSoundMasterPrim = null; | ||
425 | public SceneObjectPart LoopSoundMasterPrim | ||
426 | { | ||
427 | get { return m_LoopSoundMasterPrim; } | ||
428 | set { m_LoopSoundMasterPrim = value; } | ||
429 | } | ||
430 | |||
431 | private List<SceneObjectPart> m_LoopSoundSlavePrims = new List<SceneObjectPart>(); | ||
432 | public List<SceneObjectPart> LoopSoundSlavePrims | ||
433 | { | ||
434 | get { return m_LoopSoundSlavePrims; } | ||
435 | set { m_LoopSoundSlavePrims = value; } | ||
436 | } | ||
437 | |||
401 | // The UUID for the Region this Object is in. | 438 | // The UUID for the Region this Object is in. |
402 | public UUID RegionUUID | 439 | public UUID RegionUUID |
403 | { | 440 | { |
@@ -1779,32 +1816,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
1779 | } | 1816 | } |
1780 | } | 1817 | } |
1781 | 1818 | ||
1782 | public void rotLookAt(Quaternion target, float strength, float damping) | ||
1783 | { | ||
1784 | SceneObjectPart rootpart = m_rootPart; | ||
1785 | if (rootpart != null) | ||
1786 | { | ||
1787 | if (IsAttachment) | ||
1788 | { | ||
1789 | /* | ||
1790 | ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar); | ||
1791 | if (avatar != null) | ||
1792 | { | ||
1793 | Rotate the Av? | ||
1794 | } */ | ||
1795 | } | ||
1796 | else | ||
1797 | { | ||
1798 | if (rootpart.PhysActor != null) | ||
1799 | { | ||
1800 | rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W); | ||
1801 | rootpart.PhysActor.APIDStrength = strength; | ||
1802 | rootpart.PhysActor.APIDDamping = damping; | ||
1803 | rootpart.PhysActor.APIDActive = true; | ||
1804 | } | ||
1805 | } | ||
1806 | } | ||
1807 | } | ||
1808 | public void stopLookAt() | 1819 | public void stopLookAt() |
1809 | { | 1820 | { |
1810 | SceneObjectPart rootpart = m_rootPart; | 1821 | SceneObjectPart rootpart = m_rootPart; |
@@ -1963,6 +1974,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
1963 | 1974 | ||
1964 | foreach (SceneObjectPart part in m_parts.Values) | 1975 | foreach (SceneObjectPart part in m_parts.Values) |
1965 | { | 1976 | { |
1977 | if (!IsSelected) | ||
1978 | part.UpdateLookAt(); | ||
1966 | part.SendScheduledUpdates(); | 1979 | part.SendScheduledUpdates(); |
1967 | } | 1980 | } |
1968 | } | 1981 | } |
@@ -2452,11 +2465,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
2452 | { | 2465 | { |
2453 | if (m_rootPart.PhysActor.IsPhysical) | 2466 | if (m_rootPart.PhysActor.IsPhysical) |
2454 | { | 2467 | { |
2455 | Vector3 llmoveforce = pos - AbsolutePosition; | 2468 | if (!m_rootPart.BlockGrab) |
2456 | Vector3 grabforce = llmoveforce; | 2469 | { |
2457 | grabforce = (grabforce / 10) * m_rootPart.PhysActor.Mass; | 2470 | Vector3 llmoveforce = pos - AbsolutePosition; |
2458 | m_rootPart.PhysActor.AddForce(grabforce,true); | 2471 | Vector3 grabforce = llmoveforce; |
2459 | m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); | 2472 | grabforce = (grabforce / 10) * m_rootPart.PhysActor.Mass; |
2473 | m_rootPart.PhysActor.AddForce(grabforce, true); | ||
2474 | m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); | ||
2475 | } | ||
2460 | } | 2476 | } |
2461 | else | 2477 | else |
2462 | { | 2478 | { |
@@ -2812,6 +2828,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2812 | SceneObjectPart part = GetChildPart(localID); | 2828 | SceneObjectPart part = GetChildPart(localID); |
2813 | if (part != null) | 2829 | if (part != null) |
2814 | { | 2830 | { |
2831 | part.IgnoreUndoUpdate = true; | ||
2815 | if (scale.X > m_scene.m_maxNonphys) | 2832 | if (scale.X > m_scene.m_maxNonphys) |
2816 | scale.X = m_scene.m_maxNonphys; | 2833 | scale.X = m_scene.m_maxNonphys; |
2817 | if (scale.Y > m_scene.m_maxNonphys) | 2834 | if (scale.Y > m_scene.m_maxNonphys) |
@@ -2839,6 +2856,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2839 | { | 2856 | { |
2840 | if (obPart.UUID != m_rootPart.UUID) | 2857 | if (obPart.UUID != m_rootPart.UUID) |
2841 | { | 2858 | { |
2859 | obPart.IgnoreUndoUpdate = true; | ||
2842 | Vector3 oldSize = new Vector3(obPart.Scale); | 2860 | Vector3 oldSize = new Vector3(obPart.Scale); |
2843 | 2861 | ||
2844 | float f = 1.0f; | 2862 | float f = 1.0f; |
@@ -2898,6 +2916,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
2898 | z *= a; | 2916 | z *= a; |
2899 | } | 2917 | } |
2900 | } | 2918 | } |
2919 | obPart.IgnoreUndoUpdate = false; | ||
2920 | obPart.StoreUndoState(); | ||
2901 | } | 2921 | } |
2902 | } | 2922 | } |
2903 | } | 2923 | } |
@@ -2913,6 +2933,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2913 | { | 2933 | { |
2914 | foreach (SceneObjectPart obPart in m_parts.Values) | 2934 | foreach (SceneObjectPart obPart in m_parts.Values) |
2915 | { | 2935 | { |
2936 | obPart.IgnoreUndoUpdate = true; | ||
2916 | if (obPart.UUID != m_rootPart.UUID) | 2937 | if (obPart.UUID != m_rootPart.UUID) |
2917 | { | 2938 | { |
2918 | Vector3 currentpos = new Vector3(obPart.OffsetPosition); | 2939 | Vector3 currentpos = new Vector3(obPart.OffsetPosition); |
@@ -2926,6 +2947,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
2926 | obPart.Resize(newSize); | 2947 | obPart.Resize(newSize); |
2927 | obPart.UpdateOffSet(currentpos); | 2948 | obPart.UpdateOffSet(currentpos); |
2928 | } | 2949 | } |
2950 | obPart.IgnoreUndoUpdate = false; | ||
2951 | obPart.StoreUndoState(); | ||
2929 | } | 2952 | } |
2930 | } | 2953 | } |
2931 | 2954 | ||
@@ -2935,6 +2958,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
2935 | m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); | 2958 | m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); |
2936 | } | 2959 | } |
2937 | 2960 | ||
2961 | part.IgnoreUndoUpdate = false; | ||
2962 | part.StoreUndoState(); | ||
2938 | HasGroupChanged = true; | 2963 | HasGroupChanged = true; |
2939 | ScheduleGroupForTerseUpdate(); | 2964 | ScheduleGroupForTerseUpdate(); |
2940 | } | 2965 | } |
@@ -2950,13 +2975,26 @@ namespace OpenSim.Region.Framework.Scenes | |||
2950 | /// <param name="pos"></param> | 2975 | /// <param name="pos"></param> |
2951 | public void UpdateGroupPosition(Vector3 pos) | 2976 | public void UpdateGroupPosition(Vector3 pos) |
2952 | { | 2977 | { |
2978 | foreach (SceneObjectPart part in Children.Values) | ||
2979 | { | ||
2980 | part.StoreUndoState(); | ||
2981 | } | ||
2953 | if (m_scene.EventManager.TriggerGroupMove(UUID, pos)) | 2982 | if (m_scene.EventManager.TriggerGroupMove(UUID, pos)) |
2954 | { | 2983 | { |
2955 | if (IsAttachment) | 2984 | if (IsAttachment) |
2956 | { | 2985 | { |
2957 | m_rootPart.AttachedPos = pos; | 2986 | m_rootPart.AttachedPos = pos; |
2958 | } | 2987 | } |
2959 | 2988 | if (RootPart.GetStatusSandbox()) | |
2989 | { | ||
2990 | if (Util.GetDistanceTo(RootPart.StatusSandboxPos, pos) > 10) | ||
2991 | { | ||
2992 | RootPart.ScriptSetPhysicsStatus(false); | ||
2993 | pos = AbsolutePosition; | ||
2994 | Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"), | ||
2995 | ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false); | ||
2996 | } | ||
2997 | } | ||
2960 | AbsolutePosition = pos; | 2998 | AbsolutePosition = pos; |
2961 | 2999 | ||
2962 | HasGroupChanged = true; | 3000 | HasGroupChanged = true; |
@@ -2975,7 +3013,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
2975 | public void UpdateSinglePosition(Vector3 pos, uint localID) | 3013 | public void UpdateSinglePosition(Vector3 pos, uint localID) |
2976 | { | 3014 | { |
2977 | SceneObjectPart part = GetChildPart(localID); | 3015 | SceneObjectPart part = GetChildPart(localID); |
2978 | 3016 | foreach (SceneObjectPart parts in Children.Values) | |
3017 | { | ||
3018 | parts.StoreUndoState(); | ||
3019 | } | ||
2979 | if (part != null) | 3020 | if (part != null) |
2980 | { | 3021 | { |
2981 | if (part.UUID == m_rootPart.UUID) | 3022 | if (part.UUID == m_rootPart.UUID) |
@@ -2997,6 +3038,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
2997 | /// <param name="pos"></param> | 3038 | /// <param name="pos"></param> |
2998 | private void UpdateRootPosition(Vector3 pos) | 3039 | private void UpdateRootPosition(Vector3 pos) |
2999 | { | 3040 | { |
3041 | foreach (SceneObjectPart part in Children.Values) | ||
3042 | { | ||
3043 | part.StoreUndoState(); | ||
3044 | } | ||
3000 | Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z); | 3045 | Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z); |
3001 | Vector3 oldPos = | 3046 | Vector3 oldPos = |
3002 | new Vector3(AbsolutePosition.X + m_rootPart.OffsetPosition.X, | 3047 | new Vector3(AbsolutePosition.X + m_rootPart.OffsetPosition.X, |
@@ -3040,6 +3085,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
3040 | /// <param name="rot"></param> | 3085 | /// <param name="rot"></param> |
3041 | public void UpdateGroupRotationR(Quaternion rot) | 3086 | public void UpdateGroupRotationR(Quaternion rot) |
3042 | { | 3087 | { |
3088 | foreach (SceneObjectPart parts in Children.Values) | ||
3089 | { | ||
3090 | parts.StoreUndoState(); | ||
3091 | } | ||
3043 | m_rootPart.UpdateRotation(rot); | 3092 | m_rootPart.UpdateRotation(rot); |
3044 | 3093 | ||
3045 | PhysicsActor actor = m_rootPart.PhysActor; | 3094 | PhysicsActor actor = m_rootPart.PhysActor; |
@@ -3060,6 +3109,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
3060 | /// <param name="rot"></param> | 3109 | /// <param name="rot"></param> |
3061 | public void UpdateGroupRotationPR(Vector3 pos, Quaternion rot) | 3110 | public void UpdateGroupRotationPR(Vector3 pos, Quaternion rot) |
3062 | { | 3111 | { |
3112 | foreach (SceneObjectPart parts in Children.Values) | ||
3113 | { | ||
3114 | parts.StoreUndoState(); | ||
3115 | } | ||
3063 | m_rootPart.UpdateRotation(rot); | 3116 | m_rootPart.UpdateRotation(rot); |
3064 | 3117 | ||
3065 | PhysicsActor actor = m_rootPart.PhysActor; | 3118 | PhysicsActor actor = m_rootPart.PhysActor; |
@@ -3083,6 +3136,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
3083 | public void UpdateSingleRotation(Quaternion rot, uint localID) | 3136 | public void UpdateSingleRotation(Quaternion rot, uint localID) |
3084 | { | 3137 | { |
3085 | SceneObjectPart part = GetChildPart(localID); | 3138 | SceneObjectPart part = GetChildPart(localID); |
3139 | foreach (SceneObjectPart parts in Children.Values) | ||
3140 | { | ||
3141 | parts.StoreUndoState(); | ||
3142 | } | ||
3086 | if (part != null) | 3143 | if (part != null) |
3087 | { | 3144 | { |
3088 | if (part.UUID == m_rootPart.UUID) | 3145 | if (part.UUID == m_rootPart.UUID) |
@@ -3113,8 +3170,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
3113 | } | 3170 | } |
3114 | else | 3171 | else |
3115 | { | 3172 | { |
3173 | part.IgnoreUndoUpdate = true; | ||
3116 | part.UpdateRotation(rot); | 3174 | part.UpdateRotation(rot); |
3117 | part.OffsetPosition = pos; | 3175 | part.OffsetPosition = pos; |
3176 | part.IgnoreUndoUpdate = false; | ||
3177 | part.StoreUndoState(); | ||
3118 | } | 3178 | } |
3119 | } | 3179 | } |
3120 | } | 3180 | } |
@@ -3128,6 +3188,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3128 | Quaternion axRot = rot; | 3188 | Quaternion axRot = rot; |
3129 | Quaternion oldParentRot = m_rootPart.RotationOffset; | 3189 | Quaternion oldParentRot = m_rootPart.RotationOffset; |
3130 | 3190 | ||
3191 | m_rootPart.StoreUndoState(); | ||
3131 | m_rootPart.UpdateRotation(rot); | 3192 | m_rootPart.UpdateRotation(rot); |
3132 | if (m_rootPart.PhysActor != null) | 3193 | if (m_rootPart.PhysActor != null) |
3133 | { | 3194 | { |
@@ -3141,6 +3202,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3141 | { | 3202 | { |
3142 | if (prim.UUID != m_rootPart.UUID) | 3203 | if (prim.UUID != m_rootPart.UUID) |
3143 | { | 3204 | { |
3205 | prim.IgnoreUndoUpdate = true; | ||
3144 | Vector3 axPos = prim.OffsetPosition; | 3206 | Vector3 axPos = prim.OffsetPosition; |
3145 | axPos *= oldParentRot; | 3207 | axPos *= oldParentRot; |
3146 | axPos *= Quaternion.Inverse(axRot); | 3208 | axPos *= Quaternion.Inverse(axRot); |
@@ -3153,7 +3215,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
3153 | } | 3215 | } |
3154 | } | 3216 | } |
3155 | } | 3217 | } |
3156 | 3218 | foreach (SceneObjectPart childpart in Children.Values) | |
3219 | { | ||
3220 | if (childpart != m_rootPart) | ||
3221 | { | ||
3222 | childpart.IgnoreUndoUpdate = false; | ||
3223 | childpart.StoreUndoState(); | ||
3224 | } | ||
3225 | } | ||
3157 | m_rootPart.ScheduleTerseUpdate(); | 3226 | m_rootPart.ScheduleTerseUpdate(); |
3158 | } | 3227 | } |
3159 | 3228 | ||
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index dd797fc..d339208 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | |||
@@ -133,6 +133,18 @@ namespace OpenSim.Region.Framework.Scenes | |||
133 | [XmlIgnore] | 133 | [XmlIgnore] |
134 | public bool DIE_AT_EDGE; | 134 | public bool DIE_AT_EDGE; |
135 | 135 | ||
136 | [XmlIgnore] | ||
137 | public bool RETURN_AT_EDGE; | ||
138 | |||
139 | [XmlIgnore] | ||
140 | public bool BlockGrab; | ||
141 | |||
142 | [XmlIgnore] | ||
143 | public bool StatusSandbox; | ||
144 | |||
145 | [XmlIgnore] | ||
146 | public Vector3 StatusSandboxPos; | ||
147 | |||
136 | // TODO: This needs to be persisted in next XML version update! | 148 | // TODO: This needs to be persisted in next XML version update! |
137 | [XmlIgnore] | 149 | [XmlIgnore] |
138 | public readonly int[] PayPrice = {-2,-2,-2,-2,-2}; | 150 | public readonly int[] PayPrice = {-2,-2,-2,-2,-2}; |
@@ -219,6 +231,15 @@ namespace OpenSim.Region.Framework.Scenes | |||
219 | [XmlIgnore] | 231 | [XmlIgnore] |
220 | public Quaternion SpinOldOrientation = Quaternion.Identity; | 232 | public Quaternion SpinOldOrientation = Quaternion.Identity; |
221 | 233 | ||
234 | [XmlIgnore] | ||
235 | public Quaternion m_APIDTarget = Quaternion.Identity; | ||
236 | |||
237 | [XmlIgnore] | ||
238 | public float m_APIDDamp = 0; | ||
239 | |||
240 | [XmlIgnore] | ||
241 | public float m_APIDStrength = 0; | ||
242 | |||
222 | /// <summary> | 243 | /// <summary> |
223 | /// This part's inventory | 244 | /// This part's inventory |
224 | /// </summary> | 245 | /// </summary> |
@@ -233,6 +254,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
233 | public bool Undoing; | 254 | public bool Undoing; |
234 | 255 | ||
235 | [XmlIgnore] | 256 | [XmlIgnore] |
257 | public bool IgnoreUndoUpdate = false; | ||
258 | |||
259 | [XmlIgnore] | ||
236 | private PrimFlags LocalFlags; | 260 | private PrimFlags LocalFlags; |
237 | [XmlIgnore] | 261 | [XmlIgnore] |
238 | private float m_damage = -1.0f; | 262 | private float m_damage = -1.0f; |
@@ -253,6 +277,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
253 | private string m_text = String.Empty; | 277 | private string m_text = String.Empty; |
254 | private string m_touchName = String.Empty; | 278 | private string m_touchName = String.Empty; |
255 | private readonly UndoStack<UndoState> m_undo = new UndoStack<UndoState>(5); | 279 | private readonly UndoStack<UndoState> m_undo = new UndoStack<UndoState>(5); |
280 | private readonly UndoStack<UndoState> m_redo = new UndoStack<UndoState>(5); | ||
256 | private UUID _creatorID; | 281 | private UUID _creatorID; |
257 | 282 | ||
258 | private bool m_passTouches; | 283 | private bool m_passTouches; |
@@ -501,6 +526,27 @@ namespace OpenSim.Region.Framework.Scenes | |||
501 | } | 526 | } |
502 | } | 527 | } |
503 | 528 | ||
529 | [XmlIgnore] | ||
530 | public Quaternion APIDTarget | ||
531 | { | ||
532 | get { return m_APIDTarget; } | ||
533 | set { m_APIDTarget = value; } | ||
534 | } | ||
535 | |||
536 | [XmlIgnore] | ||
537 | public float APIDDamp | ||
538 | { | ||
539 | get { return m_APIDDamp; } | ||
540 | set { m_APIDDamp = value; } | ||
541 | } | ||
542 | |||
543 | [XmlIgnore] | ||
544 | public float APIDStrength | ||
545 | { | ||
546 | get { return m_APIDStrength; } | ||
547 | set { m_APIDStrength = value; } | ||
548 | } | ||
549 | |||
504 | public ulong RegionHandle | 550 | public ulong RegionHandle |
505 | { | 551 | { |
506 | get { return m_regionHandle; } | 552 | get { return m_regionHandle; } |
@@ -512,6 +558,33 @@ namespace OpenSim.Region.Framework.Scenes | |||
512 | get { return m_scriptAccessPin; } | 558 | get { return m_scriptAccessPin; } |
513 | set { m_scriptAccessPin = (int)value; } | 559 | set { m_scriptAccessPin = (int)value; } |
514 | } | 560 | } |
561 | private SceneObjectPart m_PlaySoundMasterPrim = null; | ||
562 | public SceneObjectPart PlaySoundMasterPrim | ||
563 | { | ||
564 | get { return m_PlaySoundMasterPrim; } | ||
565 | set { m_PlaySoundMasterPrim = value; } | ||
566 | } | ||
567 | |||
568 | private List<SceneObjectPart> m_PlaySoundSlavePrims = new List<SceneObjectPart>(); | ||
569 | public List<SceneObjectPart> PlaySoundSlavePrims | ||
570 | { | ||
571 | get { return m_LoopSoundSlavePrims; } | ||
572 | set { m_LoopSoundSlavePrims = value; } | ||
573 | } | ||
574 | |||
575 | private SceneObjectPart m_LoopSoundMasterPrim = null; | ||
576 | public SceneObjectPart LoopSoundMasterPrim | ||
577 | { | ||
578 | get { return m_LoopSoundMasterPrim; } | ||
579 | set { m_LoopSoundMasterPrim = value; } | ||
580 | } | ||
581 | |||
582 | private List<SceneObjectPart> m_LoopSoundSlavePrims = new List<SceneObjectPart>(); | ||
583 | public List<SceneObjectPart> LoopSoundSlavePrims | ||
584 | { | ||
585 | get { return m_LoopSoundSlavePrims; } | ||
586 | set { m_LoopSoundSlavePrims = value; } | ||
587 | } | ||
515 | 588 | ||
516 | [XmlIgnore] | 589 | [XmlIgnore] |
517 | public Byte[] TextureAnimation | 590 | public Byte[] TextureAnimation |
@@ -573,8 +646,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
573 | } | 646 | } |
574 | set | 647 | set |
575 | { | 648 | { |
576 | StoreUndoState(); | ||
577 | |||
578 | m_groupPosition = value; | 649 | m_groupPosition = value; |
579 | 650 | ||
580 | PhysicsActor actor = PhysActor; | 651 | PhysicsActor actor = PhysActor; |
@@ -1401,6 +1472,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
1401 | { | 1472 | { |
1402 | m_undo.Clear(); | 1473 | m_undo.Clear(); |
1403 | } | 1474 | } |
1475 | lock (m_redo) | ||
1476 | { | ||
1477 | m_redo.Clear(); | ||
1478 | } | ||
1404 | StoreUndoState(); | 1479 | StoreUndoState(); |
1405 | } | 1480 | } |
1406 | 1481 | ||
@@ -1711,6 +1786,66 @@ namespace OpenSim.Region.Framework.Scenes | |||
1711 | return m_parentGroup.RootPart.DIE_AT_EDGE; | 1786 | return m_parentGroup.RootPart.DIE_AT_EDGE; |
1712 | } | 1787 | } |
1713 | 1788 | ||
1789 | public bool GetReturnAtEdge() | ||
1790 | { | ||
1791 | if (m_parentGroup == null) | ||
1792 | return false; | ||
1793 | if (m_parentGroup.IsDeleted) | ||
1794 | return false; | ||
1795 | |||
1796 | return m_parentGroup.RootPart.RETURN_AT_EDGE; | ||
1797 | } | ||
1798 | |||
1799 | public void SetReturnAtEdge(bool p) | ||
1800 | { | ||
1801 | if (m_parentGroup == null) | ||
1802 | return; | ||
1803 | if (m_parentGroup.IsDeleted) | ||
1804 | return; | ||
1805 | |||
1806 | m_parentGroup.RootPart.RETURN_AT_EDGE = p; | ||
1807 | } | ||
1808 | |||
1809 | public bool GetBlockGrab() | ||
1810 | { | ||
1811 | if (m_parentGroup == null) | ||
1812 | return false; | ||
1813 | if (m_parentGroup.IsDeleted) | ||
1814 | return false; | ||
1815 | |||
1816 | return m_parentGroup.RootPart.BlockGrab; | ||
1817 | } | ||
1818 | |||
1819 | public void SetBlockGrab(bool p) | ||
1820 | { | ||
1821 | if (m_parentGroup == null) | ||
1822 | return; | ||
1823 | if (m_parentGroup.IsDeleted) | ||
1824 | return; | ||
1825 | |||
1826 | m_parentGroup.RootPart.BlockGrab = p; | ||
1827 | } | ||
1828 | |||
1829 | public void SetStatusSandbox(bool p) | ||
1830 | { | ||
1831 | if (m_parentGroup == null) | ||
1832 | return; | ||
1833 | if (m_parentGroup.IsDeleted) | ||
1834 | return; | ||
1835 | StatusSandboxPos = m_parentGroup.RootPart.AbsolutePosition; | ||
1836 | m_parentGroup.RootPart.StatusSandbox = p; | ||
1837 | } | ||
1838 | |||
1839 | public bool GetStatusSandbox() | ||
1840 | { | ||
1841 | if (m_parentGroup == null) | ||
1842 | return false; | ||
1843 | if (m_parentGroup.IsDeleted) | ||
1844 | return false; | ||
1845 | |||
1846 | return m_parentGroup.RootPart.StatusSandbox; | ||
1847 | } | ||
1848 | |||
1714 | public int GetAxisRotation(int axis) | 1849 | public int GetAxisRotation(int axis) |
1715 | { | 1850 | { |
1716 | //Cannot use ScriptBaseClass constants as no referance to it currently. | 1851 | //Cannot use ScriptBaseClass constants as no referance to it currently. |
@@ -1917,7 +2052,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1917 | // play the sound. | 2052 | // play the sound. |
1918 | if (startedColliders.Count > 0 && CollisionSound != UUID.Zero && CollisionSoundVolume > 0.0f) | 2053 | if (startedColliders.Count > 0 && CollisionSound != UUID.Zero && CollisionSoundVolume > 0.0f) |
1919 | { | 2054 | { |
1920 | SendSound(CollisionSound.ToString(), CollisionSoundVolume, true, (byte)0); | 2055 | SendSound(CollisionSound.ToString(), CollisionSoundVolume, true, (byte)0, 0, false, false); |
1921 | } | 2056 | } |
1922 | 2057 | ||
1923 | if ((m_parentGroup.RootPart.ScriptEvents & scriptEvents.collision_start) != 0) | 2058 | if ((m_parentGroup.RootPart.ScriptEvents & scriptEvents.collision_start) != 0) |
@@ -2491,9 +2626,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
2491 | List<ScenePresence> avatarts = m_parentGroup.Scene.GetAvatars(); | 2626 | List<ScenePresence> avatarts = m_parentGroup.Scene.GetAvatars(); |
2492 | foreach (ScenePresence p in avatarts) | 2627 | foreach (ScenePresence p in avatarts) |
2493 | { | 2628 | { |
2494 | // TODO: some filtering by distance of avatar | 2629 | if (!(Util.GetDistanceTo(p.AbsolutePosition, AbsolutePosition) >= 100)) |
2495 | 2630 | p.ControllingClient.SendPreLoadSound(objectID, objectID, soundID); | |
2496 | p.ControllingClient.SendPreLoadSound(objectID, objectID, soundID); | ||
2497 | } | 2631 | } |
2498 | } | 2632 | } |
2499 | 2633 | ||
@@ -2554,7 +2688,38 @@ namespace OpenSim.Region.Framework.Scenes | |||
2554 | 2688 | ||
2555 | public void RotLookAt(Quaternion target, float strength, float damping) | 2689 | public void RotLookAt(Quaternion target, float strength, float damping) |
2556 | { | 2690 | { |
2557 | m_parentGroup.rotLookAt(target, strength, damping); | 2691 | rotLookAt(target, strength, damping); |
2692 | } | ||
2693 | |||
2694 | public void rotLookAt(Quaternion target, float strength, float damping) | ||
2695 | { | ||
2696 | if (IsAttachment) | ||
2697 | { | ||
2698 | /* | ||
2699 | ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar); | ||
2700 | if (avatar != null) | ||
2701 | { | ||
2702 | Rotate the Av? | ||
2703 | } */ | ||
2704 | } | ||
2705 | else | ||
2706 | { | ||
2707 | APIDDamp = damping; | ||
2708 | APIDStrength = strength; | ||
2709 | APIDTarget = target; | ||
2710 | } | ||
2711 | } | ||
2712 | |||
2713 | public void startLookAt(Quaternion rot, float damp, float strength) | ||
2714 | { | ||
2715 | APIDDamp = damp; | ||
2716 | APIDStrength = strength; | ||
2717 | APIDTarget = rot; | ||
2718 | } | ||
2719 | |||
2720 | public void stopLookAt() | ||
2721 | { | ||
2722 | APIDTarget = Quaternion.Identity; | ||
2558 | } | 2723 | } |
2559 | 2724 | ||
2560 | /// <summary> | 2725 | /// <summary> |
@@ -2814,7 +2979,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2814 | /// <param name="volume"></param> | 2979 | /// <param name="volume"></param> |
2815 | /// <param name="triggered"></param> | 2980 | /// <param name="triggered"></param> |
2816 | /// <param name="flags"></param> | 2981 | /// <param name="flags"></param> |
2817 | public void SendSound(string sound, double volume, bool triggered, byte flags) | 2982 | public void SendSound(string sound, double volume, bool triggered, byte flags, float radius, bool useMaster, bool isMaster) |
2818 | { | 2983 | { |
2819 | if (volume > 1) | 2984 | if (volume > 1) |
2820 | volume = 1; | 2985 | volume = 1; |
@@ -2850,10 +3015,51 @@ namespace OpenSim.Region.Framework.Scenes | |||
2850 | ISoundModule soundModule = m_parentGroup.Scene.RequestModuleInterface<ISoundModule>(); | 3015 | ISoundModule soundModule = m_parentGroup.Scene.RequestModuleInterface<ISoundModule>(); |
2851 | if (soundModule != null) | 3016 | if (soundModule != null) |
2852 | { | 3017 | { |
2853 | if (triggered) | 3018 | if (useMaster) |
2854 | soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle); | 3019 | { |
3020 | if (isMaster) | ||
3021 | { | ||
3022 | if (triggered) | ||
3023 | soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, radius); | ||
3024 | else | ||
3025 | soundModule.PlayAttachedSound(soundID, ownerID, objectID, volume, position, flags, radius); | ||
3026 | ParentGroup.PlaySoundMasterPrim = this; | ||
3027 | ownerID = this._ownerID; | ||
3028 | objectID = this.UUID; | ||
3029 | parentID = this.GetRootPartUUID(); | ||
3030 | position = this.AbsolutePosition; // region local | ||
3031 | regionHandle = this.ParentGroup.Scene.RegionInfo.RegionHandle; | ||
3032 | if (triggered) | ||
3033 | soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, radius); | ||
3034 | else | ||
3035 | soundModule.PlayAttachedSound(soundID, ownerID, objectID, volume, position, flags, radius); | ||
3036 | foreach (SceneObjectPart prim in ParentGroup.PlaySoundSlavePrims) | ||
3037 | { | ||
3038 | ownerID = prim._ownerID; | ||
3039 | objectID = prim.UUID; | ||
3040 | parentID = prim.GetRootPartUUID(); | ||
3041 | position = prim.AbsolutePosition; // region local | ||
3042 | regionHandle = prim.ParentGroup.Scene.RegionInfo.RegionHandle; | ||
3043 | if (triggered) | ||
3044 | soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, radius); | ||
3045 | else | ||
3046 | soundModule.PlayAttachedSound(soundID, ownerID, objectID, volume, position, flags, radius); | ||
3047 | } | ||
3048 | ParentGroup.PlaySoundSlavePrims.Clear(); | ||
3049 | ParentGroup.PlaySoundMasterPrim = null; | ||
3050 | } | ||
3051 | else | ||
3052 | { | ||
3053 | ParentGroup.PlaySoundSlavePrims.Add(this); | ||
3054 | } | ||
3055 | } | ||
2855 | else | 3056 | else |
2856 | soundModule.PlayAttachedSound(soundID, ownerID, objectID, volume, position, flags); | 3057 | { |
3058 | if (triggered) | ||
3059 | soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, radius); | ||
3060 | else | ||
3061 | soundModule.PlayAttachedSound(soundID, ownerID, objectID, volume, position, flags, radius); | ||
3062 | } | ||
2857 | } | 3063 | } |
2858 | } | 3064 | } |
2859 | 3065 | ||
@@ -3156,6 +3362,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
3156 | hasProfileCut = hasDimple; // is it the same thing? | 3362 | hasProfileCut = hasDimple; // is it the same thing? |
3157 | } | 3363 | } |
3158 | 3364 | ||
3365 | public void SetVehicleFlags(int param, bool remove) | ||
3366 | { | ||
3367 | if (PhysActor != null) | ||
3368 | { | ||
3369 | PhysActor.VehicleFlags(param, remove); | ||
3370 | } | ||
3371 | } | ||
3372 | |||
3159 | public void SetGroup(UUID groupID, IClientAPI client) | 3373 | public void SetGroup(UUID groupID, IClientAPI client) |
3160 | { | 3374 | { |
3161 | _groupID = groupID; | 3375 | _groupID = groupID; |
@@ -3260,27 +3474,30 @@ namespace OpenSim.Region.Framework.Scenes | |||
3260 | { | 3474 | { |
3261 | if (!Undoing) | 3475 | if (!Undoing) |
3262 | { | 3476 | { |
3263 | if (m_parentGroup != null) | 3477 | if (!IgnoreUndoUpdate) |
3264 | { | 3478 | { |
3265 | lock (m_undo) | 3479 | if (m_parentGroup != null) |
3266 | { | 3480 | { |
3267 | if (m_undo.Count > 0) | 3481 | lock (m_undo) |
3268 | { | 3482 | { |
3269 | UndoState last = m_undo.Peek(); | 3483 | if (m_undo.Count > 0) |
3270 | if (last != null) | ||
3271 | { | 3484 | { |
3272 | if (last.Compare(this)) | 3485 | UndoState last = m_undo.Peek(); |
3273 | return; | 3486 | if (last != null) |
3487 | { | ||
3488 | if (last.Compare(this)) | ||
3489 | return; | ||
3490 | } | ||
3274 | } | 3491 | } |
3275 | } | ||
3276 | 3492 | ||
3277 | if (m_parentGroup.GetSceneMaxUndo() > 0) | 3493 | if (m_parentGroup.GetSceneMaxUndo() > 0) |
3278 | { | 3494 | { |
3279 | UndoState nUndo = new UndoState(this); | 3495 | UndoState nUndo = new UndoState(this); |
3280 | 3496 | ||
3281 | m_undo.Push(nUndo); | 3497 | m_undo.Push(nUndo); |
3282 | } | 3498 | } |
3283 | 3499 | ||
3500 | } | ||
3284 | } | 3501 | } |
3285 | } | 3502 | } |
3286 | } | 3503 | } |
@@ -3751,11 +3968,36 @@ namespace OpenSim.Region.Framework.Scenes | |||
3751 | lock (m_undo) | 3968 | lock (m_undo) |
3752 | { | 3969 | { |
3753 | if (m_undo.Count > 0) | 3970 | if (m_undo.Count > 0) |
3971 | { | ||
3972 | UndoState nUndo = null; | ||
3973 | if (m_parentGroup.GetSceneMaxUndo() > 0) | ||
3754 | { | 3974 | { |
3755 | UndoState goback = m_undo.Pop(); | 3975 | nUndo = new UndoState(this); |
3756 | if (goback != null) | 3976 | } |
3757 | goback.PlaybackState(this); | 3977 | UndoState goback = m_undo.Pop(); |
3978 | if (goback != null) | ||
3979 | { | ||
3980 | goback.PlaybackState(this); | ||
3981 | if (nUndo != null) | ||
3982 | m_redo.Push(nUndo); | ||
3983 | } | ||
3984 | } | ||
3985 | } | ||
3986 | } | ||
3987 | |||
3988 | public void Redo() | ||
3989 | { | ||
3990 | lock (m_redo) | ||
3991 | { | ||
3992 | if (m_parentGroup.GetSceneMaxUndo() > 0) | ||
3993 | { | ||
3994 | UndoState nUndo = new UndoState(this); | ||
3995 | |||
3996 | m_undo.Push(nUndo); | ||
3758 | } | 3997 | } |
3998 | UndoState gofwd = m_redo.Pop(); | ||
3999 | if (gofwd != null) | ||
4000 | gofwd.PlayfwdState(this); | ||
3759 | } | 4001 | } |
3760 | } | 4002 | } |
3761 | 4003 | ||
@@ -3802,6 +4044,18 @@ namespace OpenSim.Region.Framework.Scenes | |||
3802 | (pos.Z != OffsetPosition.Z)) | 4044 | (pos.Z != OffsetPosition.Z)) |
3803 | { | 4045 | { |
3804 | Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z); | 4046 | Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z); |
4047 | |||
4048 | if (ParentGroup.RootPart.GetStatusSandbox()) | ||
4049 | { | ||
4050 | if (Util.GetDistanceTo(ParentGroup.RootPart.StatusSandboxPos, newPos) > 10) | ||
4051 | { | ||
4052 | ParentGroup.RootPart.ScriptSetPhysicsStatus(false); | ||
4053 | newPos = OffsetPosition; | ||
4054 | ParentGroup.Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"), | ||
4055 | ChatTypeEnum.DebugChannel, 0x7FFFFFFF, ParentGroup.RootPart.AbsolutePosition, Name, UUID, false); | ||
4056 | } | ||
4057 | } | ||
4058 | |||
3805 | OffsetPosition = newPos; | 4059 | OffsetPosition = newPos; |
3806 | ScheduleTerseUpdate(); | 4060 | ScheduleTerseUpdate(); |
3807 | } | 4061 | } |
@@ -4094,7 +4348,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
4094 | (rot.Z != RotationOffset.Z) || | 4348 | (rot.Z != RotationOffset.Z) || |
4095 | (rot.W != RotationOffset.W)) | 4349 | (rot.W != RotationOffset.W)) |
4096 | { | 4350 | { |
4097 | //StoreUndoState(); | ||
4098 | RotationOffset = rot; | 4351 | RotationOffset = rot; |
4099 | ParentGroup.HasGroupChanged = true; | 4352 | ParentGroup.HasGroupChanged = true; |
4100 | ScheduleTerseUpdate(); | 4353 | ScheduleTerseUpdate(); |
@@ -4396,5 +4649,36 @@ namespace OpenSim.Region.Framework.Scenes | |||
4396 | 4649 | ||
4397 | Inventory.ApplyNextOwnerPermissions(); | 4650 | Inventory.ApplyNextOwnerPermissions(); |
4398 | } | 4651 | } |
4652 | public void UpdateLookAt() | ||
4653 | { | ||
4654 | try | ||
4655 | { | ||
4656 | if (APIDTarget != Quaternion.Identity) | ||
4657 | { | ||
4658 | if (Single.IsNaN(APIDTarget.W) == true) | ||
4659 | { | ||
4660 | APIDTarget = Quaternion.Identity; | ||
4661 | return; | ||
4662 | } | ||
4663 | Quaternion rot = RotationOffset; | ||
4664 | Quaternion dir = (rot - APIDTarget); | ||
4665 | float speed = ((APIDStrength / APIDDamp) * (float)(Math.PI / 180.0f)); | ||
4666 | if (dir.Z > speed) | ||
4667 | { | ||
4668 | rot.Z -= speed; | ||
4669 | } | ||
4670 | if (dir.Z < -speed) | ||
4671 | { | ||
4672 | rot.Z += speed; | ||
4673 | } | ||
4674 | rot.Normalize(); | ||
4675 | UpdateRotation(rot); | ||
4676 | } | ||
4677 | } | ||
4678 | catch (Exception ex) | ||
4679 | { | ||
4680 | m_log.Error("[Physics] " + ex); | ||
4681 | } | ||
4682 | } | ||
4399 | } | 4683 | } |
4400 | } | 4684 | } |
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index b8a937a..6b6fa7c 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs | |||
@@ -164,6 +164,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
164 | 164 | ||
165 | private Quaternion m_bodyRot= Quaternion.Identity; | 165 | private Quaternion m_bodyRot= Quaternion.Identity; |
166 | 166 | ||
167 | private Quaternion m_bodyRotPrevious = Quaternion.Identity; | ||
168 | |||
167 | private const int LAND_VELOCITYMAG_MAX = 12; | 169 | private const int LAND_VELOCITYMAG_MAX = 12; |
168 | 170 | ||
169 | public bool IsRestrictedToRegion; | 171 | public bool IsRestrictedToRegion; |
@@ -510,6 +512,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
510 | set { m_bodyRot = value; } | 512 | set { m_bodyRot = value; } |
511 | } | 513 | } |
512 | 514 | ||
515 | public Quaternion PreviousRotation | ||
516 | { | ||
517 | get { return m_bodyRotPrevious; } | ||
518 | set { m_bodyRotPrevious = value; } | ||
519 | } | ||
520 | |||
513 | /// <summary> | 521 | /// <summary> |
514 | /// If this is true, agent doesn't have a representation in this scene. | 522 | /// If this is true, agent doesn't have a representation in this scene. |
515 | /// this is an agent 'looking into' this scene from a nearby scene(region) | 523 | /// this is an agent 'looking into' this scene from a nearby scene(region) |
@@ -826,6 +834,31 @@ namespace OpenSim.Region.Framework.Scenes | |||
826 | if (pos.X < 0 || pos.Y < 0 || pos.Z < 0) | 834 | if (pos.X < 0 || pos.Y < 0 || pos.Z < 0) |
827 | { | 835 | { |
828 | Vector3 emergencyPos = new Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 128); | 836 | Vector3 emergencyPos = new Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 128); |
837 | |||
838 | if (pos.X < 0) | ||
839 | { | ||
840 | emergencyPos.X = (int)Constants.RegionSize + pos.X; | ||
841 | if (!(pos.Y < 0)) | ||
842 | emergencyPos.Y = pos.Y; | ||
843 | if (!(pos.Z < 0)) | ||
844 | emergencyPos.X = pos.X; | ||
845 | } | ||
846 | if (pos.Y < 0) | ||
847 | { | ||
848 | emergencyPos.Y = (int)Constants.RegionSize + pos.Y; | ||
849 | if (!(pos.X < 0)) | ||
850 | emergencyPos.X = pos.X; | ||
851 | if (!(pos.Z < 0)) | ||
852 | emergencyPos.Z = pos.Z; | ||
853 | } | ||
854 | if (pos.Z < 0) | ||
855 | { | ||
856 | if (!(pos.X < 0)) | ||
857 | emergencyPos.X = pos.X; | ||
858 | if (!(pos.Y < 0)) | ||
859 | emergencyPos.Y = pos.Y; | ||
860 | //Leave as 128 | ||
861 | } | ||
829 | 862 | ||
830 | m_log.WarnFormat( | 863 | m_log.WarnFormat( |
831 | "[SCENE PRESENCE]: MakeRootAgent() was given an illegal position of {0} for avatar {1}, {2}. Substituting {3}", | 864 | "[SCENE PRESENCE]: MakeRootAgent() was given an illegal position of {0} for avatar {1}, {2}. Substituting {3}", |
@@ -1208,6 +1241,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
1208 | } | 1241 | } |
1209 | else | 1242 | else |
1210 | { | 1243 | { |
1244 | if (m_pos.X < 0) | ||
1245 | m_pos.X = 128; | ||
1246 | if (m_pos.Y < 0) | ||
1247 | m_pos.Y = 128; | ||
1248 | if (m_pos.X > Scene.WestBorders[0].BorderLine.X) | ||
1249 | m_pos.X = 128; | ||
1250 | if (m_pos.Y > Scene.NorthBorders[0].BorderLine.Y) | ||
1251 | m_pos.Y = 128; | ||
1211 | m_LastFinitePos = m_pos; | 1252 | m_LastFinitePos = m_pos; |
1212 | } | 1253 | } |
1213 | 1254 | ||
@@ -2518,6 +2559,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
2518 | /// </summary> | 2559 | /// </summary> |
2519 | public void SendWearables() | 2560 | public void SendWearables() |
2520 | { | 2561 | { |
2562 | m_log.DebugFormat("[SCENE]: Received request for wearables of {0}", Name); | ||
2563 | |||
2521 | ControllingClient.SendWearables(m_appearance.Wearables, m_appearance.Serial++); | 2564 | ControllingClient.SendWearables(m_appearance.Wearables, m_appearance.Serial++); |
2522 | } | 2565 | } |
2523 | 2566 | ||
@@ -2721,36 +2764,72 @@ namespace OpenSim.Region.Framework.Scenes | |||
2721 | { | 2764 | { |
2722 | // Checks if where it's headed exists a region | 2765 | // Checks if where it's headed exists a region |
2723 | 2766 | ||
2767 | bool needsTransit = false; | ||
2724 | if (m_scene.TestBorderCross(pos2, Cardinals.W)) | 2768 | if (m_scene.TestBorderCross(pos2, Cardinals.W)) |
2725 | { | 2769 | { |
2726 | if (m_scene.TestBorderCross(pos2, Cardinals.S)) | 2770 | if (m_scene.TestBorderCross(pos2, Cardinals.S)) |
2771 | { | ||
2772 | needsTransit = true; | ||
2727 | neighbor = HaveNeighbor(Cardinals.SW, ref fix); | 2773 | neighbor = HaveNeighbor(Cardinals.SW, ref fix); |
2774 | } | ||
2728 | else if (m_scene.TestBorderCross(pos2, Cardinals.N)) | 2775 | else if (m_scene.TestBorderCross(pos2, Cardinals.N)) |
2776 | { | ||
2777 | needsTransit = true; | ||
2729 | neighbor = HaveNeighbor(Cardinals.NW, ref fix); | 2778 | neighbor = HaveNeighbor(Cardinals.NW, ref fix); |
2779 | } | ||
2730 | else | 2780 | else |
2781 | { | ||
2782 | needsTransit = true; | ||
2731 | neighbor = HaveNeighbor(Cardinals.W, ref fix); | 2783 | neighbor = HaveNeighbor(Cardinals.W, ref fix); |
2784 | } | ||
2732 | } | 2785 | } |
2733 | else if (m_scene.TestBorderCross(pos2, Cardinals.E)) | 2786 | else if (m_scene.TestBorderCross(pos2, Cardinals.E)) |
2734 | { | 2787 | { |
2735 | if (m_scene.TestBorderCross(pos2, Cardinals.S)) | 2788 | if (m_scene.TestBorderCross(pos2, Cardinals.S)) |
2789 | { | ||
2790 | needsTransit = true; | ||
2736 | neighbor = HaveNeighbor(Cardinals.SE, ref fix); | 2791 | neighbor = HaveNeighbor(Cardinals.SE, ref fix); |
2792 | } | ||
2737 | else if (m_scene.TestBorderCross(pos2, Cardinals.N)) | 2793 | else if (m_scene.TestBorderCross(pos2, Cardinals.N)) |
2794 | { | ||
2795 | needsTransit = true; | ||
2738 | neighbor = HaveNeighbor(Cardinals.NE, ref fix); | 2796 | neighbor = HaveNeighbor(Cardinals.NE, ref fix); |
2797 | } | ||
2739 | else | 2798 | else |
2799 | { | ||
2800 | needsTransit = true; | ||
2740 | neighbor = HaveNeighbor(Cardinals.E, ref fix); | 2801 | neighbor = HaveNeighbor(Cardinals.E, ref fix); |
2802 | } | ||
2741 | } | 2803 | } |
2742 | else if (m_scene.TestBorderCross(pos2, Cardinals.S)) | 2804 | else if (m_scene.TestBorderCross(pos2, Cardinals.S)) |
2805 | { | ||
2806 | needsTransit = true; | ||
2743 | neighbor = HaveNeighbor(Cardinals.S, ref fix); | 2807 | neighbor = HaveNeighbor(Cardinals.S, ref fix); |
2808 | } | ||
2744 | else if (m_scene.TestBorderCross(pos2, Cardinals.N)) | 2809 | else if (m_scene.TestBorderCross(pos2, Cardinals.N)) |
2810 | { | ||
2811 | needsTransit = true; | ||
2745 | neighbor = HaveNeighbor(Cardinals.N, ref fix); | 2812 | neighbor = HaveNeighbor(Cardinals.N, ref fix); |
2813 | } | ||
2814 | |||
2746 | 2815 | ||
2747 | |||
2748 | // Makes sure avatar does not end up outside region | 2816 | // Makes sure avatar does not end up outside region |
2749 | if (neighbor < 0) | 2817 | if (neighbor <= 0) |
2750 | AbsolutePosition = new Vector3( | 2818 | { |
2751 | AbsolutePosition.X + 3*fix[0], | 2819 | if (!needsTransit) |
2752 | AbsolutePosition.Y + 3*fix[1], | 2820 | { |
2753 | AbsolutePosition.Z); | 2821 | Vector3 pos = AbsolutePosition; |
2822 | if (AbsolutePosition.X < 0) | ||
2823 | pos.X += Velocity.Y; | ||
2824 | else if (AbsolutePosition.X > Constants.RegionSize) | ||
2825 | pos.X -= Velocity.Y; | ||
2826 | if (AbsolutePosition.Y < 0) | ||
2827 | pos.Y += Velocity.Y; | ||
2828 | else if (AbsolutePosition.Y > Constants.RegionSize) | ||
2829 | pos.Y -= Velocity.Y; | ||
2830 | AbsolutePosition = pos; | ||
2831 | } | ||
2832 | } | ||
2754 | else if (neighbor > 0) | 2833 | else if (neighbor > 0) |
2755 | CrossToNewRegion(); | 2834 | CrossToNewRegion(); |
2756 | } | 2835 | } |
diff --git a/OpenSim/Region/Framework/Scenes/UndoState.cs b/OpenSim/Region/Framework/Scenes/UndoState.cs index 713ff69..55e407e 100644 --- a/OpenSim/Region/Framework/Scenes/UndoState.cs +++ b/OpenSim/Region/Framework/Scenes/UndoState.cs | |||
@@ -26,6 +26,7 @@ | |||
26 | */ | 26 | */ |
27 | 27 | ||
28 | using OpenMetaverse; | 28 | using OpenMetaverse; |
29 | using OpenSim.Region.Framework.Interfaces; | ||
29 | 30 | ||
30 | namespace OpenSim.Region.Framework.Scenes | 31 | namespace OpenSim.Region.Framework.Scenes |
31 | { | 32 | { |
@@ -35,29 +36,21 @@ namespace OpenSim.Region.Framework.Scenes | |||
35 | public Vector3 Scale = Vector3.Zero; | 36 | public Vector3 Scale = Vector3.Zero; |
36 | public Quaternion Rotation = Quaternion.Identity; | 37 | public Quaternion Rotation = Quaternion.Identity; |
37 | 38 | ||
38 | public UndoState(Vector3 pos, Quaternion rot, Vector3 scale) | ||
39 | { | ||
40 | Position = pos; | ||
41 | Rotation = rot; | ||
42 | Scale = scale; | ||
43 | } | ||
44 | |||
45 | public UndoState(SceneObjectPart part) | 39 | public UndoState(SceneObjectPart part) |
46 | { | 40 | { |
47 | if (part != null) | 41 | if (part != null) |
48 | { | 42 | { |
49 | if (part.ParentID == 0) | 43 | if (part.ParentID == 0) |
50 | { | 44 | { |
51 | Position = part.AbsolutePosition; | 45 | Position = part.ParentGroup.AbsolutePosition; |
52 | Rotation = part.RotationOffset; | 46 | Rotation = part.RotationOffset; |
53 | 47 | Scale = part.Shape.Scale; | |
54 | } | 48 | } |
55 | else | 49 | else |
56 | { | 50 | { |
57 | Position = part.OffsetPosition; | 51 | Position = part.OffsetPosition; |
58 | Rotation = part.RotationOffset; | 52 | Rotation = part.RotationOffset; |
59 | Scale = part.Shape.Scale; | 53 | Scale = part.Shape.Scale; |
60 | |||
61 | } | 54 | } |
62 | } | 55 | } |
63 | } | 56 | } |
@@ -68,7 +61,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
68 | { | 61 | { |
69 | if (part.ParentID == 0) | 62 | if (part.ParentID == 0) |
70 | { | 63 | { |
71 | if (Position == part.AbsolutePosition && Rotation == part.RotationOffset) | 64 | if (Position == part.ParentGroup.AbsolutePosition && Rotation == part.ParentGroup.Rotation) |
72 | return true; | 65 | return true; |
73 | else | 66 | else |
74 | return false; | 67 | return false; |
@@ -93,24 +86,78 @@ namespace OpenSim.Region.Framework.Scenes | |||
93 | 86 | ||
94 | if (part.ParentID == 0) | 87 | if (part.ParentID == 0) |
95 | { | 88 | { |
96 | part.ParentGroup.AbsolutePosition = Position; | 89 | if (Position != Vector3.Zero) |
97 | part.UpdateRotation(Rotation); | 90 | part.ParentGroup.AbsolutePosition = Position; |
91 | part.RotationOffset = Rotation; | ||
92 | if (Scale != Vector3.Zero) | ||
93 | part.Resize(Scale); | ||
98 | part.ParentGroup.ScheduleGroupForTerseUpdate(); | 94 | part.ParentGroup.ScheduleGroupForTerseUpdate(); |
99 | } | 95 | } |
100 | else | 96 | else |
101 | { | 97 | { |
102 | part.OffsetPosition = Position; | 98 | if (Position != Vector3.Zero) |
99 | part.OffsetPosition = Position; | ||
103 | part.UpdateRotation(Rotation); | 100 | part.UpdateRotation(Rotation); |
104 | part.Resize(Scale); | 101 | if (Scale != Vector3.Zero) |
102 | part.Resize(Scale); part.ScheduleTerseUpdate(); | ||
103 | } | ||
104 | part.Undoing = false; | ||
105 | |||
106 | } | ||
107 | } | ||
108 | public void PlayfwdState(SceneObjectPart part) | ||
109 | { | ||
110 | if (part != null) | ||
111 | { | ||
112 | part.Undoing = true; | ||
113 | |||
114 | if (part.ParentID == 0) | ||
115 | { | ||
116 | if (Position != Vector3.Zero) | ||
117 | part.ParentGroup.AbsolutePosition = Position; | ||
118 | if (Rotation != Quaternion.Identity) | ||
119 | part.UpdateRotation(Rotation); | ||
120 | if (Scale != Vector3.Zero) | ||
121 | part.Resize(Scale); | ||
122 | part.ParentGroup.ScheduleGroupForTerseUpdate(); | ||
123 | } | ||
124 | else | ||
125 | { | ||
126 | if (Position != Vector3.Zero) | ||
127 | part.OffsetPosition = Position; | ||
128 | if (Rotation != Quaternion.Identity) | ||
129 | part.UpdateRotation(Rotation); | ||
130 | if (Scale != Vector3.Zero) | ||
131 | part.Resize(Scale); | ||
105 | part.ScheduleTerseUpdate(); | 132 | part.ScheduleTerseUpdate(); |
106 | } | 133 | } |
107 | part.Undoing = false; | 134 | part.Undoing = false; |
108 | 135 | ||
109 | } | 136 | } |
110 | } | 137 | } |
138 | } | ||
139 | public class LandUndoState | ||
140 | { | ||
141 | public ITerrainModule m_terrainModule; | ||
142 | public ITerrainChannel m_terrainChannel; | ||
143 | |||
144 | public LandUndoState(ITerrainModule terrainModule, ITerrainChannel terrainChannel) | ||
145 | { | ||
146 | m_terrainModule = terrainModule; | ||
147 | m_terrainChannel = terrainChannel; | ||
148 | } | ||
149 | |||
150 | public bool Compare(ITerrainChannel terrainChannel) | ||
151 | { | ||
152 | if (m_terrainChannel != terrainChannel) | ||
153 | return false; | ||
154 | else | ||
155 | return false; | ||
156 | } | ||
111 | 157 | ||
112 | public UndoState() | 158 | public void PlaybackState() |
113 | { | 159 | { |
160 | m_terrainModule.UndoTerrain(m_terrainChannel); | ||
114 | } | 161 | } |
115 | } | 162 | } |
116 | } | 163 | } |