aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--CONTRIBUTORS.txt1
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs5
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs62
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs167
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectResizeTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectUndoRedoTests.cs184
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectUserGroupTests.cs3
-rw-r--r--bin/OpenSim.ini.example4
-rw-r--r--bin/OpenSimDefaults.ini4
9 files changed, 314 insertions, 118 deletions
diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt
index f334b3d..2d02a82 100644
--- a/CONTRIBUTORS.txt
+++ b/CONTRIBUTORS.txt
@@ -209,3 +209,4 @@ In addition, we would like to thank:
209* The NANT Developers 209* The NANT Developers
210* Microsoft (.NET, MSSQL-Adapters) 210* Microsoft (.NET, MSSQL-Adapters)
211*x 211*x
212
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index e9d1d42..2e03874 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -151,7 +151,8 @@ namespace OpenSim.Region.Framework.Scenes
151 // TODO: need to figure out how allow client agents but deny 151 // TODO: need to figure out how allow client agents but deny
152 // root agents when ACL denies access to root agent 152 // root agents when ACL denies access to root agent
153 public bool m_strictAccessControl = true; 153 public bool m_strictAccessControl = true;
154 public int MaxUndoCount = 5; 154
155 public int MaxUndoCount { get; set; }
155 156
156 // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet; 157 // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet;
157 public bool LoginLock = false; 158 public bool LoginLock = false;
@@ -741,6 +742,8 @@ namespace OpenSim.Region.Framework.Scenes
741 //Animation states 742 //Animation states
742 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false); 743 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false);
743 744
745 MaxUndoCount = startupConfig.GetInt("MaxPrimUndos", 20);
746
744 PhysicalPrims = startupConfig.GetBoolean("physical_prim", PhysicalPrims); 747 PhysicalPrims = startupConfig.GetBoolean("physical_prim", PhysicalPrims);
745 CollidablePrims = startupConfig.GetBoolean("collidable_prim", CollidablePrims); 748 CollidablePrims = startupConfig.GetBoolean("collidable_prim", CollidablePrims);
746 749
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index ac26be7..45bbbda 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -1119,14 +1119,6 @@ namespace OpenSim.Region.Framework.Scenes
1119 parts[i].UUID = UUID.Random(); 1119 parts[i].UUID = UUID.Random();
1120 } 1120 }
1121 1121
1122 // helper provided for parts.
1123 public int GetSceneMaxUndo()
1124 {
1125 if (m_scene != null)
1126 return m_scene.MaxUndoCount;
1127 return 5;
1128 }
1129
1130 // justincc: I don't believe this hack is needed any longer, especially since the physics 1122 // justincc: I don't believe this hack is needed any longer, especially since the physics
1131 // parts of set AbsolutePosition were already commented out. By changing HasGroupChanged to false 1123 // parts of set AbsolutePosition were already commented out. By changing HasGroupChanged to false
1132 // this method was preventing proper reload of scene objects. 1124 // this method was preventing proper reload of scene objects.
@@ -2703,29 +2695,32 @@ namespace OpenSim.Region.Framework.Scenes
2703// m_log.DebugFormat( 2695// m_log.DebugFormat(
2704// "[SCENE OBJECT GROUP]: Group resizing {0} {1} from {2} to {3}", Name, LocalId, RootPart.Scale, scale); 2696// "[SCENE OBJECT GROUP]: Group resizing {0} {1} from {2} to {3}", Name, LocalId, RootPart.Scale, scale);
2705 2697
2706 RootPart.StoreUndoState(true);
2707
2708 scale.X = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.X));
2709 scale.Y = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.Y));
2710 scale.Z = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.Z));
2711
2712 PhysicsActor pa = m_rootPart.PhysActor; 2698 PhysicsActor pa = m_rootPart.PhysActor;
2713 2699
2714 if (pa != null && pa.IsPhysical) 2700 RootPart.StoreUndoState(true);
2701
2702 if (Scene != null)
2715 { 2703 {
2716 scale.X = Math.Max(Scene.m_minPhys, Math.Min(Scene.m_maxPhys, scale.X)); 2704 scale.X = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.X));
2717 scale.Y = Math.Max(Scene.m_minPhys, Math.Min(Scene.m_maxPhys, scale.Y)); 2705 scale.Y = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.Y));
2718 scale.Z = Math.Max(Scene.m_minPhys, Math.Min(Scene.m_maxPhys, scale.Z)); 2706 scale.Z = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.Z));
2707
2708 if (pa != null && pa.IsPhysical)
2709 {
2710 scale.X = Math.Max(Scene.m_minPhys, Math.Min(Scene.m_maxPhys, scale.X));
2711 scale.Y = Math.Max(Scene.m_minPhys, Math.Min(Scene.m_maxPhys, scale.Y));
2712 scale.Z = Math.Max(Scene.m_minPhys, Math.Min(Scene.m_maxPhys, scale.Z));
2713 }
2719 } 2714 }
2720 2715
2721 float x = (scale.X / RootPart.Scale.X); 2716 float x = (scale.X / RootPart.Scale.X);
2722 float y = (scale.Y / RootPart.Scale.Y); 2717 float y = (scale.Y / RootPart.Scale.Y);
2723 float z = (scale.Z / RootPart.Scale.Z); 2718 float z = (scale.Z / RootPart.Scale.Z);
2724 2719
2725 SceneObjectPart[] parts; 2720 SceneObjectPart[] parts = m_parts.GetArray();
2726 if (x > 1.0f || y > 1.0f || z > 1.0f) 2721
2722 if (Scene != null & (x > 1.0f || y > 1.0f || z > 1.0f))
2727 { 2723 {
2728 parts = m_parts.GetArray();
2729 for (int i = 0; i < parts.Length; i++) 2724 for (int i = 0; i < parts.Length; i++)
2730 { 2725 {
2731 SceneObjectPart obPart = parts[i]; 2726 SceneObjectPart obPart = parts[i];
@@ -2739,7 +2734,7 @@ namespace OpenSim.Region.Framework.Scenes
2739 2734
2740 if (pa != null && pa.IsPhysical) 2735 if (pa != null && pa.IsPhysical)
2741 { 2736 {
2742 if (oldSize.X * x > m_scene.m_maxPhys) 2737 if (oldSize.X * x > Scene.m_maxPhys)
2743 { 2738 {
2744 f = m_scene.m_maxPhys / oldSize.X; 2739 f = m_scene.m_maxPhys / oldSize.X;
2745 a = f / x; 2740 a = f / x;
@@ -2747,7 +2742,7 @@ namespace OpenSim.Region.Framework.Scenes
2747 y *= a; 2742 y *= a;
2748 z *= a; 2743 z *= a;
2749 } 2744 }
2750 else if (oldSize.X * x < m_scene.m_minPhys) 2745 else if (oldSize.X * x < Scene.m_minPhys)
2751 { 2746 {
2752 f = m_scene.m_minPhys / oldSize.X; 2747 f = m_scene.m_minPhys / oldSize.X;
2753 a = f / x; 2748 a = f / x;
@@ -2756,7 +2751,7 @@ namespace OpenSim.Region.Framework.Scenes
2756 z *= a; 2751 z *= a;
2757 } 2752 }
2758 2753
2759 if (oldSize.Y * y > m_scene.m_maxPhys) 2754 if (oldSize.Y * y > Scene.m_maxPhys)
2760 { 2755 {
2761 f = m_scene.m_maxPhys / oldSize.Y; 2756 f = m_scene.m_maxPhys / oldSize.Y;
2762 a = f / y; 2757 a = f / y;
@@ -2764,7 +2759,7 @@ namespace OpenSim.Region.Framework.Scenes
2764 y *= a; 2759 y *= a;
2765 z *= a; 2760 z *= a;
2766 } 2761 }
2767 else if (oldSize.Y * y < m_scene.m_minPhys) 2762 else if (oldSize.Y * y < Scene.m_minPhys)
2768 { 2763 {
2769 f = m_scene.m_minPhys / oldSize.Y; 2764 f = m_scene.m_minPhys / oldSize.Y;
2770 a = f / y; 2765 a = f / y;
@@ -2773,7 +2768,7 @@ namespace OpenSim.Region.Framework.Scenes
2773 z *= a; 2768 z *= a;
2774 } 2769 }
2775 2770
2776 if (oldSize.Z * z > m_scene.m_maxPhys) 2771 if (oldSize.Z * z > Scene.m_maxPhys)
2777 { 2772 {
2778 f = m_scene.m_maxPhys / oldSize.Z; 2773 f = m_scene.m_maxPhys / oldSize.Z;
2779 a = f / z; 2774 a = f / z;
@@ -2781,7 +2776,7 @@ namespace OpenSim.Region.Framework.Scenes
2781 y *= a; 2776 y *= a;
2782 z *= a; 2777 z *= a;
2783 } 2778 }
2784 else if (oldSize.Z * z < m_scene.m_minPhys) 2779 else if (oldSize.Z * z < Scene.m_minPhys)
2785 { 2780 {
2786 f = m_scene.m_minPhys / oldSize.Z; 2781 f = m_scene.m_minPhys / oldSize.Z;
2787 a = f / z; 2782 a = f / z;
@@ -2792,7 +2787,7 @@ namespace OpenSim.Region.Framework.Scenes
2792 } 2787 }
2793 else 2788 else
2794 { 2789 {
2795 if (oldSize.X * x > m_scene.m_maxNonphys) 2790 if (oldSize.X * x > Scene.m_maxNonphys)
2796 { 2791 {
2797 f = m_scene.m_maxNonphys / oldSize.X; 2792 f = m_scene.m_maxNonphys / oldSize.X;
2798 a = f / x; 2793 a = f / x;
@@ -2800,7 +2795,7 @@ namespace OpenSim.Region.Framework.Scenes
2800 y *= a; 2795 y *= a;
2801 z *= a; 2796 z *= a;
2802 } 2797 }
2803 else if (oldSize.X * x < m_scene.m_minNonphys) 2798 else if (oldSize.X * x < Scene.m_minNonphys)
2804 { 2799 {
2805 f = m_scene.m_minNonphys / oldSize.X; 2800 f = m_scene.m_minNonphys / oldSize.X;
2806 a = f / x; 2801 a = f / x;
@@ -2809,7 +2804,7 @@ namespace OpenSim.Region.Framework.Scenes
2809 z *= a; 2804 z *= a;
2810 } 2805 }
2811 2806
2812 if (oldSize.Y * y > m_scene.m_maxNonphys) 2807 if (oldSize.Y * y > Scene.m_maxNonphys)
2813 { 2808 {
2814 f = m_scene.m_maxNonphys / oldSize.Y; 2809 f = m_scene.m_maxNonphys / oldSize.Y;
2815 a = f / y; 2810 a = f / y;
@@ -2817,7 +2812,7 @@ namespace OpenSim.Region.Framework.Scenes
2817 y *= a; 2812 y *= a;
2818 z *= a; 2813 z *= a;
2819 } 2814 }
2820 else if (oldSize.Y * y < m_scene.m_minNonphys) 2815 else if (oldSize.Y * y < Scene.m_minNonphys)
2821 { 2816 {
2822 f = m_scene.m_minNonphys / oldSize.Y; 2817 f = m_scene.m_minNonphys / oldSize.Y;
2823 a = f / y; 2818 a = f / y;
@@ -2826,7 +2821,7 @@ namespace OpenSim.Region.Framework.Scenes
2826 z *= a; 2821 z *= a;
2827 } 2822 }
2828 2823
2829 if (oldSize.Z * z > m_scene.m_maxNonphys) 2824 if (oldSize.Z * z > Scene.m_maxNonphys)
2830 { 2825 {
2831 f = m_scene.m_maxNonphys / oldSize.Z; 2826 f = m_scene.m_maxNonphys / oldSize.Z;
2832 a = f / z; 2827 a = f / z;
@@ -2834,7 +2829,7 @@ namespace OpenSim.Region.Framework.Scenes
2834 y *= a; 2829 y *= a;
2835 z *= a; 2830 z *= a;
2836 } 2831 }
2837 else if (oldSize.Z * z < m_scene.m_minNonphys) 2832 else if (oldSize.Z * z < Scene.m_minNonphys)
2838 { 2833 {
2839 f = m_scene.m_minNonphys / oldSize.Z; 2834 f = m_scene.m_minNonphys / oldSize.Z;
2840 a = f / z; 2835 a = f / z;
@@ -2858,7 +2853,6 @@ namespace OpenSim.Region.Framework.Scenes
2858 RootPart.Resize(prevScale); 2853 RootPart.Resize(prevScale);
2859// RootPart.IgnoreUndoUpdate = false; 2854// RootPart.IgnoreUndoUpdate = false;
2860 2855
2861 parts = m_parts.GetArray();
2862 for (int i = 0; i < parts.Length; i++) 2856 for (int i = 0; i < parts.Length; i++)
2863 { 2857 {
2864 SceneObjectPart obPart = parts[i]; 2858 SceneObjectPart obPart = parts[i];
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 411dcc7..3f10b34 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -266,8 +266,8 @@ namespace OpenSim.Region.Framework.Scenes
266 private string m_sitAnimation = "SIT"; 266 private string m_sitAnimation = "SIT";
267 private string m_text = String.Empty; 267 private string m_text = String.Empty;
268 private string m_touchName = String.Empty; 268 private string m_touchName = String.Empty;
269 private readonly Stack<UndoState> m_undo = new Stack<UndoState>(5); 269 private readonly List<UndoState> m_undo = new List<UndoState>(5);
270 private readonly Stack<UndoState> m_redo = new Stack<UndoState>(5); 270 private readonly List<UndoState> m_redo = new List<UndoState>(5);
271 271
272 private bool m_passTouches = false; 272 private bool m_passTouches = false;
273 private bool m_passCollisions = false; 273 private bool m_passCollisions = false;
@@ -2368,16 +2368,20 @@ namespace OpenSim.Region.Framework.Scenes
2368 /// <param name="scale"></param> 2368 /// <param name="scale"></param>
2369 public void Resize(Vector3 scale) 2369 public void Resize(Vector3 scale)
2370 { 2370 {
2371 scale.X = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.X));
2372 scale.Y = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.Y));
2373 scale.Z = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.Z));
2374
2375 PhysicsActor pa = PhysActor; 2371 PhysicsActor pa = PhysActor;
2376 if (pa != null && pa.IsPhysical) 2372
2373 if (ParentGroup.Scene != null)
2377 { 2374 {
2378 scale.X = Math.Max(ParentGroup.Scene.m_minPhys, Math.Min(ParentGroup.Scene.m_maxPhys, scale.X)); 2375 scale.X = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.X));
2379 scale.Y = Math.Max(ParentGroup.Scene.m_minPhys, Math.Min(ParentGroup.Scene.m_maxPhys, scale.Y)); 2376 scale.Y = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.Y));
2380 scale.Z = Math.Max(ParentGroup.Scene.m_minPhys, Math.Min(ParentGroup.Scene.m_maxPhys, scale.Z)); 2377 scale.Z = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.Z));
2378
2379 if (pa != null && pa.IsPhysical)
2380 {
2381 scale.X = Math.Max(ParentGroup.Scene.m_minPhys, Math.Min(ParentGroup.Scene.m_maxPhys, scale.X));
2382 scale.Y = Math.Max(ParentGroup.Scene.m_minPhys, Math.Min(ParentGroup.Scene.m_maxPhys, scale.Y));
2383 scale.Z = Math.Max(ParentGroup.Scene.m_minPhys, Math.Min(ParentGroup.Scene.m_maxPhys, scale.Z));
2384 }
2381 } 2385 }
2382 2386
2383// m_log.DebugFormat("[SCENE OBJECT PART]: Resizing {0} {1} to {2}", Name, LocalId, scale); 2387// m_log.DebugFormat("[SCENE OBJECT PART]: Resizing {0} {1} to {2}", Name, LocalId, scale);
@@ -3166,61 +3170,62 @@ namespace OpenSim.Region.Framework.Scenes
3166 3170
3167 public void StoreUndoState(bool forGroup) 3171 public void StoreUndoState(bool forGroup)
3168 { 3172 {
3169 if (!Undoing) 3173 if (ParentGroup == null || ParentGroup.Scene == null)
3174 return;
3175
3176 if (Undoing)
3170 { 3177 {
3171 if (!IgnoreUndoUpdate) 3178// m_log.DebugFormat(
3179// "[SCENE OBJECT PART]: Ignoring undo store for {0} {1} since already undoing", Name, LocalId);
3180 return;
3181 }
3182
3183 if (IgnoreUndoUpdate)
3184 {
3185// m_log.DebugFormat("[SCENE OBJECT PART]: Ignoring undo store for {0} {1}", Name, LocalId);
3186 return;
3187 }
3188
3189 lock (m_undo)
3190 {
3191 if (m_undo.Count > 0)
3172 { 3192 {
3173 if (ParentGroup != null) 3193 UndoState last = m_undo[m_undo.Count - 1];
3194 if (last != null)
3174 { 3195 {
3175 lock (m_undo) 3196 // TODO: May need to fix for group comparison
3197 if (last.Compare(this))
3176 { 3198 {
3177 if (m_undo.Count > 0) 3199// m_log.DebugFormat(
3178 { 3200// "[SCENE OBJECT PART]: Not storing undo for {0} {1} since current state is same as last undo state, initial stack size {2}",
3179 UndoState last = m_undo.Peek(); 3201// Name, LocalId, m_undo.Count);
3180 if (last != null) 3202
3181 { 3203 return;
3182 // TODO: May need to fix for group comparison
3183 if (last.Compare(this))
3184 {
3185 // m_log.DebugFormat(
3186 // "[SCENE OBJECT PART]: Not storing undo for {0} {1} since current state is same as last undo state, initial stack size {2}",
3187 // Name, LocalId, m_undo.Count);
3188
3189 return;
3190 }
3191 }
3192 }
3193
3194 // m_log.DebugFormat(
3195 // "[SCENE OBJECT PART]: Storing undo state for {0} {1}, forGroup {2}, initial stack size {3}",
3196 // Name, LocalId, forGroup, m_undo.Count);
3197
3198 if (ParentGroup.GetSceneMaxUndo() > 0)
3199 {
3200 UndoState nUndo = new UndoState(this, forGroup);
3201
3202 m_undo.Push(nUndo);
3203
3204 if (m_redo.Count > 0)
3205 m_redo.Clear();
3206
3207 // m_log.DebugFormat(
3208 // "[SCENE OBJECT PART]: Stored undo state for {0} {1}, forGroup {2}, stack size now {3}",
3209 // Name, LocalId, forGroup, m_undo.Count);
3210 }
3211 } 3204 }
3212 } 3205 }
3213 } 3206 }
3214// else 3207
3215// { 3208// m_log.DebugFormat(
3216// m_log.DebugFormat("[SCENE OBJECT PART]: Ignoring undo store for {0} {1}", Name, LocalId); 3209// "[SCENE OBJECT PART]: Storing undo state for {0} {1}, forGroup {2}, initial stack size {3}",
3217// } 3210// Name, LocalId, forGroup, m_undo.Count);
3211
3212 if (ParentGroup.Scene.MaxUndoCount > 0)
3213 {
3214 UndoState nUndo = new UndoState(this, forGroup);
3215
3216 m_undo.Add(nUndo);
3217
3218 if (m_undo.Count > ParentGroup.Scene.MaxUndoCount)
3219 m_undo.RemoveAt(0);
3220
3221 if (m_redo.Count > 0)
3222 m_redo.Clear();
3223
3224// m_log.DebugFormat(
3225// "[SCENE OBJECT PART]: Stored undo state for {0} {1}, forGroup {2}, stack size now {3}",
3226// Name, LocalId, forGroup, m_undo.Count);
3227 }
3218 } 3228 }
3219// else
3220// {
3221// m_log.DebugFormat(
3222// "[SCENE OBJECT PART]: Ignoring undo store for {0} {1} since already undoing", Name, LocalId);
3223// }
3224 } 3229 }
3225 3230
3226 /// <summary> 3231 /// <summary>
@@ -3245,21 +3250,24 @@ namespace OpenSim.Region.Framework.Scenes
3245 3250
3246 if (m_undo.Count > 0) 3251 if (m_undo.Count > 0)
3247 { 3252 {
3248 UndoState goback = m_undo.Pop(); 3253 UndoState goback = m_undo[m_undo.Count - 1];
3254 m_undo.RemoveAt(m_undo.Count - 1);
3249 3255
3250 if (goback != null) 3256 UndoState nUndo = null;
3257
3258 if (ParentGroup.Scene.MaxUndoCount > 0)
3251 { 3259 {
3252 UndoState nUndo = null; 3260 nUndo = new UndoState(this, goback.ForGroup);
3253 3261 }
3254 if (ParentGroup.GetSceneMaxUndo() > 0) 3262
3255 { 3263 goback.PlaybackState(this);
3256 nUndo = new UndoState(this, goback.ForGroup);
3257 }
3258 3264
3259 goback.PlaybackState(this); 3265 if (nUndo != null)
3266 {
3267 m_redo.Add(nUndo);
3260 3268
3261 if (nUndo != null) 3269 if (m_redo.Count > ParentGroup.Scene.MaxUndoCount)
3262 m_redo.Push(nUndo); 3270 m_redo.RemoveAt(0);
3263 } 3271 }
3264 } 3272 }
3265 3273
@@ -3279,20 +3287,21 @@ namespace OpenSim.Region.Framework.Scenes
3279 3287
3280 if (m_redo.Count > 0) 3288 if (m_redo.Count > 0)
3281 { 3289 {
3282 UndoState gofwd = m_redo.Pop(); 3290 UndoState gofwd = m_redo[m_redo.Count - 1];
3283 3291 m_redo.RemoveAt(m_redo.Count - 1);
3284 if (gofwd != null) 3292
3293 if (ParentGroup.Scene.MaxUndoCount > 0)
3285 { 3294 {
3286 if (ParentGroup.GetSceneMaxUndo() > 0) 3295 UndoState nUndo = new UndoState(this, gofwd.ForGroup);
3287 { 3296
3288 UndoState nUndo = new UndoState(this, gofwd.ForGroup); 3297 m_undo.Add(nUndo);
3289 3298
3290 m_undo.Push(nUndo); 3299 if (m_undo.Count > ParentGroup.Scene.MaxUndoCount)
3291 } 3300 m_undo.RemoveAt(0);
3292
3293 gofwd.PlayfwdState(this);
3294 } 3301 }
3295 3302
3303 gofwd.PlayfwdState(this);
3304
3296// m_log.DebugFormat( 3305// m_log.DebugFormat(
3297// "[SCENE OBJECT PART]: Handled redo request for {0} {1}, stack size now {2}", 3306// "[SCENE OBJECT PART]: Handled redo request for {0} {1}, stack size now {2}",
3298// Name, LocalId, m_redo.Count); 3307// Name, LocalId, m_redo.Count);
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectResizeTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectResizeTests.cs
index e931859..89647d6 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectResizeTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectResizeTests.cs
@@ -62,8 +62,6 @@ namespace OpenSim.Region.Framework.Scenes.Tests
62 Assert.That(g1Post.RootPart.Scale.X, Is.EqualTo(2)); 62 Assert.That(g1Post.RootPart.Scale.X, Is.EqualTo(2));
63 Assert.That(g1Post.RootPart.Scale.Y, Is.EqualTo(3)); 63 Assert.That(g1Post.RootPart.Scale.Y, Is.EqualTo(3));
64 Assert.That(g1Post.RootPart.Scale.Z, Is.EqualTo(4)); 64 Assert.That(g1Post.RootPart.Scale.Z, Is.EqualTo(4));
65
66 Assert.That(g1Post.RootPart.UndoCount, Is.EqualTo(1));
67 } 65 }
68 66
69 /// <summary> 67 /// <summary>
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUndoRedoTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUndoRedoTests.cs
new file mode 100644
index 0000000..96973de
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUndoRedoTests.cs
@@ -0,0 +1,184 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Reflection;
30using NUnit.Framework;
31using OpenMetaverse;
32using OpenSim.Framework;
33using OpenSim.Framework.Communications;
34using OpenSim.Region.Framework.Scenes;
35using OpenSim.Tests.Common;
36using OpenSim.Tests.Common.Mock;
37
38namespace OpenSim.Region.Framework.Scenes.Tests
39{
40 /// <summary>
41 /// Tests for undo/redo
42 /// </summary>
43 public class SceneObjectUndoRedoTests : OpenSimTestCase
44 {
45 [Test]
46 public void TestUndoRedoResizeSceneObject()
47 {
48 TestHelpers.InMethod();
49// TestHelpers.EnableLogging();
50
51 Vector3 firstSize = new Vector3(2, 3, 4);
52 Vector3 secondSize = new Vector3(5, 6, 7);
53
54 Scene scene = new SceneHelpers().SetupScene();
55 scene.MaxUndoCount = 20;
56 SceneObjectGroup g1 = SceneHelpers.AddSceneObject(scene);
57
58 // TODO: It happens to be the case that we are not storing undo states for SOPs which are not yet in a SOG,
59 // which is the way that AddSceneObject() sets up the object (i.e. it creates the SOP first). However,
60 // this is somewhat by chance. Really, we shouldn't be storing undo states at all if the object is not
61 // in a scene.
62 Assert.That(g1.RootPart.UndoCount, Is.EqualTo(0));
63
64 g1.GroupResize(firstSize);
65 Assert.That(g1.RootPart.UndoCount, Is.EqualTo(1));
66
67 g1.GroupResize(secondSize);
68 Assert.That(g1.RootPart.UndoCount, Is.EqualTo(2));
69
70 g1.RootPart.Undo();
71 Assert.That(g1.RootPart.UndoCount, Is.EqualTo(1));
72 Assert.That(g1.GroupScale, Is.EqualTo(firstSize));
73
74 g1.RootPart.Redo();
75 Assert.That(g1.RootPart.UndoCount, Is.EqualTo(2));
76 Assert.That(g1.GroupScale, Is.EqualTo(secondSize));
77 }
78
79 [Test]
80 public void TestUndoLimit()
81 {
82 TestHelpers.InMethod();
83
84 Vector3 firstSize = new Vector3(2, 3, 4);
85 Vector3 secondSize = new Vector3(5, 6, 7);
86 Vector3 thirdSize = new Vector3(8, 9, 10);
87 Vector3 fourthSize = new Vector3(11, 12, 13);
88
89 Scene scene = new SceneHelpers().SetupScene();
90 scene.MaxUndoCount = 2;
91 SceneObjectGroup g1 = SceneHelpers.AddSceneObject(scene);
92
93 g1.GroupResize(firstSize);
94 g1.GroupResize(secondSize);
95 g1.GroupResize(thirdSize);
96 g1.GroupResize(fourthSize);
97
98 g1.RootPart.Undo();
99 g1.RootPart.Undo();
100 g1.RootPart.Undo();
101
102 Assert.That(g1.RootPart.UndoCount, Is.EqualTo(0));
103 Assert.That(g1.GroupScale, Is.EqualTo(secondSize));
104 }
105
106 [Test]
107 public void TestNoUndoOnObjectsNotInScene()
108 {
109 TestHelpers.InMethod();
110
111 Vector3 firstSize = new Vector3(2, 3, 4);
112 Vector3 secondSize = new Vector3(5, 6, 7);
113 Vector3 thirdSize = new Vector3(8, 9, 10);
114 Vector3 fourthSize = new Vector3(11, 12, 13);
115
116 Scene scene = new SceneHelpers().SetupScene();
117 scene.MaxUndoCount = 20;
118 SceneObjectGroup g1 = SceneHelpers.CreateSceneObject(1, TestHelpers.ParseTail(0x1));
119
120 g1.GroupResize(firstSize);
121 g1.GroupResize(secondSize);
122
123 Assert.That(g1.RootPart.UndoCount, Is.EqualTo(0));
124
125 g1.RootPart.Undo();
126
127 Assert.That(g1.GroupScale, Is.EqualTo(secondSize));
128 }
129
130 [Test]
131 public void TestUndoBeyondAvailable()
132 {
133 TestHelpers.InMethod();
134
135 Vector3 newSize = new Vector3(2, 3, 4);
136
137 Scene scene = new SceneHelpers().SetupScene();
138 scene.MaxUndoCount = 20;
139 SceneObjectGroup g1 = SceneHelpers.AddSceneObject(scene);
140 Vector3 originalSize = g1.GroupScale;
141
142 g1.RootPart.Undo();
143
144 Assert.That(g1.RootPart.UndoCount, Is.EqualTo(0));
145 Assert.That(g1.GroupScale, Is.EqualTo(originalSize));
146
147 g1.GroupResize(newSize);
148 Assert.That(g1.RootPart.UndoCount, Is.EqualTo(1));
149 Assert.That(g1.GroupScale, Is.EqualTo(newSize));
150
151 g1.RootPart.Undo();
152 g1.RootPart.Undo();
153
154 Assert.That(g1.RootPart.UndoCount, Is.EqualTo(0));
155 Assert.That(g1.GroupScale, Is.EqualTo(originalSize));
156 }
157
158 [Test]
159 public void TestRedoBeyondAvailable()
160 {
161 TestHelpers.InMethod();
162
163 Vector3 newSize = new Vector3(2, 3, 4);
164
165 Scene scene = new SceneHelpers().SetupScene();
166 scene.MaxUndoCount = 20;
167 SceneObjectGroup g1 = SceneHelpers.AddSceneObject(scene);
168 Vector3 originalSize = g1.GroupScale;
169
170 g1.RootPart.Redo();
171
172 Assert.That(g1.RootPart.UndoCount, Is.EqualTo(0));
173 Assert.That(g1.GroupScale, Is.EqualTo(originalSize));
174
175 g1.GroupResize(newSize);
176 g1.RootPart.Undo();
177 g1.RootPart.Redo();
178 g1.RootPart.Redo();
179
180 Assert.That(g1.RootPart.UndoCount, Is.EqualTo(1));
181 Assert.That(g1.GroupScale, Is.EqualTo(newSize));
182 }
183 }
184} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUserGroupTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUserGroupTests.cs
index c7eaff9..2b79271 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUserGroupTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUserGroupTests.cs
@@ -44,7 +44,7 @@ using OpenSim.Tests.Common.Mock;
44namespace OpenSim.Region.Framework.Scenes.Tests 44namespace OpenSim.Region.Framework.Scenes.Tests
45{ 45{
46 [TestFixture] 46 [TestFixture]
47 public class SceneObjectUserGroupTests 47 public class SceneObjectUserGroupTests : OpenSimTestCase
48 { 48 {
49 /// <summary> 49 /// <summary>
50 /// Test share with group object functionality 50 /// Test share with group object functionality
@@ -54,7 +54,6 @@ namespace OpenSim.Region.Framework.Scenes.Tests
54 public void TestShareWithGroup() 54 public void TestShareWithGroup()
55 { 55 {
56 TestHelpers.InMethod(); 56 TestHelpers.InMethod();
57// log4net.Config.XmlConfigurator.Configure();
58 57
59 UUID userId = UUID.Parse("10000000-0000-0000-0000-000000000001"); 58 UUID userId = UUID.Parse("10000000-0000-0000-0000-000000000001");
60 59
diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example
index b21a214..c7df7bb 100644
--- a/bin/OpenSim.ini.example
+++ b/bin/OpenSim.ini.example
@@ -97,6 +97,10 @@
97 ;; from the selected region_info_source. 97 ;; from the selected region_info_source.
98 ; allow_regionless = false 98 ; allow_regionless = false
99 99
100 ;# {MaxPrimUndos} {} {Maximum number of undos avialable for position, rotation and scale changes of each prim} {} 20
101 ;; Increasing the number of undos available number will increase memory usage.
102 MaxPrimUndos = 20
103
100 ;# {NonPhysicalPrimMin} {} {Minimum size of nonphysical prims?} {} 0.001 104 ;# {NonPhysicalPrimMin} {} {Minimum size of nonphysical prims?} {} 0.001
101 ;; Minimum size for non-physical prims. Affects resizing of existing 105 ;; Minimum size for non-physical prims. Affects resizing of existing
102 ;; prims. This can be overriden in the region config file (as 106 ;; prims. This can be overriden in the region config file (as
diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini
index 315ffbe..9c32abd 100644
--- a/bin/OpenSimDefaults.ini
+++ b/bin/OpenSimDefaults.ini
@@ -85,6 +85,10 @@
85 ;; from the selected region_info_source. 85 ;; from the selected region_info_source.
86 allow_regionless = false 86 allow_regionless = false
87 87
88 ; Maximum number of position, rotation and scale changes for each prim that the simulator will store for later undos
89 ; Increasing this number will increase memory usage.
90 MaxPrimUndos = 20
91
88 ; Maximum size of non physical prims. Affects resizing of existing prims. This can be overriden in the region config file (as NonPhysicalPrimMax!). 92 ; Maximum size of non physical prims. Affects resizing of existing prims. This can be overriden in the region config file (as NonPhysicalPrimMax!).
89 NonPhysicalPrimMax = 256 93 NonPhysicalPrimMax = 256
90 94