aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
authorDiva Canto2015-05-07 12:38:40 -0700
committerDiva Canto2015-05-07 12:38:40 -0700
commitca4569eeb4c51e9afeb55d83679576a5f97c9d41 (patch)
tree0debff1684288fded6b6407d9bb41988a59851d5 /OpenSim
parentpCampbot: added behavior that mimic initial inventory download. It's not exac... (diff)
parentMinor whitespace removal (diff)
downloadopensim-SC_OLD-ca4569eeb4c51e9afeb55d83679576a5f97c9d41.zip
opensim-SC_OLD-ca4569eeb4c51e9afeb55d83679576a5f97c9d41.tar.gz
opensim-SC_OLD-ca4569eeb4c51e9afeb55d83679576a5f97c9d41.tar.bz2
opensim-SC_OLD-ca4569eeb4c51e9afeb55d83679576a5f97c9d41.tar.xz
Merge branch 'master' of ssh://opensimulator.org/var/git/opensim
Diffstat (limited to 'OpenSim')
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/Features/RectangleFeature.cs149
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/ITerrainModifier.cs (renamed from OpenSim/Region/CoreModules/World/Terrain/TerrainFeature.cs)90
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/Modifiers/FillModifier.cs94
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/Modifiers/LowerModifier.cs93
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/Modifiers/MaxModifier.cs93
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/Modifiers/MinModifier.cs93
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/Modifiers/NoiseModifier.cs109
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/Modifiers/RaiseModifier.cs93
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/Modifiers/SmoothModifier.cs132
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/TerrainModifier.cs378
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/TerrainModifierData.cs17
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs341
12 files changed, 1313 insertions, 369 deletions
diff --git a/OpenSim/Region/CoreModules/World/Terrain/Features/RectangleFeature.cs b/OpenSim/Region/CoreModules/World/Terrain/Features/RectangleFeature.cs
deleted file mode 100644
index 33c3fbe..0000000
--- a/OpenSim/Region/CoreModules/World/Terrain/Features/RectangleFeature.cs
+++ /dev/null
@@ -1,149 +0,0 @@
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 OpenSim.Region.CoreModules.World.Terrain;
30using OpenSim.Region.Framework.Interfaces;
31
32namespace OpenSim.Region.CoreModules.World.Terrain.Features
33{
34 public class RectangleFeature : TerrainFeature
35 {
36 public RectangleFeature(ITerrainModule module) : base(module)
37 {
38 }
39
40 public override string CreateFeature(ITerrainChannel map, string[] args)
41 {
42 string val;
43 string result;
44 if (args.Length < 7)
45 {
46 result = "Usage: " + GetUsage();
47 }
48 else
49 {
50 result = String.Empty;
51
52 float targetElevation;
53 val = base.parseFloat(args[3], out targetElevation);
54 if (val != String.Empty)
55 {
56 result = val;
57 }
58
59 int xOrigin;
60 val = base.parseInt(args[4], out xOrigin);
61 if (val != String.Empty)
62 {
63 result = val;
64 }
65 else if (xOrigin < 0 || xOrigin >= map.Width)
66 {
67 result = "x-origin must be within the region";
68 }
69
70 int yOrigin;
71 val = base.parseInt(args[5], out yOrigin);
72 if (val != String.Empty)
73 {
74 result = val;
75 }
76 else if (yOrigin < 0 || yOrigin >= map.Height)
77 {
78 result = "y-origin must be within the region";
79 }
80
81 int xDelta;
82 val = base.parseInt(args[6], out xDelta);
83 if (val != String.Empty)
84 {
85 result = val;
86 }
87 else if (xDelta <= 0)
88 {
89 result = "x-size must be greater than zero";
90 }
91
92 int yDelta;
93 if (args.Length > 7)
94 {
95 val = base.parseInt(args[7], out yDelta);
96 if (val != String.Empty)
97 {
98 result = val;
99 }
100 else if (yDelta <= 0)
101 {
102 result = "y-size must be greater than zero";
103 }
104 }
105 else
106 {
107 // no y-size.. make it square
108 yDelta = xDelta;
109 }
110
111 // slightly more complex validation, if required.
112 if (result == String.Empty)
113 {
114 if (xOrigin + xDelta > map.Width)
115 {
116 result = "(x-origin + x-size) must be within the region size";
117 }
118 else if (yOrigin + yDelta > map.Height)
119 {
120 result = "(y-origin + y-size) must be within the region size";
121 }
122 }
123
124 // if it's all good, then do the work
125 if (result == String.Empty)
126 {
127 int yPos = yOrigin + yDelta;
128 while(--yPos >= yOrigin)
129 {
130 int xPos = xOrigin + xDelta;
131 while(--xPos >= xOrigin)
132 {
133 map[xPos, yPos] = (double)targetElevation;
134 }
135 }
136 }
137 }
138
139 return result;
140 }
141
142 public override string GetUsage()
143 {
144 return "rectangle <height> <x-origin> <y-origin> <x-size> [<y-size>]";
145 }
146 }
147
148}
149
diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainFeature.cs b/OpenSim/Region/CoreModules/World/Terrain/ITerrainModifier.cs
index 701a729..0e0a0e4 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/TerrainFeature.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/ITerrainModifier.cs
@@ -24,65 +24,53 @@
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 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. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27using System;
28using System.Reflection;
29 27
28using System;
30using OpenSim.Region.Framework.Interfaces; 29using OpenSim.Region.Framework.Interfaces;
31 30
32namespace OpenSim.Region.CoreModules.World.Terrain 31namespace OpenSim.Region.CoreModules.World.Terrain
33{ 32{
34 public abstract class TerrainFeature : ITerrainFeature 33 public interface ITerrainModifier
35 { 34 {
36 protected ITerrainModule m_module; 35 /// <summary>
37 36 /// Creates the feature.
38 protected TerrainFeature(ITerrainModule module) 37 /// </summary>
39 { 38 /// <returns>
40 m_module = module; 39 /// Empty string if successful, otherwise error message.
41 } 40 /// </returns>
42 41 /// <param name='map'>
43 public abstract string CreateFeature(ITerrainChannel map, string[] args); 42 /// ITerrainChannel holding terrain data.
44 43 /// </param>
45 public abstract string GetUsage(); 44 /// <param name='args'>
46 45 /// command-line arguments from console.
47 protected string parseFloat(String s, out float f) 46 /// </param>
48 { 47 string ModifyTerrain(ITerrainChannel map, string[] args);
49 string result;
50 double d;
51 if (Double.TryParse(s, out d))
52 {
53 try
54 {
55 f = (float)d;
56 result = String.Empty;
57 }
58 catch(InvalidCastException)
59 {
60 result = String.Format("{0} is invalid", s);
61 f = -1.0f;
62 }
63 }
64 else
65 {
66 f = -1.0f;
67 result = String.Format("{0} is invalid", s);
68 }
69 return result;
70 }
71 48
72 protected string parseInt(String s, out int i) 49 /// <summary>
73 { 50 /// Gets a string describing the usage.
74 string result; 51 /// </summary>
75 if (Int32.TryParse(s, out i)) 52 /// <returns>
76 { 53 /// A string describing parameters for creating the feature.
77 result = String.Empty; 54 /// Format is "feature-name <arg1> <arg2> ..."
78 } 55 /// </returns>
79 else 56 string GetUsage();
80 {
81 result = String.Format("{0} is invalid", s);
82 }
83 return result;
84 }
85 57
58 /// <summary>
59 /// Apply the appropriate operation on the specified map, at (x, y).
60 /// </summary>
61 /// <param name='map'>
62 /// Map.
63 /// </param>
64 /// <param name='data'>
65 /// Data.
66 /// </param>
67 /// <param name='x'>
68 /// X.
69 /// </param>
70 /// <param name='y'>
71 /// Y.
72 /// </param>
73 double operate(double[,] map, TerrainModifierData data, int x, int y);
86 } 74 }
87 75
88} 76}
diff --git a/OpenSim/Region/CoreModules/World/Terrain/Modifiers/FillModifier.cs b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/FillModifier.cs
new file mode 100644
index 0000000..0df7132
--- /dev/null
+++ b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/FillModifier.cs
@@ -0,0 +1,94 @@
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 */
27using System;
28
29using OpenSim.Region.CoreModules.World.Terrain;
30using OpenSim.Region.Framework.Interfaces;
31
32namespace OpenSim.Region.CoreModules.World.Terrain.Modifiers
33{
34 public class FillModifier : TerrainModifier
35 {
36
37 public FillModifier(ITerrainModule module) : base(module)
38 {
39 }
40
41 public override string ModifyTerrain(ITerrainChannel map, string[] args)
42 {
43 string val;
44 string result;
45 if (args.Length < 3)
46 {
47 result = "Usage: " + GetUsage();
48 }
49 else
50 {
51 TerrainModifierData data;
52 result = this.parseParameters(args, out data);
53
54 // Context-specific validation
55 if (result == String.Empty)
56 {
57 if (data.shape == String.Empty)
58 {
59 data.shape = "rectangle";
60 data.x0 = 0;
61 data.y0 = 0;
62 data.dx = map.Width;
63 data.dy = map.Height;
64 }
65 }
66
67 // if it's all good, then do the work
68 if (result == String.Empty)
69 {
70 this.applyModification(map, data);
71 }
72 }
73
74 return result;
75 }
76
77 public override string GetUsage()
78 {
79 string val = "fill <height> [ -rec=x1,y1,dx[,dy] | -ell=x0,y0,rx[,ry] ] [-taper=<height2>]"
80 + "\nSets all points within the specified range to the specified value.";
81 return val;
82 }
83
84 public override double operate(double[,] map, TerrainModifierData data, int x, int y)
85 {
86 double factor = this.computeBevel(data, x, y);
87 double result = data.elevation - (data.elevation - data.bevelevation) * factor;
88 return result;
89 }
90
91 }
92
93}
94
diff --git a/OpenSim/Region/CoreModules/World/Terrain/Modifiers/LowerModifier.cs b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/LowerModifier.cs
new file mode 100644
index 0000000..3e4a457
--- /dev/null
+++ b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/LowerModifier.cs
@@ -0,0 +1,93 @@
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 */
27using System;
28using OpenSim.Region.CoreModules.World.Terrain;
29using OpenSim.Region.Framework.Interfaces;
30
31namespace OpenSim.Region.CoreModules.World.Terrain.Modifiers
32{
33 public class LowerModifier : TerrainModifier
34 {
35 public LowerModifier(ITerrainModule module) : base(module)
36 {
37 }
38
39 public override string ModifyTerrain(ITerrainChannel map, string[] args)
40 {
41 string val;
42 string result;
43 if (args.Length < 3)
44 {
45 result = "Usage: " + GetUsage();
46 }
47 else
48 {
49 TerrainModifierData data;
50 result = this.parseParameters(args, out data);
51
52 // Context-specific validation
53 if (result == String.Empty)
54 {
55 if (data.shape == String.Empty)
56 {
57 data.shape = "rectangle";
58 data.x0 = 0;
59 data.y0 = 0;
60 data.dx = map.Width;
61 data.dy = map.Height;
62 }
63 }
64
65 // if it's all good, then do the work
66 if (result == String.Empty)
67 {
68 this.applyModification(map, data);
69 }
70 }
71
72 return result;
73 }
74
75 public override string GetUsage()
76 {
77 string val = "lower <delta> [ -rec=x1,y1,dx[,dy] | -ell=x0,y0,rx[,ry] ] [-taper=<delta2>]"
78 + "\nLowers all points within the specified range by the specified amount.";
79 return val;
80
81 }
82
83 public override double operate(double[,] map, TerrainModifierData data, int x, int y)
84 {
85 double factor = this.computeBevel(data, x, y);
86 double result = map[x, y] - (data.elevation - (data.elevation - data.bevelevation) * factor);
87 return result;
88 }
89
90 }
91
92}
93
diff --git a/OpenSim/Region/CoreModules/World/Terrain/Modifiers/MaxModifier.cs b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/MaxModifier.cs
new file mode 100644
index 0000000..02f1852
--- /dev/null
+++ b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/MaxModifier.cs
@@ -0,0 +1,93 @@
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 */
27using System;
28using OpenSim.Region.CoreModules.World.Terrain;
29using OpenSim.Region.Framework.Interfaces;
30
31namespace OpenSim.Region.CoreModules.World.Terrain.Modifiers
32{
33 public class MaxModifier : TerrainModifier
34 {
35 public MaxModifier(ITerrainModule module) : base(module)
36 {
37 }
38
39 public override string ModifyTerrain(ITerrainChannel map, string[] args)
40 {
41 string val;
42 string result;
43 if (args.Length < 3)
44 {
45 result = "Usage: " + GetUsage();
46 }
47 else
48 {
49 TerrainModifierData data;
50 result = this.parseParameters(args, out data);
51
52 // Context-specific validation
53 if (result == String.Empty)
54 {
55 if (data.shape == String.Empty)
56 {
57 data.shape = "rectangle";
58 data.x0 = 0;
59 data.y0 = 0;
60 data.dx = map.Width;
61 data.dy = map.Height;
62 }
63 }
64
65 // if it's all good, then do the work
66 if (result == String.Empty)
67 {
68 this.applyModification(map, data);
69 }
70 }
71
72 return result;
73 }
74
75 public override string GetUsage()
76 {
77 string val = "max <height> [ -rec=x1,y1,dx[,dy] | -ell=x0,y0,rx[,ry] ] [-taper=<height2>]"
78 + "\nEnsures that all points within the specified range are no higher than the specified value.";
79 return val;
80
81 }
82
83 public override double operate(double[,] map, TerrainModifierData data, int x, int y)
84 {
85 double factor = this.computeBevel(data, x, y);
86 double result = Math.Min(data.elevation - (data.elevation - data.bevelevation) * factor, map[x, y]);
87 return result;
88 }
89
90 }
91
92}
93
diff --git a/OpenSim/Region/CoreModules/World/Terrain/Modifiers/MinModifier.cs b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/MinModifier.cs
new file mode 100644
index 0000000..2db49c8
--- /dev/null
+++ b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/MinModifier.cs
@@ -0,0 +1,93 @@
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 */
27using System;
28using OpenSim.Region.CoreModules.World.Terrain;
29using OpenSim.Region.Framework.Interfaces;
30
31namespace OpenSim.Region.CoreModules.World.Terrain.Modifiers
32{
33 public class MinModifier : TerrainModifier
34 {
35 public MinModifier(ITerrainModule module) : base(module)
36 {
37 }
38
39 public override string ModifyTerrain(ITerrainChannel map, string[] args)
40 {
41 string val;
42 string result;
43 if (args.Length < 3)
44 {
45 result = "Usage: " + GetUsage();
46 }
47 else
48 {
49 TerrainModifierData data;
50 result = this.parseParameters(args, out data);
51
52 // Context-specific validation
53 if (result == String.Empty)
54 {
55 if (data.shape == String.Empty)
56 {
57 data.shape = "rectangle";
58 data.x0 = 0;
59 data.y0 = 0;
60 data.dx = map.Width;
61 data.dy = map.Height;
62 }
63 }
64
65 // if it's all good, then do the work
66 if (result == String.Empty)
67 {
68 this.applyModification(map, data);
69 }
70 }
71
72 return result;
73 }
74
75 public override string GetUsage()
76 {
77 string val = "min <height> [ -rec=x1,y1,dx[,dy] | -ell=x0,y0,rx[,ry] ] [-taper=<height2>]"
78 + "\nEnsures that all points within the specified range are no lower than the specified value.";
79 return val;
80
81 }
82
83 public override double operate(double[,] map, TerrainModifierData data, int x, int y)
84 {
85 double factor = this.computeBevel(data, x, y);
86 double result = Math.Max(data.elevation - (data.elevation - data.bevelevation) * factor, map[x, y]);
87 return result;
88 }
89
90 }
91
92}
93
diff --git a/OpenSim/Region/CoreModules/World/Terrain/Modifiers/NoiseModifier.cs b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/NoiseModifier.cs
new file mode 100644
index 0000000..53a64df
--- /dev/null
+++ b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/NoiseModifier.cs
@@ -0,0 +1,109 @@
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 */
27using System;
28using OpenSim.Region.CoreModules.World.Terrain;
29using OpenSim.Region.Framework.Interfaces;
30using OpenSim.Region.Framework.Scenes;
31
32namespace OpenSim.Region.CoreModules.World.Terrain.Modifiers
33{
34 public class NoiseModifier : TerrainModifier
35 {
36 public NoiseModifier(ITerrainModule module) : base(module)
37 {
38 }
39
40 public override string ModifyTerrain(ITerrainChannel map, string[] args)
41 {
42 string val;
43 string result;
44 if (args.Length < 3)
45 {
46 result = "Usage: " + GetUsage();
47 }
48 else
49 {
50 TerrainModifierData data;
51 result = this.parseParameters(args, out data);
52
53 // Context-specific validation
54 if (result == String.Empty)
55 {
56 if (data.bevel == "taper")
57 {
58 if (data.bevelevation < 0.0 || data.bevelevation > 1.0)
59 {
60 result = String.Format("Taper must be 0.0 to 1.0: {0}", data.bevelevation);
61 }
62 }
63 else
64 {
65 data.bevelevation = 1.0f;
66 }
67
68 if (data.elevation < 0.0 || data.elevation > 1.0)
69 {
70 result = String.Format("Noise strength must be 0.0 to 1.0: {0}", data.elevation);
71 }
72
73 if (data.shape == String.Empty)
74 {
75 data.shape = "rectangle";
76 data.x0 = 0;
77 data.y0 = 0;
78 data.dx = map.Width;
79 data.dy = map.Height;
80 }
81 }
82
83 // if it's all good, then do the work
84 if (result == String.Empty)
85 {
86 this.applyModification(map, data);
87 }
88 }
89
90 return result;
91 }
92
93 public override string GetUsage()
94 {
95 string val = "noise <delta> [ -rec=x1,y1,dx[,dy] | -ell=x0,y0,rx[,ry] ] [-taper=<delta2>]"
96 + "\nAdds noise to all points within the specified range.";
97 return val;
98 }
99
100 public override double operate(double[,] map, TerrainModifierData data, int x, int y)
101 {
102 double factor = this.computeBevel(data, x, y);
103 double noise = TerrainUtil.PerlinNoise2D((double)x / map.GetLength(0), (double)y / map.GetLength(1), 8, 1.0);
104 return map[x, y] + (data.elevation - (data.elevation - data.bevelevation) * factor) * (noise - .5);
105 }
106
107 }
108
109}
diff --git a/OpenSim/Region/CoreModules/World/Terrain/Modifiers/RaiseModifier.cs b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/RaiseModifier.cs
new file mode 100644
index 0000000..9ac1edd
--- /dev/null
+++ b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/RaiseModifier.cs
@@ -0,0 +1,93 @@
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 */
27using System;
28using OpenSim.Region.CoreModules.World.Terrain;
29using OpenSim.Region.Framework.Interfaces;
30
31namespace OpenSim.Region.CoreModules.World.Terrain.Modifiers
32{
33 public class RaiseModifier : TerrainModifier
34 {
35 public RaiseModifier(ITerrainModule module) : base(module)
36 {
37 }
38
39 public override string ModifyTerrain(ITerrainChannel map, string[] args)
40 {
41 string val;
42 string result;
43 if (args.Length < 3)
44 {
45 result = "Usage: " + GetUsage();
46 }
47 else
48 {
49 TerrainModifierData data;
50 result = this.parseParameters(args, out data);
51
52 // Context-specific validation
53 if (result == String.Empty)
54 {
55 if (data.shape == String.Empty)
56 {
57 data.shape = "rectangle";
58 data.x0 = 0;
59 data.y0 = 0;
60 data.dx = map.Width;
61 data.dy = map.Height;
62 }
63 }
64
65 // if it's all good, then do the work
66 if (result == String.Empty)
67 {
68 this.applyModification(map, data);
69 }
70 }
71
72 return result;
73 }
74
75 public override string GetUsage()
76 {
77 string val = "raise <delta> [ -rec=x1,y1,dx[,dy] | -ell=x0,y0,rx[,ry] ] [-taper=<delta2>]"
78 + "\nRaises all points within the specified range by the specified amount.";
79 return val;
80
81 }
82
83 public override double operate(double[,] map, TerrainModifierData data, int x, int y)
84 {
85 double factor = this.computeBevel(data, x, y);
86 double result = map[x, y] + (data.elevation - (data.elevation - data.bevelevation) * factor);
87 return result;
88 }
89
90 }
91
92}
93
diff --git a/OpenSim/Region/CoreModules/World/Terrain/Modifiers/SmoothModifier.cs b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/SmoothModifier.cs
new file mode 100644
index 0000000..72b172c
--- /dev/null
+++ b/OpenSim/Region/CoreModules/World/Terrain/Modifiers/SmoothModifier.cs
@@ -0,0 +1,132 @@
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 */
27using System;
28using OpenSim.Region.CoreModules.World.Terrain;
29using OpenSim.Region.Framework.Interfaces;
30
31namespace OpenSim.Region.CoreModules.World.Terrain.Modifiers
32{
33 public class SmoothModifier : TerrainModifier
34 {
35 public SmoothModifier(ITerrainModule module) : base(module)
36 {
37 }
38
39 public override string ModifyTerrain(ITerrainChannel map, string[] args)
40 {
41 string val;
42 string result;
43 if (args.Length < 3)
44 {
45 result = "Usage: " + GetUsage();
46 }
47 else
48 {
49 TerrainModifierData data;
50 result = this.parseParameters(args, out data);
51
52 // Context-specific validation
53 if (result == String.Empty)
54 {
55 if (data.bevel == "taper")
56 {
57 if (data.bevelevation < 0.01 || data.bevelevation > 0.99)
58 {
59 result = String.Format("Taper must be 0.01 to 0.99: {0}", data.bevelevation);
60 }
61 }
62 else
63 {
64 data.bevelevation = 2.0f / 3.0f;
65 }
66
67 if (data.elevation < 0.0 || data.elevation > 1.0)
68 {
69 result = String.Format("Smoothing strength must be 0.0 to 1.0: {0}", data.elevation);
70 }
71
72 if (data.shape == String.Empty)
73 {
74 data.shape = "rectangle";
75 data.x0 = 0;
76 data.y0 = 0;
77 data.dx = map.Width;
78 data.dy = map.Height;
79 }
80 }
81
82 // if it's all good, then do the work
83 if (result == String.Empty)
84 {
85 this.applyModification(map, data);
86 }
87 }
88
89 return result;
90 }
91
92 public override string GetUsage()
93 {
94 string val = "smooth <strength> [ -rec=x1,y1,dx[,dy] | -ell=x0,y0,rx[,ry] ] [-taper=<fraction>]"
95 + "\nSmooths all points within the specified range using a simple averaging algorithm.";
96 return val;
97 }
98
99 public override double operate(double[,] map, TerrainModifierData data, int x, int y)
100 {
101 double[] scale = new double[3];
102 scale[0] = data.elevation;
103 scale[1] = ((1.0 - scale[0]) * data.bevelevation) / 8.0;
104 scale[2] = ((1.0 - scale[0]) * (1.0 - data.bevelevation)) / 16.0;
105 int xMax = map.GetLength(0);
106 int yMax = map.GetLength(1);
107 double result;
108 if ((x == 0) || (y == 0) || (x == (xMax - 1)) || (y == (yMax - 1)))
109 {
110 result = map[x, y];
111 }
112 else
113 {
114 result = 0.0;
115 for(int yPos = (y - 2); yPos < (y + 3); yPos++)
116 {
117 int yVal = (yPos <= 0) ? 0 : ((yPos < yMax) ? yPos : yMax - 1);
118 for(int xPos = (x - 2); xPos < (x + 3); xPos++)
119 {
120 int xVal = (xPos <= 0) ? 0 : ((xPos < xMax) ? xPos : xMax - 1);
121 int dist = Math.Max(Math.Abs(x - xVal), Math.Abs(y - yVal));
122 result += map[xVal, yVal] * scale[dist];
123 }
124 }
125 }
126 return result;
127 }
128
129 }
130
131}
132
diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModifier.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModifier.cs
new file mode 100644
index 0000000..7ebd08e
--- /dev/null
+++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModifier.cs
@@ -0,0 +1,378 @@
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 */
27using System;
28using System.Reflection;
29using log4net;
30
31using OpenSim.Region.Framework.Interfaces;
32
33namespace OpenSim.Region.CoreModules.World.Terrain
34{
35 public abstract class TerrainModifier : ITerrainModifier
36 {
37 protected ITerrainModule m_module;
38 protected static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
39
40 protected TerrainModifier(ITerrainModule module)
41 {
42 m_module = module;
43 }
44
45 public abstract string ModifyTerrain(ITerrainChannel map, string[] args);
46
47 public abstract string GetUsage();
48
49 public abstract double operate(double[,] map, TerrainModifierData data, int x, int y);
50
51 protected String parseParameters(string[] args, out TerrainModifierData data)
52 {
53 string val;
54 string arg;
55 string result;
56 data = new TerrainModifierData();
57 data.shape = String.Empty;
58 data.bevel = String.Empty;
59 data.dx = 0;
60 data.dy = 0;
61 if (args.Length < 4)
62 {
63 result = "Usage: " + GetUsage();
64 }
65 else
66 {
67 result = this.parseFloat(args[3], out data.elevation);
68 }
69 if (result == String.Empty)
70 {
71 int index = 3;
72 while(++index < args.Length && result == String.Empty)
73 {
74 arg = args[index];
75 // check for shape
76 if (arg.StartsWith("-rec=") || arg.StartsWith("-ell="))
77 {
78 if (data.shape != String.Empty)
79 {
80 result = "Only 1 '-rec' or '-ell' parameter is permitted.";
81 }
82 else
83 {
84 data.shape = arg.StartsWith("-ell=") ? "ellipse" : "rectangle";
85 val = arg.Substring(arg.IndexOf("=") + 1);
86 string[] coords = val.Split(new char[] {','});
87 if ((coords.Length < 3) || (coords.Length > 4))
88 {
89 result = String.Format("Bad format for shape parameter {0}", arg);
90 }
91 else
92 {
93 result = this.parseInt(coords[0], out data.x0);
94 if (result == String.Empty)
95 {
96 result = this.parseInt(coords[1], out data.y0);
97 }
98 if (result == String.Empty)
99 {
100 result = this.parseInt(coords[2], out data.dx);
101 }
102 if (result == String.Empty)
103 {
104 if (coords.Length == 4)
105 {
106 result = this.parseInt(coords[3], out data.dy);
107 }
108 else
109 {
110 data.dy = data.dx;
111 }
112 }
113 if (result == String.Empty)
114 {
115 if ((data.dx <= 0) || (data.dy <= 0))
116 {
117 result = "Shape sizes must be positive integers";
118 }
119 }
120 else
121 {
122 result = String.Format("Bad value in shape parameters {0}", arg);
123 }
124 }
125 }
126 }
127 else if (arg.StartsWith("-taper="))
128 {
129 if (data.bevel != String.Empty)
130 {
131 result = "Only 1 '-taper' parameter is permitted.";
132 }
133 else
134 {
135 data.bevel = "taper";
136 val = arg.Substring(arg.IndexOf("=") + 1);
137 result = this.parseFloat(val, out data.bevelevation);
138 if (result != String.Empty)
139 {
140 result = String.Format("Bad format for taper parameter {0}", arg);
141 }
142 }
143 }
144 else
145 {
146 result = String.Format("Unrecognized parameter {0}", arg);
147 }
148 }
149 }
150 return result;
151 }
152
153 protected string parseFloat(String s, out float f)
154 {
155 string result;
156 double d;
157 if (Double.TryParse(s, out d))
158 {
159 try
160 {
161 f = (float)d;
162 result = String.Empty;
163 }
164 catch(InvalidCastException)
165 {
166 result = String.Format("{0} is invalid", s);
167 f = -1.0f;
168 }
169 }
170 else
171 {
172 f = -1.0f;
173 result = String.Format("{0} is invalid", s);
174 }
175 return result;
176 }
177
178 protected string parseInt(String s, out int i)
179 {
180 string result;
181 if (Int32.TryParse(s, out i))
182 {
183 result = String.Empty;
184 }
185 else
186 {
187 result = String.Format("{0} is invalid", s);
188 }
189 return result;
190 }
191
192 protected void applyModification(ITerrainChannel map, TerrainModifierData data)
193 {
194 bool[,] mask;
195 int xMax;
196 int yMax;
197 int xMid;
198 int yMid;
199 if (data.shape == "ellipse")
200 {
201 mask = this.ellipticalMask(data.dx, data.dy);
202 xMax = mask.GetLength(0);
203 yMax = mask.GetLength(1);
204 xMid = xMax / 2 + xMax % 2;
205 yMid = yMax / 2 + yMax % 2;
206 }
207 else
208 {
209 mask = this.rectangularMask(data.dx, data.dy);
210 xMax = mask.GetLength(0);
211 yMax = mask.GetLength(1);
212 xMid = 0;
213 yMid = 0;
214 }
215// m_log.DebugFormat("Apply {0} mask {1}x{2} @ {3},{4}", data.shape, xMax, yMax, xMid, yMid);
216 double[,] buffer = map.GetDoubles();
217 int yDim = yMax;
218 while(--yDim >= 0)
219 {
220 int yPos = data.y0 + yDim - yMid;
221 if ((yPos >= 0) && (yPos < map.Height))
222 {
223 int xDim = xMax;
224 while(--xDim >= 0)
225 {
226 int xPos = data.x0 + xDim - xMid;
227 if ((xPos >= 0) && (xPos < map.Width) && (mask[xDim, yDim]))
228 {
229 double endElevation = this.operate(buffer, data, xPos, yPos);
230 map[xPos, yPos] = endElevation;
231 }
232 }
233 }
234 }
235 }
236
237 protected double computeBevel(TerrainModifierData data, int x, int y)
238 {
239 int deltaX;
240 int deltaY;
241 int xMax;
242 int yMax;
243 double factor;
244 if (data.bevel == "taper")
245 {
246 if (data.shape == "ellipse")
247 {
248 deltaX = x - data.x0;
249 deltaY = y - data.y0;
250 xMax = data.dx;
251 yMax = data.dy;
252 factor = (double)((deltaX * deltaX) + (deltaY * deltaY));
253 factor /= ((xMax * xMax) + (yMax * yMax));
254 }
255 else
256 {
257 // pyramid
258 xMax = data.dx / 2 + data.dx % 2;
259 yMax = data.dy / 2 + data.dy % 2;
260 deltaX = Math.Abs(data.x0 + xMax - x);
261 deltaY = Math.Abs(data.y0 + yMax - y);
262 factor = Math.Max(((double)(deltaY) / yMax), ((double)(deltaX) / xMax));
263 }
264 }
265 else
266 {
267 factor = 0.0;
268 }
269 return factor;
270 }
271
272 private bool[,] rectangularMask(int xSize, int ySize)
273 {
274 bool[,] mask = new bool[xSize, ySize];
275 int yPos = ySize;
276 while(--yPos >= 0)
277 {
278 int xPos = xSize;
279 while(--xPos >= 0)
280 {
281 mask[xPos, yPos] = true;
282 }
283 }
284 return mask;
285 }
286
287 /*
288 * Fast ellipse-based derivative of Bresenham algorithm.
289 * https://web.archive.org/web/20120225095359/http://homepage.smc.edu/kennedy_john/belipse.pdf
290 */
291 private bool[,] ellipticalMask(int xRadius, int yRadius)
292 {
293 long twoASquared = 2L * xRadius * xRadius;
294 long twoBSquared = 2L * yRadius * yRadius;
295
296 bool[,] mask = new bool[2 * xRadius + 1, 2 * yRadius + 1];
297
298 long ellipseError = 0L;
299 long stoppingX = twoBSquared * xRadius;
300 long stoppingY = 0L;
301 long xChange = yRadius * yRadius * (1L - 2L * xRadius);
302 long yChange = xRadius * xRadius;
303
304 int xPos = xRadius;
305 int yPos = 0;
306
307 // first set of points
308 while(stoppingX >= stoppingY)
309 {
310 int yUpper = yRadius + yPos;
311 int yLower = yRadius - yPos;
312 // fill in the mask
313 int xNow = xPos;
314 while(xNow >= 0)
315 {
316 mask[xRadius + xNow, yUpper] = true;
317 mask[xRadius - xNow, yUpper] = true;
318 mask[xRadius + xNow, yLower] = true;
319 mask[xRadius - xNow, yLower] = true;
320 --xNow;
321 }
322 yPos++;
323 stoppingY += twoASquared;
324 ellipseError += yChange;
325 yChange += twoASquared;
326 if ((2L * ellipseError + xChange) > 0L)
327 {
328 xPos--;
329 stoppingX -= twoBSquared;
330 ellipseError += xChange;
331 xChange += twoBSquared;
332 }
333 }
334
335 // second set of points
336 xPos = 0;
337 yPos = yRadius;
338 xChange = yRadius * yRadius;
339 yChange = xRadius * xRadius * (1L - 2L * yRadius);
340
341 ellipseError = 0L;
342 stoppingX = 0L;
343 stoppingY = twoASquared * yRadius;
344
345 while(stoppingX <= stoppingY)
346 {
347 int xUpper = xRadius + xPos;
348 int xLower = xRadius - xPos;
349 // fill in the mask
350 int yNow = yPos;
351 while(yNow >= 0)
352 {
353 mask[xUpper, yRadius + yNow] = true;
354 mask[xUpper, yRadius - yNow] = true;
355 mask[xLower, yRadius + yNow] = true;
356 mask[xLower, yRadius - yNow] = true;
357 --yNow;
358 }
359 xPos++;
360 stoppingX += twoBSquared;
361 ellipseError += xChange;
362 xChange += twoBSquared;
363 if ((2L * ellipseError + yChange) > 0L)
364 {
365 yPos--;
366 stoppingY -= twoASquared;
367 ellipseError += yChange;
368 yChange += twoASquared;
369 }
370 }
371 return mask;
372 }
373
374
375 }
376
377}
378
diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModifierData.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModifierData.cs
new file mode 100644
index 0000000..4e0f8d7
--- /dev/null
+++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModifierData.cs
@@ -0,0 +1,17 @@
1using System;
2
3namespace OpenSim.Region.CoreModules.World.Terrain
4{
5 public struct TerrainModifierData
6 {
7 public float elevation;
8 public string shape;
9 public int x0;
10 public int y0;
11 public int dx;
12 public int dy;
13 public string bevel;
14 public float bevelevation;
15 }
16}
17
diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
index 3bb8040..05c5fca 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
@@ -24,7 +24,6 @@
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 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. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27
28using System; 27using System;
29using System.Collections.Generic; 28using System.Collections.Generic;
30using System.IO; 29using System.IO;
@@ -42,7 +41,7 @@ using OpenSim.Framework;
42using OpenSim.Framework.Console; 41using OpenSim.Framework.Console;
43using OpenSim.Region.CoreModules.Framework.InterfaceCommander; 42using OpenSim.Region.CoreModules.Framework.InterfaceCommander;
44using OpenSim.Region.CoreModules.World.Terrain.FileLoaders; 43using OpenSim.Region.CoreModules.World.Terrain.FileLoaders;
45using OpenSim.Region.CoreModules.World.Terrain.Features; 44using OpenSim.Region.CoreModules.World.Terrain.Modifiers;
46using OpenSim.Region.CoreModules.World.Terrain.FloodBrushes; 45using OpenSim.Region.CoreModules.World.Terrain.FloodBrushes;
47using OpenSim.Region.CoreModules.World.Terrain.PaintBrushes; 46using OpenSim.Region.CoreModules.World.Terrain.PaintBrushes;
48using OpenSim.Region.Framework.Interfaces; 47using OpenSim.Region.Framework.Interfaces;
@@ -75,14 +74,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain
75 74
76 #endregion 75 #endregion
77 76
78 /// <summary>
79 /// Terrain Features
80 /// </summary>
81 public enum TerrainFeatures: byte
82 {
83 Rectangle = 1,
84 }
85
86 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 77 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
87 78
88#pragma warning disable 414 79#pragma warning disable 414
@@ -90,26 +81,19 @@ namespace OpenSim.Region.CoreModules.World.Terrain
90#pragma warning restore 414 81#pragma warning restore 414
91 82
92 private readonly Commander m_commander = new Commander("terrain"); 83 private readonly Commander m_commander = new Commander("terrain");
93
94 private readonly Dictionary<StandardTerrainEffects, ITerrainFloodEffect> m_floodeffects = 84 private readonly Dictionary<StandardTerrainEffects, ITerrainFloodEffect> m_floodeffects =
95 new Dictionary<StandardTerrainEffects, ITerrainFloodEffect>(); 85 new Dictionary<StandardTerrainEffects, ITerrainFloodEffect>();
96
97 private readonly Dictionary<string, ITerrainLoader> m_loaders = new Dictionary<string, ITerrainLoader>(); 86 private readonly Dictionary<string, ITerrainLoader> m_loaders = new Dictionary<string, ITerrainLoader>();
98
99 private readonly Dictionary<StandardTerrainEffects, ITerrainPaintableEffect> m_painteffects = 87 private readonly Dictionary<StandardTerrainEffects, ITerrainPaintableEffect> m_painteffects =
100 new Dictionary<StandardTerrainEffects, ITerrainPaintableEffect>(); 88 new Dictionary<StandardTerrainEffects, ITerrainPaintableEffect>();
101
102 private Dictionary<string, ITerrainEffect> m_plugineffects; 89 private Dictionary<string, ITerrainEffect> m_plugineffects;
103 90 private Dictionary<string, ITerrainModifier> m_modifyOperations =
104 private Dictionary<string, ITerrainFeature> m_featureEffects = 91 new Dictionary<string, ITerrainModifier>();
105 new Dictionary<string, ITerrainFeature>();
106
107 private ITerrainChannel m_channel; 92 private ITerrainChannel m_channel;
108 private ITerrainChannel m_revert; 93 private ITerrainChannel m_revert;
109 private Scene m_scene; 94 private Scene m_scene;
110 private volatile bool m_tainted; 95 private volatile bool m_tainted;
111 private readonly Stack<LandUndoState> m_undo = new Stack<LandUndoState>(5); 96 private readonly Stack<LandUndoState> m_undo = new Stack<LandUndoState>(5);
112
113 private String m_InitialTerrain = "pinhead-island"; 97 private String m_InitialTerrain = "pinhead-island";
114 98
115 // If true, send terrain patch updates to clients based on their view distance 99 // If true, send terrain patch updates to clients based on their view distance
@@ -136,14 +120,17 @@ namespace OpenSim.Region.CoreModules.World.Terrain
136 { 120 {
137 return (updateCount > 0); 121 return (updateCount > 0);
138 } 122 }
123
139 public void SetByXY(int x, int y, bool state) 124 public void SetByXY(int x, int y, bool state)
140 { 125 {
141 this.SetByPatch(x / Constants.TerrainPatchSize, y / Constants.TerrainPatchSize, state); 126 this.SetByPatch(x / Constants.TerrainPatchSize, y / Constants.TerrainPatchSize, state);
142 } 127 }
128
143 public bool GetByPatch(int patchX, int patchY) 129 public bool GetByPatch(int patchX, int patchY)
144 { 130 {
145 return updated[patchX, patchY]; 131 return updated[patchX, patchY];
146 } 132 }
133
147 public void SetByPatch(int patchX, int patchY, bool state) 134 public void SetByPatch(int patchX, int patchY, bool state)
148 { 135 {
149 bool prevState = updated[patchX, patchY]; 136 bool prevState = updated[patchX, patchY];
@@ -153,11 +140,12 @@ namespace OpenSim.Region.CoreModules.World.Terrain
153 updateCount--; 140 updateCount--;
154 updated[patchX, patchY] = state; 141 updated[patchX, patchY] = state;
155 } 142 }
143
156 public void SetAll(bool state) 144 public void SetAll(bool state)
157 { 145 {
158 updateCount = 0; 146 updateCount = 0;
159 for (int xx = 0; xx < updated.GetLength(0); xx++) 147 for(int xx = 0; xx < updated.GetLength(0); xx++)
160 for (int yy = 0; yy < updated.GetLength(1); yy++) 148 for(int yy = 0; yy < updated.GetLength(1); yy++)
161 updated[xx, yy] = state; 149 updated[xx, yy] = state;
162 if (state) 150 if (state)
163 updateCount = updated.GetLength(0) * updated.GetLength(1); 151 updateCount = updated.GetLength(0) * updated.GetLength(1);
@@ -174,9 +162,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain
174 terrData.SizeX / Constants.TerrainPatchSize, terrData.SizeY / Constants.TerrainPatchSize) 162 terrData.SizeX / Constants.TerrainPatchSize, terrData.SizeY / Constants.TerrainPatchSize)
175 ); 163 );
176 } 164 }
177 for (int xx = 0; xx < terrData.SizeX; xx += Constants.TerrainPatchSize) 165 for(int xx = 0; xx < terrData.SizeX; xx += Constants.TerrainPatchSize)
178 { 166 {
179 for (int yy = 0; yy < terrData.SizeY; yy += Constants.TerrainPatchSize) 167 for(int yy = 0; yy < terrData.SizeY; yy += Constants.TerrainPatchSize)
180 { 168 {
181 // Only set tainted. The patch bit may be set if the patch was to be sent later. 169 // Only set tainted. The patch bit may be set if the patch was to be sent later.
182 if (terrData.IsTaintedAt(xx, yy, false)) 170 if (terrData.IsTaintedAt(xx, yy, false))
@@ -201,8 +189,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
201 189
202 #region ICommandableModule Members 190 #region ICommandableModule Members
203 191
204 public ICommander CommandInterface 192 public ICommander CommandInterface {
205 {
206 get { return m_commander; } 193 get { return m_commander; }
207 } 194 }
208 195
@@ -230,7 +217,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
230 m_scene = scene; 217 m_scene = scene;
231 218
232 // Install terrain module in the simulator 219 // Install terrain module in the simulator
233 lock (m_scene) 220 lock(m_scene)
234 { 221 {
235 if (m_scene.Heightmap == null) 222 if (m_scene.Heightmap == null)
236 { 223 {
@@ -262,7 +249,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
262 string supportedFilesSeparatorForTileSave = ""; 249 string supportedFilesSeparatorForTileSave = "";
263 250
264 m_supportFileExtensionsForTileSave = ""; 251 m_supportFileExtensionsForTileSave = "";
265 foreach (KeyValuePair<string, ITerrainLoader> loader in m_loaders) 252 foreach(KeyValuePair<string, ITerrainLoader> loader in m_loaders)
266 { 253 {
267 m_supportedFileExtensions += supportedFilesSeparator + loader.Key + " (" + loader.Value + ")"; 254 m_supportedFileExtensions += supportedFilesSeparator + loader.Key + " (" + loader.Value + ")";
268 supportedFilesSeparator = ", "; 255 supportedFilesSeparator = ", ";
@@ -285,7 +272,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
285 272
286 public void RemoveRegion(Scene scene) 273 public void RemoveRegion(Scene scene)
287 { 274 {
288 lock (m_scene) 275 lock(m_scene)
289 { 276 {
290 // remove the commands 277 // remove the commands
291 m_scene.UnregisterModuleCommander(m_commander.Name); 278 m_scene.UnregisterModuleCommander(m_commander.Name);
@@ -304,13 +291,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain
304 { 291 {
305 } 292 }
306 293
307 public Type ReplaceableInterface 294 public Type ReplaceableInterface {
308 {
309 get { return null; } 295 get { return null; }
310 } 296 }
311 297
312 public string Name 298 public string Name {
313 {
314 get { return "TerrainModule"; } 299 get { return "TerrainModule"; }
315 } 300 }
316 301
@@ -329,11 +314,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain
329 /// <param name="filename">Filename to terrain file. Type is determined by extension.</param> 314 /// <param name="filename">Filename to terrain file. Type is determined by extension.</param>
330 public void LoadFromFile(string filename) 315 public void LoadFromFile(string filename)
331 { 316 {
332 foreach (KeyValuePair<string, ITerrainLoader> loader in m_loaders) 317 foreach(KeyValuePair<string, ITerrainLoader> loader in m_loaders)
333 { 318 {
334 if (filename.EndsWith(loader.Key)) 319 if (filename.EndsWith(loader.Key))
335 { 320 {
336 lock (m_scene) 321 lock(m_scene)
337 { 322 {
338 try 323 try
339 { 324 {
@@ -349,20 +334,20 @@ namespace OpenSim.Region.CoreModules.World.Terrain
349 m_channel = channel; 334 m_channel = channel;
350 UpdateRevertMap(); 335 UpdateRevertMap();
351 } 336 }
352 catch (NotImplementedException) 337 catch(NotImplementedException)
353 { 338 {
354 m_log.Error("[TERRAIN]: Unable to load heightmap, the " + loader.Value + 339 m_log.Error("[TERRAIN]: Unable to load heightmap, the " + loader.Value +
355 " parser does not support file loading. (May be save only)"); 340 " parser does not support file loading. (May be save only)");
356 throw new TerrainException(String.Format("unable to load heightmap: parser {0} does not support loading", loader.Value)); 341 throw new TerrainException(String.Format("unable to load heightmap: parser {0} does not support loading", loader.Value));
357 } 342 }
358 catch (FileNotFoundException) 343 catch(FileNotFoundException)
359 { 344 {
360 m_log.Error( 345 m_log.Error(
361 "[TERRAIN]: Unable to load heightmap, file not found. (A directory permissions error may also cause this)"); 346 "[TERRAIN]: Unable to load heightmap, file not found. (A directory permissions error may also cause this)");
362 throw new TerrainException( 347 throw new TerrainException(
363 String.Format("unable to load heightmap: file {0} not found (or permissions do not allow access", filename)); 348 String.Format("unable to load heightmap: file {0} not found (or permissions do not allow access", filename));
364 } 349 }
365 catch (ArgumentException e) 350 catch(ArgumentException e)
366 { 351 {
367 m_log.ErrorFormat("[TERRAIN]: Unable to load heightmap: {0}", e.Message); 352 m_log.ErrorFormat("[TERRAIN]: Unable to load heightmap: {0}", e.Message);
368 throw new TerrainException( 353 throw new TerrainException(
@@ -386,7 +371,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
386 { 371 {
387 try 372 try
388 { 373 {
389 foreach (KeyValuePair<string, ITerrainLoader> loader in m_loaders) 374 foreach(KeyValuePair<string, ITerrainLoader> loader in m_loaders)
390 { 375 {
391 if (filename.EndsWith(loader.Key)) 376 if (filename.EndsWith(loader.Key))
392 { 377 {
@@ -396,7 +381,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
396 } 381 }
397 } 382 }
398 } 383 }
399 catch (IOException ioe) 384 catch(IOException ioe)
400 { 385 {
401 m_log.Error(String.Format("[TERRAIN]: Unable to save to {0}, {1}", filename, ioe.Message)); 386 m_log.Error(String.Format("[TERRAIN]: Unable to save to {0}, {1}", filename, ioe.Message));
402 } 387 }
@@ -429,11 +414,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain
429 public void LoadFromStream(string filename, Vector3 displacement, 414 public void LoadFromStream(string filename, Vector3 displacement,
430 float radianRotation, Vector2 rotationDisplacement, Stream stream) 415 float radianRotation, Vector2 rotationDisplacement, Stream stream)
431 { 416 {
432 foreach (KeyValuePair<string, ITerrainLoader> loader in m_loaders) 417 foreach(KeyValuePair<string, ITerrainLoader> loader in m_loaders)
433 { 418 {
434 if (filename.EndsWith(loader.Key)) 419 if (filename.EndsWith(loader.Key))
435 { 420 {
436 lock (m_scene) 421 lock(m_scene)
437 { 422 {
438 try 423 try
439 { 424 {
@@ -441,7 +426,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
441 m_channel.Merge(channel, displacement, radianRotation, rotationDisplacement); 426 m_channel.Merge(channel, displacement, radianRotation, rotationDisplacement);
442 UpdateRevertMap(); 427 UpdateRevertMap();
443 } 428 }
444 catch (NotImplementedException) 429 catch(NotImplementedException)
445 { 430 {
446 m_log.Error("[TERRAIN]: Unable to load heightmap, the " + loader.Value + 431 m_log.Error("[TERRAIN]: Unable to load heightmap, the " + loader.Value +
447 " parser does not support file loading. (May be save only)"); 432 " parser does not support file loading. (May be save only)");
@@ -501,7 +486,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
501 { 486 {
502 try 487 try
503 { 488 {
504 foreach (KeyValuePair<string, ITerrainLoader> loader in m_loaders) 489 foreach(KeyValuePair<string, ITerrainLoader> loader in m_loaders)
505 { 490 {
506 if (filename.EndsWith(loader.Key)) 491 if (filename.EndsWith(loader.Key))
507 { 492 {
@@ -510,7 +495,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
510 } 495 }
511 } 496 }
512 } 497 }
513 catch (NotImplementedException) 498 catch(NotImplementedException)
514 { 499 {
515 m_log.Error("Unable to save to " + filename + ", saving of this file format has not been implemented."); 500 m_log.Error("Unable to save to " + filename + ", saving of this file format has not been implemented.");
516 throw new TerrainException(String.Format("Unable to save heightmap: saving of this file format not implemented")); 501 throw new TerrainException(String.Format("Unable to save heightmap: saving of this file format not implemented"));
@@ -519,12 +504,12 @@ namespace OpenSim.Region.CoreModules.World.Terrain
519 504
520 // Someone diddled terrain outside the normal code paths. Set the taintedness for all clients. 505 // Someone diddled terrain outside the normal code paths. Set the taintedness for all clients.
521 // ITerrainModule.TaintTerrain() 506 // ITerrainModule.TaintTerrain()
522 public void TaintTerrain () 507 public void TaintTerrain()
523 { 508 {
524 lock (m_perClientPatchUpdates) 509 lock(m_perClientPatchUpdates)
525 { 510 {
526 // Set the flags for all clients so the tainted patches will be sent out 511 // Set the flags for all clients so the tainted patches will be sent out
527 foreach (PatchUpdates pups in m_perClientPatchUpdates.Values) 512 foreach(PatchUpdates pups in m_perClientPatchUpdates.Values)
528 { 513 {
529 pups.SetAll(m_scene.Heightmap.GetTerrainData()); 514 pups.SetAll(m_scene.Heightmap.GetTerrainData());
530 } 515 }
@@ -539,7 +524,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
539 ScenePresence presence = m_scene.GetScenePresence(pClient.AgentId); 524 ScenePresence presence = m_scene.GetScenePresence(pClient.AgentId);
540 if (presence != null) 525 if (presence != null)
541 { 526 {
542 lock (m_perClientPatchUpdates) 527 lock(m_perClientPatchUpdates)
543 { 528 {
544 PatchUpdates pups; 529 PatchUpdates pups;
545 if (!m_perClientPatchUpdates.TryGetValue(pClient.AgentId, out pups)) 530 if (!m_perClientPatchUpdates.TryGetValue(pClient.AgentId, out pups))
@@ -572,7 +557,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
572 return; 557 return;
573 558
574 string[] files = Directory.GetFiles(plugineffectsPath); 559 string[] files = Directory.GetFiles(plugineffectsPath);
575 foreach (string file in files) 560 foreach(string file in files)
576 { 561 {
577 m_log.Info("Loading effects in " + file); 562 m_log.Info("Loading effects in " + file);
578 try 563 try
@@ -580,7 +565,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
580 Assembly library = Assembly.LoadFrom(file); 565 Assembly library = Assembly.LoadFrom(file);
581 LoadPlugins(library); 566 LoadPlugins(library);
582 } 567 }
583 catch (BadImageFormatException) 568 catch(BadImageFormatException)
584 { 569 {
585 } 570 }
586 } 571 }
@@ -588,7 +573,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
588 573
589 private void LoadPlugins(Assembly library) 574 private void LoadPlugins(Assembly library)
590 { 575 {
591 foreach (Type pluginType in library.GetTypes()) 576 foreach(Type pluginType in library.GetTypes())
592 { 577 {
593 try 578 try
594 { 579 {
@@ -610,7 +595,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
610 m_log.Info("L ... " + typeName); 595 m_log.Info("L ... " + typeName);
611 } 596 }
612 } 597 }
613 catch (AmbiguousMatchException) 598 catch(AmbiguousMatchException)
614 { 599 {
615 } 600 }
616 } 601 }
@@ -618,7 +603,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
618 603
619 public void InstallPlugin(string pluginName, ITerrainEffect effect) 604 public void InstallPlugin(string pluginName, ITerrainEffect effect)
620 { 605 {
621 lock (m_plugineffects) 606 lock(m_plugineffects)
622 { 607 {
623 if (!m_plugineffects.ContainsKey(pluginName)) 608 if (!m_plugineffects.ContainsKey(pluginName))
624 { 609 {
@@ -661,8 +646,14 @@ namespace OpenSim.Region.CoreModules.World.Terrain
661 m_floodeffects[StandardTerrainEffects.Flatten] = new FlattenArea(); 646 m_floodeffects[StandardTerrainEffects.Flatten] = new FlattenArea();
662 m_floodeffects[StandardTerrainEffects.Revert] = new RevertArea(m_revert); 647 m_floodeffects[StandardTerrainEffects.Revert] = new RevertArea(m_revert);
663 648
664 // Terrain Feature effects 649 // Terrain Modifier operations
665 m_featureEffects["rectangle"] = new RectangleFeature(this); 650 m_modifyOperations["min"] = new MinModifier(this);
651 m_modifyOperations["max"] = new MaxModifier(this);
652 m_modifyOperations["raise"] = new RaiseModifier(this);
653 m_modifyOperations["lower"] = new LowerModifier(this);
654 m_modifyOperations["fill"] = new FillModifier(this);
655 m_modifyOperations["smooth"] = new SmoothModifier(this);
656 m_modifyOperations["noise"] = new NoiseModifier(this);
666 657
667 // Filesystem load/save loaders 658 // Filesystem load/save loaders
668 m_loaders[".r32"] = new RAW32(); 659 m_loaders[".r32"] = new RAW32();
@@ -707,22 +698,22 @@ namespace OpenSim.Region.CoreModules.World.Terrain
707 /// <param name="fileStartY">Where to begin our slice</param> 698 /// <param name="fileStartY">Where to begin our slice</param>
708 public void LoadFromFile(string filename, int fileWidth, int fileHeight, int fileStartX, int fileStartY) 699 public void LoadFromFile(string filename, int fileWidth, int fileHeight, int fileStartX, int fileStartY)
709 { 700 {
710 int offsetX = (int) m_scene.RegionInfo.RegionLocX - fileStartX; 701 int offsetX = (int)m_scene.RegionInfo.RegionLocX - fileStartX;
711 int offsetY = (int) m_scene.RegionInfo.RegionLocY - fileStartY; 702 int offsetY = (int)m_scene.RegionInfo.RegionLocY - fileStartY;
712 703
713 if (offsetX >= 0 && offsetX < fileWidth && offsetY >= 0 && offsetY < fileHeight) 704 if (offsetX >= 0 && offsetX < fileWidth && offsetY >= 0 && offsetY < fileHeight)
714 { 705 {
715 // this region is included in the tile request 706 // this region is included in the tile request
716 foreach (KeyValuePair<string, ITerrainLoader> loader in m_loaders) 707 foreach(KeyValuePair<string, ITerrainLoader> loader in m_loaders)
717 { 708 {
718 if (filename.EndsWith(loader.Key)) 709 if (filename.EndsWith(loader.Key))
719 { 710 {
720 lock (m_scene) 711 lock(m_scene)
721 { 712 {
722 ITerrainChannel channel = loader.Value.LoadFile(filename, offsetX, offsetY, 713 ITerrainChannel channel = loader.Value.LoadFile(filename, offsetX, offsetY,
723 fileWidth, fileHeight, 714 fileWidth, fileHeight,
724 (int) m_scene.RegionInfo.RegionSizeX, 715 (int)m_scene.RegionInfo.RegionSizeX,
725 (int) m_scene.RegionInfo.RegionSizeY); 716 (int)m_scene.RegionInfo.RegionSizeY);
726 m_scene.Heightmap = channel; 717 m_scene.Heightmap = channel;
727 m_channel = channel; 718 m_channel = channel;
728 UpdateRevertMap(); 719 UpdateRevertMap();
@@ -761,11 +752,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain
761 } 752 }
762 753
763 // this region is included in the tile request 754 // this region is included in the tile request
764 foreach (KeyValuePair<string, ITerrainLoader> loader in m_loaders) 755 foreach(KeyValuePair<string, ITerrainLoader> loader in m_loaders)
765 { 756 {
766 if (filename.EndsWith(loader.Key) && loader.Value.SupportsTileSave()) 757 if (filename.EndsWith(loader.Key) && loader.Value.SupportsTileSave())
767 { 758 {
768 lock (m_scene) 759 lock(m_scene)
769 { 760 {
770 loader.Value.SaveFile(m_channel, filename, offsetX, offsetY, 761 loader.Value.SaveFile(m_channel, filename, offsetX, offsetY,
771 fileWidth, fileHeight, 762 fileWidth, fileHeight,
@@ -799,9 +790,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain
799 TerrainData terrData = m_channel.GetTerrainData(); 790 TerrainData terrData = m_channel.GetTerrainData();
800 791
801 bool shouldTaint = false; 792 bool shouldTaint = false;
802 for (int x = 0; x < terrData.SizeX; x += Constants.TerrainPatchSize) 793 for(int x = 0; x < terrData.SizeX; x += Constants.TerrainPatchSize)
803 { 794 {
804 for (int y = 0; y < terrData.SizeY; y += Constants.TerrainPatchSize) 795 for(int y = 0; y < terrData.SizeY; y += Constants.TerrainPatchSize)
805 { 796 {
806 if (terrData.IsTaintedAt(x, y)) 797 if (terrData.IsTaintedAt(x, y))
807 { 798 {
@@ -856,7 +847,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
856 847
857 string[] tmpArgs = new string[args.Length - 2]; 848 string[] tmpArgs = new string[args.Length - 2];
858 int i; 849 int i;
859 for (i = 2; i < args.Length; i++) 850 for(i = 2; i < args.Length; i++)
860 tmpArgs[i - 2] = args[i]; 851 tmpArgs[i - 2] = args[i];
861 852
862 m_commander.ProcessConsoleCommand(args[1], tmpArgs); 853 m_commander.ProcessConsoleCommand(args[1], tmpArgs);
@@ -890,7 +881,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
890 presence.ControllingClient.OnUnackedTerrain -= client_OnUnackedTerrain; 881 presence.ControllingClient.OnUnackedTerrain -= client_OnUnackedTerrain;
891 } 882 }
892 883
893 lock (m_perClientPatchUpdates) 884 lock(m_perClientPatchUpdates)
894 m_perClientPatchUpdates.Remove(client); 885 m_perClientPatchUpdates.Remove(client);
895 } 886 }
896 887
@@ -904,12 +895,12 @@ namespace OpenSim.Region.CoreModules.World.Terrain
904 TerrainData terrData = m_channel.GetTerrainData(); 895 TerrainData terrData = m_channel.GetTerrainData();
905 896
906 bool wasLimited = false; 897 bool wasLimited = false;
907 for (int x = 0; x < terrData.SizeX; x += Constants.TerrainPatchSize) 898 for(int x = 0; x < terrData.SizeX; x += Constants.TerrainPatchSize)
908 { 899 {
909 for (int y = 0; y < terrData.SizeY; y += Constants.TerrainPatchSize) 900 for(int y = 0; y < terrData.SizeY; y += Constants.TerrainPatchSize)
910 { 901 {
911 if (terrData.IsTaintedAt(x, y, false /* clearOnTest */)) 902 if (terrData.IsTaintedAt(x, y, false /* clearOnTest */))
912 { 903 {
913 // If we should respect the estate settings then 904 // If we should respect the estate settings then
914 // fixup and height deltas that don't respect them. 905 // fixup and height deltas that don't respect them.
915 // Note that LimitChannelChanges() modifies the TerrainChannel with the limited height values. 906 // Note that LimitChannelChanges() modifies the TerrainChannel with the limited height values.
@@ -933,9 +924,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain
933 924
934 // loop through the height map for this patch and compare it against 925 // loop through the height map for this patch and compare it against
935 // the revert map 926 // the revert map
936 for (int x = xStart; x < xStart + Constants.TerrainPatchSize; x++) 927 for(int x = xStart; x < xStart + Constants.TerrainPatchSize; x++)
937 { 928 {
938 for (int y = yStart; y < yStart + Constants.TerrainPatchSize; y++) 929 for(int y = yStart; y < yStart + Constants.TerrainPatchSize; y++)
939 { 930 {
940 float requestedHeight = terrData[x, y]; 931 float requestedHeight = terrData[x, y];
941 float bakedHeight = (float)m_revert[x, y]; 932 float bakedHeight = (float)m_revert[x, y];
@@ -959,7 +950,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
959 950
960 private void client_OnLandUndo(IClientAPI client) 951 private void client_OnLandUndo(IClientAPI client)
961 { 952 {
962 lock (m_undo) 953 lock(m_undo)
963 { 954 {
964 if (m_undo.Count > 0) 955 if (m_undo.Count > 0)
965 { 956 {
@@ -981,19 +972,19 @@ namespace OpenSim.Region.CoreModules.World.Terrain
981 if (m_sendTerrainUpdatesByViewDistance) 972 if (m_sendTerrainUpdatesByViewDistance)
982 { 973 {
983 // Add that this patch needs to be sent to the accounting for each client. 974 // Add that this patch needs to be sent to the accounting for each client.
984 lock (m_perClientPatchUpdates) 975 lock(m_perClientPatchUpdates)
985 { 976 {
986 m_scene.ForEachScenePresence(presence => 977 m_scene.ForEachScenePresence(presence =>
978 {
979 PatchUpdates thisClientUpdates;
980 if (!m_perClientPatchUpdates.TryGetValue(presence.UUID, out thisClientUpdates))
987 { 981 {
988 PatchUpdates thisClientUpdates; 982 // There is a ScenePresence without a send patch map. Create one.
989 if (!m_perClientPatchUpdates.TryGetValue(presence.UUID, out thisClientUpdates)) 983 thisClientUpdates = new PatchUpdates(terrData, presence);
990 { 984 m_perClientPatchUpdates.Add(presence.UUID, thisClientUpdates);
991 // There is a ScenePresence without a send patch map. Create one.
992 thisClientUpdates = new PatchUpdates(terrData, presence);
993 m_perClientPatchUpdates.Add(presence.UUID, thisClientUpdates);
994 }
995 thisClientUpdates.SetByXY(x, y, true);
996 } 985 }
986 thisClientUpdates.SetByXY(x, y, true);
987 }
997 ); 988 );
998 } 989 }
999 } 990 }
@@ -1005,11 +996,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1005 float[] heightMap = new float[10]; 996 float[] heightMap = new float[10];
1006 m_scene.ForEachClient( 997 m_scene.ForEachClient(
1007 delegate(IClientAPI controller) 998 delegate(IClientAPI controller)
1008 { 999 {
1009 controller.SendLayerData(x / Constants.TerrainPatchSize, 1000 controller.SendLayerData(x / Constants.TerrainPatchSize,
1010 y / Constants.TerrainPatchSize, 1001 y / Constants.TerrainPatchSize,
1011 heightMap); 1002 heightMap);
1012 } 1003 }
1013 ); 1004 );
1014 } 1005 }
1015 } 1006 }
@@ -1019,12 +1010,14 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1019 public int PatchX; 1010 public int PatchX;
1020 public int PatchY; 1011 public int PatchY;
1021 public float Dist; 1012 public float Dist;
1013
1022 public PatchesToSend(int pX, int pY, float pDist) 1014 public PatchesToSend(int pX, int pY, float pDist)
1023 { 1015 {
1024 PatchX = pX; 1016 PatchX = pX;
1025 PatchY = pY; 1017 PatchY = pY;
1026 Dist = pDist; 1018 Dist = pDist;
1027 } 1019 }
1020
1028 public int CompareTo(PatchesToSend other) 1021 public int CompareTo(PatchesToSend other)
1029 { 1022 {
1030 return Dist.CompareTo(other.Dist); 1023 return Dist.CompareTo(other.Dist);
@@ -1036,9 +1029,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1036 // Loop through all the per-client info and send any patches necessary. 1029 // Loop through all the per-client info and send any patches necessary.
1037 private void CheckSendingPatchesToClients() 1030 private void CheckSendingPatchesToClients()
1038 { 1031 {
1039 lock (m_perClientPatchUpdates) 1032 lock(m_perClientPatchUpdates)
1040 { 1033 {
1041 foreach (PatchUpdates pups in m_perClientPatchUpdates.Values) 1034 foreach(PatchUpdates pups in m_perClientPatchUpdates.Values)
1042 { 1035 {
1043 if (pups.HasUpdates()) 1036 if (pups.HasUpdates())
1044 { 1037 {
@@ -1062,7 +1055,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1062 int[] yPieces = new int[toSend.Count]; 1055 int[] yPieces = new int[toSend.Count];
1063 float[] patchPieces = new float[toSend.Count * 2]; 1056 float[] patchPieces = new float[toSend.Count * 2];
1064 int pieceIndex = 0; 1057 int pieceIndex = 0;
1065 foreach (PatchesToSend pts in toSend) 1058 foreach(PatchesToSend pts in toSend)
1066 { 1059 {
1067 patchPieces[pieceIndex++] = pts.PatchX; 1060 patchPieces[pieceIndex++] = pts.PatchX;
1068 patchPieces[pieceIndex++] = pts.PatchY; 1061 patchPieces[pieceIndex++] = pts.PatchY;
@@ -1083,25 +1076,25 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1083 return ret; 1076 return ret;
1084 1077
1085 // Compute the area of patches within our draw distance 1078 // Compute the area of patches within our draw distance
1086 int startX = (((int) (presence.AbsolutePosition.X - presence.DrawDistance))/Constants.TerrainPatchSize) - 2; 1079 int startX = (((int)(presence.AbsolutePosition.X - presence.DrawDistance)) / Constants.TerrainPatchSize) - 2;
1087 startX = Math.Max(startX, 0); 1080 startX = Math.Max(startX, 0);
1088 startX = Math.Min(startX, (int)m_scene.RegionInfo.RegionSizeX/Constants.TerrainPatchSize); 1081 startX = Math.Min(startX, (int)m_scene.RegionInfo.RegionSizeX / Constants.TerrainPatchSize);
1089 int startY = (((int) (presence.AbsolutePosition.Y - presence.DrawDistance))/Constants.TerrainPatchSize) - 2; 1082 int startY = (((int)(presence.AbsolutePosition.Y - presence.DrawDistance)) / Constants.TerrainPatchSize) - 2;
1090 startY = Math.Max(startY, 0); 1083 startY = Math.Max(startY, 0);
1091 startY = Math.Min(startY, (int)m_scene.RegionInfo.RegionSizeY/Constants.TerrainPatchSize); 1084 startY = Math.Min(startY, (int)m_scene.RegionInfo.RegionSizeY / Constants.TerrainPatchSize);
1092 int endX = (((int) (presence.AbsolutePosition.X + presence.DrawDistance))/Constants.TerrainPatchSize) + 2; 1085 int endX = (((int)(presence.AbsolutePosition.X + presence.DrawDistance)) / Constants.TerrainPatchSize) + 2;
1093 endX = Math.Max(endX, 0); 1086 endX = Math.Max(endX, 0);
1094 endX = Math.Min(endX, (int)m_scene.RegionInfo.RegionSizeX/Constants.TerrainPatchSize); 1087 endX = Math.Min(endX, (int)m_scene.RegionInfo.RegionSizeX / Constants.TerrainPatchSize);
1095 int endY = (((int) (presence.AbsolutePosition.Y + presence.DrawDistance))/Constants.TerrainPatchSize) + 2; 1088 int endY = (((int)(presence.AbsolutePosition.Y + presence.DrawDistance)) / Constants.TerrainPatchSize) + 2;
1096 endY = Math.Max(endY, 0); 1089 endY = Math.Max(endY, 0);
1097 endY = Math.Min(endY, (int)m_scene.RegionInfo.RegionSizeY/Constants.TerrainPatchSize); 1090 endY = Math.Min(endY, (int)m_scene.RegionInfo.RegionSizeY / Constants.TerrainPatchSize);
1098 // m_log.DebugFormat("{0} GetModifiedPatchesInViewDistance. rName={1}, ddist={2}, apos={3}, start=<{4},{5}>, end=<{6},{7}>", 1091 // m_log.DebugFormat("{0} GetModifiedPatchesInViewDistance. rName={1}, ddist={2}, apos={3}, start=<{4},{5}>, end=<{6},{7}>",
1099 // LogHeader, m_scene.RegionInfo.RegionName, 1092 // LogHeader, m_scene.RegionInfo.RegionName,
1100 // presence.DrawDistance, presence.AbsolutePosition, 1093 // presence.DrawDistance, presence.AbsolutePosition,
1101 // startX, startY, endX, endY); 1094 // startX, startY, endX, endY);
1102 for (int x = startX; x < endX; x++) 1095 for(int x = startX; x < endX; x++)
1103 { 1096 {
1104 for (int y = startY; y < endY; y++) 1097 for(int y = startY; y < endY; y++)
1105 { 1098 {
1106 //Need to make sure we don't send the same ones over and over 1099 //Need to make sure we don't send the same ones over and over
1107 Vector3 presencePos = presence.AbsolutePosition; 1100 Vector3 presencePos = presence.AbsolutePosition;
@@ -1133,28 +1126,28 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1133 bool allowed = false; 1126 bool allowed = false;
1134 if (north == south && east == west) 1127 if (north == south && east == west)
1135 { 1128 {
1136 if (m_painteffects.ContainsKey((StandardTerrainEffects) action)) 1129 if (m_painteffects.ContainsKey((StandardTerrainEffects)action))
1137 { 1130 {
1138 bool[,] allowMask = new bool[m_channel.Width,m_channel.Height]; 1131 bool[,] allowMask = new bool[m_channel.Width, m_channel.Height];
1139 allowMask.Initialize(); 1132 allowMask.Initialize();
1140 int n = size + 1; 1133 int n = size + 1;
1141 if (n > 2) 1134 if (n > 2)
1142 n = 4; 1135 n = 4;
1143 1136
1144 int zx = (int) (west + 0.5); 1137 int zx = (int)(west + 0.5);
1145 int zy = (int) (north + 0.5); 1138 int zy = (int)(north + 0.5);
1146 1139
1147 int dx; 1140 int dx;
1148 for (dx=-n; dx<=n; dx++) 1141 for(dx=-n; dx<=n; dx++)
1149 { 1142 {
1150 int dy; 1143 int dy;
1151 for (dy=-n; dy<=n; dy++) 1144 for(dy=-n; dy<=n; dy++)
1152 { 1145 {
1153 int x = zx + dx; 1146 int x = zx + dx;
1154 int y = zy + dy; 1147 int y = zy + dy;
1155 if (x>=0 && y>=0 && x<m_channel.Width && y<m_channel.Height) 1148 if (x >= 0 && y >= 0 && x < m_channel.Width && y < m_channel.Height)
1156 { 1149 {
1157 if (m_scene.Permissions.CanTerraformLand(agentId, new Vector3(x,y,0))) 1150 if (m_scene.Permissions.CanTerraformLand(agentId, new Vector3(x, y, 0)))
1158 { 1151 {
1159 allowMask[x, y] = true; 1152 allowMask[x, y] = true;
1160 allowed = true; 1153 allowed = true;
@@ -1165,7 +1158,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1165 if (allowed) 1158 if (allowed)
1166 { 1159 {
1167 StoreUndoState(); 1160 StoreUndoState();
1168 m_painteffects[(StandardTerrainEffects) action].PaintEffect( 1161 m_painteffects[(StandardTerrainEffects)action].PaintEffect(
1169 m_channel, allowMask, west, south, height, size, seconds); 1162 m_channel, allowMask, west, south, height, size, seconds);
1170 1163
1171 //revert changes outside estate limits 1164 //revert changes outside estate limits
@@ -1180,22 +1173,22 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1180 } 1173 }
1181 else 1174 else
1182 { 1175 {
1183 if (m_floodeffects.ContainsKey((StandardTerrainEffects) action)) 1176 if (m_floodeffects.ContainsKey((StandardTerrainEffects)action))
1184 { 1177 {
1185 bool[,] fillArea = new bool[m_channel.Width,m_channel.Height]; 1178 bool[,] fillArea = new bool[m_channel.Width, m_channel.Height];
1186 fillArea.Initialize(); 1179 fillArea.Initialize();
1187 1180
1188 int x; 1181 int x;
1189 for (x = 0; x < m_channel.Width; x++) 1182 for(x = 0; x < m_channel.Width; x++)
1190 { 1183 {
1191 int y; 1184 int y;
1192 for (y = 0; y < m_channel.Height; y++) 1185 for(y = 0; y < m_channel.Height; y++)
1193 { 1186 {
1194 if (x < east && x > west) 1187 if (x < east && x > west)
1195 { 1188 {
1196 if (y < north && y > south) 1189 if (y < north && y > south)
1197 { 1190 {
1198 if (m_scene.Permissions.CanTerraformLand(agentId, new Vector3(x,y,0))) 1191 if (m_scene.Permissions.CanTerraformLand(agentId, new Vector3(x, y, 0)))
1199 { 1192 {
1200 fillArea[x, y] = true; 1193 fillArea[x, y] = true;
1201 allowed = true; 1194 allowed = true;
@@ -1208,7 +1201,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1208 if (allowed) 1201 if (allowed)
1209 { 1202 {
1210 StoreUndoState(); 1203 StoreUndoState();
1211 m_floodeffects[(StandardTerrainEffects) action].FloodEffect(m_channel, fillArea, size); 1204 m_floodeffects[(StandardTerrainEffects)action].FloodEffect(m_channel, fillArea, size);
1212 1205
1213 //revert changes outside estate limits 1206 //revert changes outside estate limits
1214 if (!god) 1207 if (!god)
@@ -1243,7 +1236,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1243 1236
1244 private void StoreUndoState() 1237 private void StoreUndoState()
1245 { 1238 {
1246 lock (m_undo) 1239 lock(m_undo)
1247 { 1240 {
1248 if (m_undo.Count > 0) 1241 if (m_undo.Count > 0)
1249 { 1242 {
@@ -1264,21 +1257,21 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1264 1257
1265 private void InterfaceLoadFile(Object[] args) 1258 private void InterfaceLoadFile(Object[] args)
1266 { 1259 {
1267 LoadFromFile((string) args[0]); 1260 LoadFromFile((string)args[0]);
1268 } 1261 }
1269 1262
1270 private void InterfaceLoadTileFile(Object[] args) 1263 private void InterfaceLoadTileFile(Object[] args)
1271 { 1264 {
1272 LoadFromFile((string) args[0], 1265 LoadFromFile((string)args[0],
1273 (int) args[1], 1266 (int)args[1],
1274 (int) args[2], 1267 (int)args[2],
1275 (int) args[3], 1268 (int)args[3],
1276 (int) args[4]); 1269 (int)args[4]);
1277 } 1270 }
1278 1271
1279 private void InterfaceSaveFile(Object[] args) 1272 private void InterfaceSaveFile(Object[] args)
1280 { 1273 {
1281 SaveToFile((string) args[0]); 1274 SaveToFile((string)args[0]);
1282 } 1275 }
1283 1276
1284 private void InterfaceSaveTileFile(Object[] args) 1277 private void InterfaceSaveTileFile(Object[] args)
@@ -1298,8 +1291,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1298 private void InterfaceRevertTerrain(Object[] args) 1291 private void InterfaceRevertTerrain(Object[] args)
1299 { 1292 {
1300 int x, y; 1293 int x, y;
1301 for (x = 0; x < m_channel.Width; x++) 1294 for(x = 0; x < m_channel.Width; x++)
1302 for (y = 0; y < m_channel.Height; y++) 1295 for(y = 0; y < m_channel.Height; y++)
1303 m_channel[x, y] = m_revert[x, y]; 1296 m_channel[x, y] = m_revert[x, y];
1304 1297
1305 } 1298 }
@@ -1310,9 +1303,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1310 1303
1311 if (direction.ToLower().StartsWith("y")) 1304 if (direction.ToLower().StartsWith("y"))
1312 { 1305 {
1313 for (int x = 0; x < m_channel.Width; x++) 1306 for(int x = 0; x < m_channel.Width; x++)
1314 { 1307 {
1315 for (int y = 0; y < m_channel.Height / 2; y++) 1308 for(int y = 0; y < m_channel.Height / 2; y++)
1316 { 1309 {
1317 double height = m_channel[x, y]; 1310 double height = m_channel[x, y];
1318 double flippedHeight = m_channel[x, (int)m_channel.Height - 1 - y]; 1311 double flippedHeight = m_channel[x, (int)m_channel.Height - 1 - y];
@@ -1324,9 +1317,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1324 } 1317 }
1325 else if (direction.ToLower().StartsWith("x")) 1318 else if (direction.ToLower().StartsWith("x"))
1326 { 1319 {
1327 for (int y = 0; y < m_channel.Height; y++) 1320 for(int y = 0; y < m_channel.Height; y++)
1328 { 1321 {
1329 for (int x = 0; x < m_channel.Width / 2; x++) 1322 for(int x = 0; x < m_channel.Width / 2; x++)
1330 { 1323 {
1331 double height = m_channel[x, y]; 1324 double height = m_channel[x, y];
1332 double flippedHeight = m_channel[(int)m_channel.Width - 1 - x, y]; 1325 double flippedHeight = m_channel[(int)m_channel.Width - 1 - x, y];
@@ -1365,9 +1358,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1365 int width = m_channel.Width; 1358 int width = m_channel.Width;
1366 int height = m_channel.Height; 1359 int height = m_channel.Height;
1367 1360
1368 for (int x = 0; x < width; x++) 1361 for(int x = 0; x < width; x++)
1369 { 1362 {
1370 for (int y = 0; y < height; y++) 1363 for(int y = 0; y < height; y++)
1371 { 1364 {
1372 double currHeight = m_channel[x, y]; 1365 double currHeight = m_channel[x, y];
1373 if (currHeight < currMin) 1366 if (currHeight < currMin)
@@ -1388,12 +1381,12 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1388 //m_log.InfoFormat("Scale = {0}", scale); 1381 //m_log.InfoFormat("Scale = {0}", scale);
1389 1382
1390 // scale the heightmap accordingly 1383 // scale the heightmap accordingly
1391 for (int x = 0; x < width; x++) 1384 for(int x = 0; x < width; x++)
1392 { 1385 {
1393 for (int y = 0; y < height; y++) 1386 for(int y = 0; y < height; y++)
1394 { 1387 {
1395 double currHeight = m_channel[x, y] - currMin; 1388 double currHeight = m_channel[x, y] - currMin;
1396 m_channel[x, y] = desiredMin + (currHeight * scale); 1389 m_channel[x, y] = desiredMin + (currHeight * scale);
1397 } 1390 }
1398 } 1391 }
1399 1392
@@ -1404,42 +1397,42 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1404 private void InterfaceElevateTerrain(Object[] args) 1397 private void InterfaceElevateTerrain(Object[] args)
1405 { 1398 {
1406 int x, y; 1399 int x, y;
1407 for (x = 0; x < m_channel.Width; x++) 1400 for(x = 0; x < m_channel.Width; x++)
1408 for (y = 0; y < m_channel.Height; y++) 1401 for(y = 0; y < m_channel.Height; y++)
1409 m_channel[x, y] += (double) args[0]; 1402 m_channel[x, y] += (double)args[0];
1410 } 1403 }
1411 1404
1412 private void InterfaceMultiplyTerrain(Object[] args) 1405 private void InterfaceMultiplyTerrain(Object[] args)
1413 { 1406 {
1414 int x, y; 1407 int x, y;
1415 for (x = 0; x < m_channel.Width; x++) 1408 for(x = 0; x < m_channel.Width; x++)
1416 for (y = 0; y < m_channel.Height; y++) 1409 for(y = 0; y < m_channel.Height; y++)
1417 m_channel[x, y] *= (double) args[0]; 1410 m_channel[x, y] *= (double)args[0];
1418 } 1411 }
1419 1412
1420 private void InterfaceLowerTerrain(Object[] args) 1413 private void InterfaceLowerTerrain(Object[] args)
1421 { 1414 {
1422 int x, y; 1415 int x, y;
1423 for (x = 0; x < m_channel.Width; x++) 1416 for(x = 0; x < m_channel.Width; x++)
1424 for (y = 0; y < m_channel.Height; y++) 1417 for(y = 0; y < m_channel.Height; y++)
1425 m_channel[x, y] -= (double) args[0]; 1418 m_channel[x, y] -= (double)args[0];
1426 } 1419 }
1427 1420
1428 public void InterfaceFillTerrain(Object[] args) 1421 public void InterfaceFillTerrain(Object[] args)
1429 { 1422 {
1430 int x, y; 1423 int x, y;
1431 1424
1432 for (x = 0; x < m_channel.Width; x++) 1425 for(x = 0; x < m_channel.Width; x++)
1433 for (y = 0; y < m_channel.Height; y++) 1426 for(y = 0; y < m_channel.Height; y++)
1434 m_channel[x, y] = (double) args[0]; 1427 m_channel[x, y] = (double)args[0];
1435 } 1428 }
1436 1429
1437 private void InterfaceMinTerrain(Object[] args) 1430 private void InterfaceMinTerrain(Object[] args)
1438 { 1431 {
1439 int x, y; 1432 int x, y;
1440 for (x = 0; x < m_channel.Width; x++) 1433 for(x = 0; x < m_channel.Width; x++)
1441 { 1434 {
1442 for (y = 0; y < m_channel.Height; y++) 1435 for(y = 0; y < m_channel.Height; y++)
1443 { 1436 {
1444 m_channel[x, y] = Math.Max((double)args[0], m_channel[x, y]); 1437 m_channel[x, y] = Math.Max((double)args[0], m_channel[x, y]);
1445 } 1438 }
@@ -1449,9 +1442,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1449 private void InterfaceMaxTerrain(Object[] args) 1442 private void InterfaceMaxTerrain(Object[] args)
1450 { 1443 {
1451 int x, y; 1444 int x, y;
1452 for (x = 0; x < m_channel.Width; x++) 1445 for(x = 0; x < m_channel.Width; x++)
1453 { 1446 {
1454 for (y = 0; y < m_channel.Height; y++) 1447 for(y = 0; y < m_channel.Height; y++)
1455 { 1448 {
1456 m_channel[x, y] = Math.Min((double)args[0], m_channel[x, y]); 1449 m_channel[x, y] = Math.Min((double)args[0], m_channel[x, y]);
1457 } 1450 }
@@ -1480,10 +1473,10 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1480 double sum = 0; 1473 double sum = 0;
1481 1474
1482 int x; 1475 int x;
1483 for (x = 0; x < m_channel.Width; x++) 1476 for(x = 0; x < m_channel.Width; x++)
1484 { 1477 {
1485 int y; 1478 int y;
1486 for (y = 0; y < m_channel.Height; y++) 1479 for(y = 0; y < m_channel.Height; y++)
1487 { 1480 {
1488 sum += m_channel[x, y]; 1481 sum += m_channel[x, y];
1489 if (max < m_channel[x, y]) 1482 if (max < m_channel[x, y])
@@ -1501,7 +1494,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1501 1494
1502 private void InterfaceEnableExperimentalBrushes(Object[] args) 1495 private void InterfaceEnableExperimentalBrushes(Object[] args)
1503 { 1496 {
1504 if ((bool) args[0]) 1497 if ((bool)args[0])
1505 { 1498 {
1506 m_painteffects[StandardTerrainEffects.Revert] = new WeatherSphere(); 1499 m_painteffects[StandardTerrainEffects.Revert] = new WeatherSphere();
1507 m_painteffects[StandardTerrainEffects.Flatten] = new OlsenSphere(); 1500 m_painteffects[StandardTerrainEffects.Flatten] = new OlsenSphere();
@@ -1520,7 +1513,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1520 if (firstArg == "list") 1513 if (firstArg == "list")
1521 { 1514 {
1522 MainConsole.Instance.Output("List of loaded plugins"); 1515 MainConsole.Instance.Output("List of loaded plugins");
1523 foreach (KeyValuePair<string, ITerrainEffect> kvp in m_plugineffects) 1516 foreach(KeyValuePair<string, ITerrainEffect> kvp in m_plugineffects)
1524 { 1517 {
1525 MainConsole.Instance.Output(kvp.Key); 1518 MainConsole.Instance.Output(kvp.Key);
1526 } 1519 }
@@ -1665,46 +1658,56 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1665 // Add this to our scene so scripts can call these functions 1658 // Add this to our scene so scripts can call these functions
1666 m_scene.RegisterModuleCommander(m_commander); 1659 m_scene.RegisterModuleCommander(m_commander);
1667 1660
1668 // Add Feature command to Scene, since Command object requires fixed-length arglists 1661 // Add Modify command to Scene, since Command object requires fixed-length arglists
1669 m_scene.AddCommand("Terrain", this, "terrain feature", 1662 m_scene.AddCommand("Terrain", this, "terrain modify",
1670 "terrain feature <type> <parameters...>", "Constructs a feature of the requested type.", FeatureCommand); 1663 "terrain modify <operation> <value> [<area>] [<taper>]",
1664 "Modifies the terrain as instructed." +
1665 "\nEach operation can be limited to an area of effect:" +
1666 "\n * -ell=x,y,rx[,ry] constrains the operation to an ellipse centred at x,y" +
1667 "\n * -rec=x,y,dx[,dy] constrains the operation to a rectangle based at x,y" +
1668 "\nEach operation can have its effect tapered based on distance from centre:" +
1669 "\n * elliptical operations taper as cones" +
1670 "\n * rectangular operations taper as pyramids"
1671 ,
1672 ModifyCommand);
1671 1673
1672 } 1674 }
1673 1675
1674 public void FeatureCommand(string module, string[] cmd) 1676 public void ModifyCommand(string module, string[] cmd)
1675 { 1677 {
1676 string result; 1678 string result;
1677 if (cmd.Length > 2) 1679 if (cmd.Length > 2)
1678 { 1680 {
1679 string featureType = cmd[2]; 1681 string operationType = cmd[2];
1680 1682
1681 ITerrainFeature feature; 1683 ITerrainModifier operation;
1682 if (!m_featureEffects.TryGetValue(featureType, out feature)) 1684 if (!m_modifyOperations.TryGetValue(operationType, out operation))
1683 { 1685 {
1684 result = String.Format("Terrain Feature \"{0}\" not found.", featureType); 1686 result = String.Format("Terrain Modify \"{0}\" not found.", operationType);
1685 } 1687 }
1686 else if ((cmd.Length > 3) && (cmd[3] == "usage")) 1688 else if ((cmd.Length > 3) && (cmd[3] == "usage"))
1687 { 1689 {
1688 result = "Usage: " + feature.GetUsage(); 1690 result = "Usage: " + operation.GetUsage();
1689 } 1691 }
1690 else 1692 else
1691 { 1693 {
1692 result = feature.CreateFeature(m_channel, cmd); 1694 result = operation.ModifyTerrain(m_channel, cmd);
1693 } 1695 }
1694 1696
1695 if(result == String.Empty) 1697 if (result == String.Empty)
1696 { 1698 {
1697 result = "Created Feature"; 1699 result = "Modified terrain";
1698 m_log.DebugFormat("Created terrain feature {0}", featureType); 1700 m_log.DebugFormat("Performed terrain operation {0}", operationType);
1699 } 1701 }
1700 } 1702 }
1701 else 1703 else
1702 { 1704 {
1703 result = "Usage: <feature-name> <arg1> <arg2>..."; 1705 result = "Usage: <operation-name> <arg1> <arg2>...";
1704 } 1706 }
1705 MainConsole.Instance.Output(result); 1707 MainConsole.Instance.Output(result);
1706 } 1708 }
1707 #endregion 1709
1710#endregion
1708 1711
1709 } 1712 }
1710} 1713}