diff options
author | Dev Random | 2015-05-06 13:15:41 -0400 |
---|---|---|
committer | Michael Cerquoni | 2015-05-06 13:55:22 -0400 |
commit | 4bf62e11b6a99c024e3dfa42db7425ea790009ee (patch) | |
tree | ff845c62f5e354ddeb60ec02edba112ff2b5b227 /OpenSim/Region/CoreModules/World | |
parent | Attempt at fixing mantis #7054. The two inventory threads are stepping on eac... (diff) | |
download | opensim-SC-4bf62e11b6a99c024e3dfa42db7425ea790009ee.zip opensim-SC-4bf62e11b6a99c024e3dfa42db7425ea790009ee.tar.gz opensim-SC-4bf62e11b6a99c024e3dfa42db7425ea790009ee.tar.bz2 opensim-SC-4bf62e11b6a99c024e3dfa42db7425ea790009ee.tar.xz |
'terrain modify' command for area-of-effect operations
Signed-off-by: Michael Cerquoni <nebadon2025@gmail.com>
Diffstat (limited to 'OpenSim/Region/CoreModules/World')
10 files changed, 1266 insertions, 143 deletions
diff --git a/OpenSim/Region/CoreModules/World/Terrain/ITerrainModifier.cs b/OpenSim/Region/CoreModules/World/Terrain/ITerrainModifier.cs new file mode 100644 index 0000000..0e0a0e4 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Terrain/ITerrainModifier.cs | |||
@@ -0,0 +1,77 @@ | |||
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 | |||
28 | using System; | ||
29 | using OpenSim.Region.Framework.Interfaces; | ||
30 | |||
31 | namespace OpenSim.Region.CoreModules.World.Terrain | ||
32 | { | ||
33 | public interface ITerrainModifier | ||
34 | { | ||
35 | /// <summary> | ||
36 | /// Creates the feature. | ||
37 | /// </summary> | ||
38 | /// <returns> | ||
39 | /// Empty string if successful, otherwise error message. | ||
40 | /// </returns> | ||
41 | /// <param name='map'> | ||
42 | /// ITerrainChannel holding terrain data. | ||
43 | /// </param> | ||
44 | /// <param name='args'> | ||
45 | /// command-line arguments from console. | ||
46 | /// </param> | ||
47 | string ModifyTerrain(ITerrainChannel map, string[] args); | ||
48 | |||
49 | /// <summary> | ||
50 | /// Gets a string describing the usage. | ||
51 | /// </summary> | ||
52 | /// <returns> | ||
53 | /// A string describing parameters for creating the feature. | ||
54 | /// Format is "feature-name <arg1> <arg2> ..." | ||
55 | /// </returns> | ||
56 | string GetUsage(); | ||
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); | ||
74 | } | ||
75 | |||
76 | } | ||
77 | |||
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 | */ | ||
27 | using System; | ||
28 | |||
29 | using OpenSim.Region.CoreModules.World.Terrain; | ||
30 | using OpenSim.Region.Framework.Interfaces; | ||
31 | |||
32 | namespace 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 | */ | ||
27 | using System; | ||
28 | using OpenSim.Region.CoreModules.World.Terrain; | ||
29 | using OpenSim.Region.Framework.Interfaces; | ||
30 | |||
31 | namespace 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 | */ | ||
27 | using System; | ||
28 | using OpenSim.Region.CoreModules.World.Terrain; | ||
29 | using OpenSim.Region.Framework.Interfaces; | ||
30 | |||
31 | namespace 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 | */ | ||
27 | using System; | ||
28 | using OpenSim.Region.CoreModules.World.Terrain; | ||
29 | using OpenSim.Region.Framework.Interfaces; | ||
30 | |||
31 | namespace 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/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 | */ | ||
27 | using System; | ||
28 | using OpenSim.Region.CoreModules.World.Terrain; | ||
29 | using OpenSim.Region.Framework.Interfaces; | ||
30 | |||
31 | namespace 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..1731cd8 --- /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 | */ | ||
27 | using System; | ||
28 | using OpenSim.Region.CoreModules.World.Terrain; | ||
29 | using OpenSim.Region.Framework.Interfaces; | ||
30 | |||
31 | namespace 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("Scaling factor 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 | */ | ||
27 | using System; | ||
28 | using System.Reflection; | ||
29 | using log4net; | ||
30 | |||
31 | using OpenSim.Region.Framework.Interfaces; | ||
32 | |||
33 | namespace 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 @@ | |||
1 | using System; | ||
2 | |||
3 | namespace 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..02f21b9 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 | |||
28 | using System; | 27 | using System; |
29 | using System.Collections.Generic; | 28 | using System.Collections.Generic; |
30 | using System.IO; | 29 | using System.IO; |
@@ -43,6 +42,7 @@ using OpenSim.Framework.Console; | |||
43 | using OpenSim.Region.CoreModules.Framework.InterfaceCommander; | 42 | using OpenSim.Region.CoreModules.Framework.InterfaceCommander; |
44 | using OpenSim.Region.CoreModules.World.Terrain.FileLoaders; | 43 | using OpenSim.Region.CoreModules.World.Terrain.FileLoaders; |
45 | using OpenSim.Region.CoreModules.World.Terrain.Features; | 44 | using OpenSim.Region.CoreModules.World.Terrain.Features; |
45 | using OpenSim.Region.CoreModules.World.Terrain.Modifiers; | ||
46 | using OpenSim.Region.CoreModules.World.Terrain.FloodBrushes; | 46 | using OpenSim.Region.CoreModules.World.Terrain.FloodBrushes; |
47 | using OpenSim.Region.CoreModules.World.Terrain.PaintBrushes; | 47 | using OpenSim.Region.CoreModules.World.Terrain.PaintBrushes; |
48 | using OpenSim.Region.Framework.Interfaces; | 48 | using OpenSim.Region.Framework.Interfaces; |
@@ -90,26 +90,21 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
90 | #pragma warning restore 414 | 90 | #pragma warning restore 414 |
91 | 91 | ||
92 | private readonly Commander m_commander = new Commander("terrain"); | 92 | private readonly Commander m_commander = new Commander("terrain"); |
93 | |||
94 | private readonly Dictionary<StandardTerrainEffects, ITerrainFloodEffect> m_floodeffects = | 93 | private readonly Dictionary<StandardTerrainEffects, ITerrainFloodEffect> m_floodeffects = |
95 | new Dictionary<StandardTerrainEffects, ITerrainFloodEffect>(); | 94 | new Dictionary<StandardTerrainEffects, ITerrainFloodEffect>(); |
96 | |||
97 | private readonly Dictionary<string, ITerrainLoader> m_loaders = new Dictionary<string, ITerrainLoader>(); | 95 | private readonly Dictionary<string, ITerrainLoader> m_loaders = new Dictionary<string, ITerrainLoader>(); |
98 | |||
99 | private readonly Dictionary<StandardTerrainEffects, ITerrainPaintableEffect> m_painteffects = | 96 | private readonly Dictionary<StandardTerrainEffects, ITerrainPaintableEffect> m_painteffects = |
100 | new Dictionary<StandardTerrainEffects, ITerrainPaintableEffect>(); | 97 | new Dictionary<StandardTerrainEffects, ITerrainPaintableEffect>(); |
101 | |||
102 | private Dictionary<string, ITerrainEffect> m_plugineffects; | 98 | private Dictionary<string, ITerrainEffect> m_plugineffects; |
103 | |||
104 | private Dictionary<string, ITerrainFeature> m_featureEffects = | 99 | private Dictionary<string, ITerrainFeature> m_featureEffects = |
105 | new Dictionary<string, ITerrainFeature>(); | 100 | new Dictionary<string, ITerrainFeature>(); |
106 | 101 | private Dictionary<string, ITerrainModifier> m_modifyOperations = | |
102 | new Dictionary<string, ITerrainModifier>(); | ||
107 | private ITerrainChannel m_channel; | 103 | private ITerrainChannel m_channel; |
108 | private ITerrainChannel m_revert; | 104 | private ITerrainChannel m_revert; |
109 | private Scene m_scene; | 105 | private Scene m_scene; |
110 | private volatile bool m_tainted; | 106 | private volatile bool m_tainted; |
111 | private readonly Stack<LandUndoState> m_undo = new Stack<LandUndoState>(5); | 107 | private readonly Stack<LandUndoState> m_undo = new Stack<LandUndoState>(5); |
112 | |||
113 | private String m_InitialTerrain = "pinhead-island"; | 108 | private String m_InitialTerrain = "pinhead-island"; |
114 | 109 | ||
115 | // If true, send terrain patch updates to clients based on their view distance | 110 | // If true, send terrain patch updates to clients based on their view distance |
@@ -136,14 +131,17 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
136 | { | 131 | { |
137 | return (updateCount > 0); | 132 | return (updateCount > 0); |
138 | } | 133 | } |
134 | |||
139 | public void SetByXY(int x, int y, bool state) | 135 | public void SetByXY(int x, int y, bool state) |
140 | { | 136 | { |
141 | this.SetByPatch(x / Constants.TerrainPatchSize, y / Constants.TerrainPatchSize, state); | 137 | this.SetByPatch(x / Constants.TerrainPatchSize, y / Constants.TerrainPatchSize, state); |
142 | } | 138 | } |
139 | |||
143 | public bool GetByPatch(int patchX, int patchY) | 140 | public bool GetByPatch(int patchX, int patchY) |
144 | { | 141 | { |
145 | return updated[patchX, patchY]; | 142 | return updated[patchX, patchY]; |
146 | } | 143 | } |
144 | |||
147 | public void SetByPatch(int patchX, int patchY, bool state) | 145 | public void SetByPatch(int patchX, int patchY, bool state) |
148 | { | 146 | { |
149 | bool prevState = updated[patchX, patchY]; | 147 | bool prevState = updated[patchX, patchY]; |
@@ -153,11 +151,12 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
153 | updateCount--; | 151 | updateCount--; |
154 | updated[patchX, patchY] = state; | 152 | updated[patchX, patchY] = state; |
155 | } | 153 | } |
154 | |||
156 | public void SetAll(bool state) | 155 | public void SetAll(bool state) |
157 | { | 156 | { |
158 | updateCount = 0; | 157 | updateCount = 0; |
159 | for (int xx = 0; xx < updated.GetLength(0); xx++) | 158 | for(int xx = 0; xx < updated.GetLength(0); xx++) |
160 | for (int yy = 0; yy < updated.GetLength(1); yy++) | 159 | for(int yy = 0; yy < updated.GetLength(1); yy++) |
161 | updated[xx, yy] = state; | 160 | updated[xx, yy] = state; |
162 | if (state) | 161 | if (state) |
163 | updateCount = updated.GetLength(0) * updated.GetLength(1); | 162 | updateCount = updated.GetLength(0) * updated.GetLength(1); |
@@ -174,9 +173,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
174 | terrData.SizeX / Constants.TerrainPatchSize, terrData.SizeY / Constants.TerrainPatchSize) | 173 | terrData.SizeX / Constants.TerrainPatchSize, terrData.SizeY / Constants.TerrainPatchSize) |
175 | ); | 174 | ); |
176 | } | 175 | } |
177 | for (int xx = 0; xx < terrData.SizeX; xx += Constants.TerrainPatchSize) | 176 | for(int xx = 0; xx < terrData.SizeX; xx += Constants.TerrainPatchSize) |
178 | { | 177 | { |
179 | for (int yy = 0; yy < terrData.SizeY; yy += Constants.TerrainPatchSize) | 178 | for(int yy = 0; yy < terrData.SizeY; yy += Constants.TerrainPatchSize) |
180 | { | 179 | { |
181 | // Only set tainted. The patch bit may be set if the patch was to be sent later. | 180 | // Only set tainted. The patch bit may be set if the patch was to be sent later. |
182 | if (terrData.IsTaintedAt(xx, yy, false)) | 181 | if (terrData.IsTaintedAt(xx, yy, false)) |
@@ -201,8 +200,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
201 | 200 | ||
202 | #region ICommandableModule Members | 201 | #region ICommandableModule Members |
203 | 202 | ||
204 | public ICommander CommandInterface | 203 | public ICommander CommandInterface { |
205 | { | ||
206 | get { return m_commander; } | 204 | get { return m_commander; } |
207 | } | 205 | } |
208 | 206 | ||
@@ -230,7 +228,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
230 | m_scene = scene; | 228 | m_scene = scene; |
231 | 229 | ||
232 | // Install terrain module in the simulator | 230 | // Install terrain module in the simulator |
233 | lock (m_scene) | 231 | lock(m_scene) |
234 | { | 232 | { |
235 | if (m_scene.Heightmap == null) | 233 | if (m_scene.Heightmap == null) |
236 | { | 234 | { |
@@ -262,7 +260,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
262 | string supportedFilesSeparatorForTileSave = ""; | 260 | string supportedFilesSeparatorForTileSave = ""; |
263 | 261 | ||
264 | m_supportFileExtensionsForTileSave = ""; | 262 | m_supportFileExtensionsForTileSave = ""; |
265 | foreach (KeyValuePair<string, ITerrainLoader> loader in m_loaders) | 263 | foreach(KeyValuePair<string, ITerrainLoader> loader in m_loaders) |
266 | { | 264 | { |
267 | m_supportedFileExtensions += supportedFilesSeparator + loader.Key + " (" + loader.Value + ")"; | 265 | m_supportedFileExtensions += supportedFilesSeparator + loader.Key + " (" + loader.Value + ")"; |
268 | supportedFilesSeparator = ", "; | 266 | supportedFilesSeparator = ", "; |
@@ -285,7 +283,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
285 | 283 | ||
286 | public void RemoveRegion(Scene scene) | 284 | public void RemoveRegion(Scene scene) |
287 | { | 285 | { |
288 | lock (m_scene) | 286 | lock(m_scene) |
289 | { | 287 | { |
290 | // remove the commands | 288 | // remove the commands |
291 | m_scene.UnregisterModuleCommander(m_commander.Name); | 289 | m_scene.UnregisterModuleCommander(m_commander.Name); |
@@ -304,13 +302,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
304 | { | 302 | { |
305 | } | 303 | } |
306 | 304 | ||
307 | public Type ReplaceableInterface | 305 | public Type ReplaceableInterface { |
308 | { | ||
309 | get { return null; } | 306 | get { return null; } |
310 | } | 307 | } |
311 | 308 | ||
312 | public string Name | 309 | public string Name { |
313 | { | ||
314 | get { return "TerrainModule"; } | 310 | get { return "TerrainModule"; } |
315 | } | 311 | } |
316 | 312 | ||
@@ -329,11 +325,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
329 | /// <param name="filename">Filename to terrain file. Type is determined by extension.</param> | 325 | /// <param name="filename">Filename to terrain file. Type is determined by extension.</param> |
330 | public void LoadFromFile(string filename) | 326 | public void LoadFromFile(string filename) |
331 | { | 327 | { |
332 | foreach (KeyValuePair<string, ITerrainLoader> loader in m_loaders) | 328 | foreach(KeyValuePair<string, ITerrainLoader> loader in m_loaders) |
333 | { | 329 | { |
334 | if (filename.EndsWith(loader.Key)) | 330 | if (filename.EndsWith(loader.Key)) |
335 | { | 331 | { |
336 | lock (m_scene) | 332 | lock(m_scene) |
337 | { | 333 | { |
338 | try | 334 | try |
339 | { | 335 | { |
@@ -349,20 +345,20 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
349 | m_channel = channel; | 345 | m_channel = channel; |
350 | UpdateRevertMap(); | 346 | UpdateRevertMap(); |
351 | } | 347 | } |
352 | catch (NotImplementedException) | 348 | catch(NotImplementedException) |
353 | { | 349 | { |
354 | m_log.Error("[TERRAIN]: Unable to load heightmap, the " + loader.Value + | 350 | m_log.Error("[TERRAIN]: Unable to load heightmap, the " + loader.Value + |
355 | " parser does not support file loading. (May be save only)"); | 351 | " 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)); | 352 | throw new TerrainException(String.Format("unable to load heightmap: parser {0} does not support loading", loader.Value)); |
357 | } | 353 | } |
358 | catch (FileNotFoundException) | 354 | catch(FileNotFoundException) |
359 | { | 355 | { |
360 | m_log.Error( | 356 | m_log.Error( |
361 | "[TERRAIN]: Unable to load heightmap, file not found. (A directory permissions error may also cause this)"); | 357 | "[TERRAIN]: Unable to load heightmap, file not found. (A directory permissions error may also cause this)"); |
362 | throw new TerrainException( | 358 | throw new TerrainException( |
363 | String.Format("unable to load heightmap: file {0} not found (or permissions do not allow access", filename)); | 359 | String.Format("unable to load heightmap: file {0} not found (or permissions do not allow access", filename)); |
364 | } | 360 | } |
365 | catch (ArgumentException e) | 361 | catch(ArgumentException e) |
366 | { | 362 | { |
367 | m_log.ErrorFormat("[TERRAIN]: Unable to load heightmap: {0}", e.Message); | 363 | m_log.ErrorFormat("[TERRAIN]: Unable to load heightmap: {0}", e.Message); |
368 | throw new TerrainException( | 364 | throw new TerrainException( |
@@ -386,7 +382,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
386 | { | 382 | { |
387 | try | 383 | try |
388 | { | 384 | { |
389 | foreach (KeyValuePair<string, ITerrainLoader> loader in m_loaders) | 385 | foreach(KeyValuePair<string, ITerrainLoader> loader in m_loaders) |
390 | { | 386 | { |
391 | if (filename.EndsWith(loader.Key)) | 387 | if (filename.EndsWith(loader.Key)) |
392 | { | 388 | { |
@@ -396,7 +392,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
396 | } | 392 | } |
397 | } | 393 | } |
398 | } | 394 | } |
399 | catch (IOException ioe) | 395 | catch(IOException ioe) |
400 | { | 396 | { |
401 | m_log.Error(String.Format("[TERRAIN]: Unable to save to {0}, {1}", filename, ioe.Message)); | 397 | m_log.Error(String.Format("[TERRAIN]: Unable to save to {0}, {1}", filename, ioe.Message)); |
402 | } | 398 | } |
@@ -429,11 +425,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
429 | public void LoadFromStream(string filename, Vector3 displacement, | 425 | public void LoadFromStream(string filename, Vector3 displacement, |
430 | float radianRotation, Vector2 rotationDisplacement, Stream stream) | 426 | float radianRotation, Vector2 rotationDisplacement, Stream stream) |
431 | { | 427 | { |
432 | foreach (KeyValuePair<string, ITerrainLoader> loader in m_loaders) | 428 | foreach(KeyValuePair<string, ITerrainLoader> loader in m_loaders) |
433 | { | 429 | { |
434 | if (filename.EndsWith(loader.Key)) | 430 | if (filename.EndsWith(loader.Key)) |
435 | { | 431 | { |
436 | lock (m_scene) | 432 | lock(m_scene) |
437 | { | 433 | { |
438 | try | 434 | try |
439 | { | 435 | { |
@@ -441,7 +437,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
441 | m_channel.Merge(channel, displacement, radianRotation, rotationDisplacement); | 437 | m_channel.Merge(channel, displacement, radianRotation, rotationDisplacement); |
442 | UpdateRevertMap(); | 438 | UpdateRevertMap(); |
443 | } | 439 | } |
444 | catch (NotImplementedException) | 440 | catch(NotImplementedException) |
445 | { | 441 | { |
446 | m_log.Error("[TERRAIN]: Unable to load heightmap, the " + loader.Value + | 442 | m_log.Error("[TERRAIN]: Unable to load heightmap, the " + loader.Value + |
447 | " parser does not support file loading. (May be save only)"); | 443 | " parser does not support file loading. (May be save only)"); |
@@ -501,7 +497,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
501 | { | 497 | { |
502 | try | 498 | try |
503 | { | 499 | { |
504 | foreach (KeyValuePair<string, ITerrainLoader> loader in m_loaders) | 500 | foreach(KeyValuePair<string, ITerrainLoader> loader in m_loaders) |
505 | { | 501 | { |
506 | if (filename.EndsWith(loader.Key)) | 502 | if (filename.EndsWith(loader.Key)) |
507 | { | 503 | { |
@@ -510,7 +506,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
510 | } | 506 | } |
511 | } | 507 | } |
512 | } | 508 | } |
513 | catch (NotImplementedException) | 509 | catch(NotImplementedException) |
514 | { | 510 | { |
515 | m_log.Error("Unable to save to " + filename + ", saving of this file format has not been implemented."); | 511 | 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")); | 512 | throw new TerrainException(String.Format("Unable to save heightmap: saving of this file format not implemented")); |
@@ -519,12 +515,12 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
519 | 515 | ||
520 | // Someone diddled terrain outside the normal code paths. Set the taintedness for all clients. | 516 | // Someone diddled terrain outside the normal code paths. Set the taintedness for all clients. |
521 | // ITerrainModule.TaintTerrain() | 517 | // ITerrainModule.TaintTerrain() |
522 | public void TaintTerrain () | 518 | public void TaintTerrain() |
523 | { | 519 | { |
524 | lock (m_perClientPatchUpdates) | 520 | lock(m_perClientPatchUpdates) |
525 | { | 521 | { |
526 | // Set the flags for all clients so the tainted patches will be sent out | 522 | // Set the flags for all clients so the tainted patches will be sent out |
527 | foreach (PatchUpdates pups in m_perClientPatchUpdates.Values) | 523 | foreach(PatchUpdates pups in m_perClientPatchUpdates.Values) |
528 | { | 524 | { |
529 | pups.SetAll(m_scene.Heightmap.GetTerrainData()); | 525 | pups.SetAll(m_scene.Heightmap.GetTerrainData()); |
530 | } | 526 | } |
@@ -539,7 +535,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
539 | ScenePresence presence = m_scene.GetScenePresence(pClient.AgentId); | 535 | ScenePresence presence = m_scene.GetScenePresence(pClient.AgentId); |
540 | if (presence != null) | 536 | if (presence != null) |
541 | { | 537 | { |
542 | lock (m_perClientPatchUpdates) | 538 | lock(m_perClientPatchUpdates) |
543 | { | 539 | { |
544 | PatchUpdates pups; | 540 | PatchUpdates pups; |
545 | if (!m_perClientPatchUpdates.TryGetValue(pClient.AgentId, out pups)) | 541 | if (!m_perClientPatchUpdates.TryGetValue(pClient.AgentId, out pups)) |
@@ -572,7 +568,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
572 | return; | 568 | return; |
573 | 569 | ||
574 | string[] files = Directory.GetFiles(plugineffectsPath); | 570 | string[] files = Directory.GetFiles(plugineffectsPath); |
575 | foreach (string file in files) | 571 | foreach(string file in files) |
576 | { | 572 | { |
577 | m_log.Info("Loading effects in " + file); | 573 | m_log.Info("Loading effects in " + file); |
578 | try | 574 | try |
@@ -580,7 +576,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
580 | Assembly library = Assembly.LoadFrom(file); | 576 | Assembly library = Assembly.LoadFrom(file); |
581 | LoadPlugins(library); | 577 | LoadPlugins(library); |
582 | } | 578 | } |
583 | catch (BadImageFormatException) | 579 | catch(BadImageFormatException) |
584 | { | 580 | { |
585 | } | 581 | } |
586 | } | 582 | } |
@@ -588,7 +584,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
588 | 584 | ||
589 | private void LoadPlugins(Assembly library) | 585 | private void LoadPlugins(Assembly library) |
590 | { | 586 | { |
591 | foreach (Type pluginType in library.GetTypes()) | 587 | foreach(Type pluginType in library.GetTypes()) |
592 | { | 588 | { |
593 | try | 589 | try |
594 | { | 590 | { |
@@ -610,7 +606,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
610 | m_log.Info("L ... " + typeName); | 606 | m_log.Info("L ... " + typeName); |
611 | } | 607 | } |
612 | } | 608 | } |
613 | catch (AmbiguousMatchException) | 609 | catch(AmbiguousMatchException) |
614 | { | 610 | { |
615 | } | 611 | } |
616 | } | 612 | } |
@@ -618,7 +614,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
618 | 614 | ||
619 | public void InstallPlugin(string pluginName, ITerrainEffect effect) | 615 | public void InstallPlugin(string pluginName, ITerrainEffect effect) |
620 | { | 616 | { |
621 | lock (m_plugineffects) | 617 | lock(m_plugineffects) |
622 | { | 618 | { |
623 | if (!m_plugineffects.ContainsKey(pluginName)) | 619 | if (!m_plugineffects.ContainsKey(pluginName)) |
624 | { | 620 | { |
@@ -664,6 +660,14 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
664 | // Terrain Feature effects | 660 | // Terrain Feature effects |
665 | m_featureEffects["rectangle"] = new RectangleFeature(this); | 661 | m_featureEffects["rectangle"] = new RectangleFeature(this); |
666 | 662 | ||
663 | // Terrain Modifier operations | ||
664 | m_modifyOperations["min"] = new MinModifier(this); | ||
665 | m_modifyOperations["max"] = new MaxModifier(this); | ||
666 | m_modifyOperations["raise"] = new RaiseModifier(this); | ||
667 | m_modifyOperations["lower"] = new LowerModifier(this); | ||
668 | m_modifyOperations["fill"] = new FillModifier(this); | ||
669 | m_modifyOperations["smooth"] = new SmoothModifier(this); | ||
670 | |||
667 | // Filesystem load/save loaders | 671 | // Filesystem load/save loaders |
668 | m_loaders[".r32"] = new RAW32(); | 672 | m_loaders[".r32"] = new RAW32(); |
669 | m_loaders[".f32"] = m_loaders[".r32"]; | 673 | m_loaders[".f32"] = m_loaders[".r32"]; |
@@ -707,22 +711,22 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
707 | /// <param name="fileStartY">Where to begin our slice</param> | 711 | /// <param name="fileStartY">Where to begin our slice</param> |
708 | public void LoadFromFile(string filename, int fileWidth, int fileHeight, int fileStartX, int fileStartY) | 712 | public void LoadFromFile(string filename, int fileWidth, int fileHeight, int fileStartX, int fileStartY) |
709 | { | 713 | { |
710 | int offsetX = (int) m_scene.RegionInfo.RegionLocX - fileStartX; | 714 | int offsetX = (int)m_scene.RegionInfo.RegionLocX - fileStartX; |
711 | int offsetY = (int) m_scene.RegionInfo.RegionLocY - fileStartY; | 715 | int offsetY = (int)m_scene.RegionInfo.RegionLocY - fileStartY; |
712 | 716 | ||
713 | if (offsetX >= 0 && offsetX < fileWidth && offsetY >= 0 && offsetY < fileHeight) | 717 | if (offsetX >= 0 && offsetX < fileWidth && offsetY >= 0 && offsetY < fileHeight) |
714 | { | 718 | { |
715 | // this region is included in the tile request | 719 | // this region is included in the tile request |
716 | foreach (KeyValuePair<string, ITerrainLoader> loader in m_loaders) | 720 | foreach(KeyValuePair<string, ITerrainLoader> loader in m_loaders) |
717 | { | 721 | { |
718 | if (filename.EndsWith(loader.Key)) | 722 | if (filename.EndsWith(loader.Key)) |
719 | { | 723 | { |
720 | lock (m_scene) | 724 | lock(m_scene) |
721 | { | 725 | { |
722 | ITerrainChannel channel = loader.Value.LoadFile(filename, offsetX, offsetY, | 726 | ITerrainChannel channel = loader.Value.LoadFile(filename, offsetX, offsetY, |
723 | fileWidth, fileHeight, | 727 | fileWidth, fileHeight, |
724 | (int) m_scene.RegionInfo.RegionSizeX, | 728 | (int)m_scene.RegionInfo.RegionSizeX, |
725 | (int) m_scene.RegionInfo.RegionSizeY); | 729 | (int)m_scene.RegionInfo.RegionSizeY); |
726 | m_scene.Heightmap = channel; | 730 | m_scene.Heightmap = channel; |
727 | m_channel = channel; | 731 | m_channel = channel; |
728 | UpdateRevertMap(); | 732 | UpdateRevertMap(); |
@@ -761,11 +765,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
761 | } | 765 | } |
762 | 766 | ||
763 | // this region is included in the tile request | 767 | // this region is included in the tile request |
764 | foreach (KeyValuePair<string, ITerrainLoader> loader in m_loaders) | 768 | foreach(KeyValuePair<string, ITerrainLoader> loader in m_loaders) |
765 | { | 769 | { |
766 | if (filename.EndsWith(loader.Key) && loader.Value.SupportsTileSave()) | 770 | if (filename.EndsWith(loader.Key) && loader.Value.SupportsTileSave()) |
767 | { | 771 | { |
768 | lock (m_scene) | 772 | lock(m_scene) |
769 | { | 773 | { |
770 | loader.Value.SaveFile(m_channel, filename, offsetX, offsetY, | 774 | loader.Value.SaveFile(m_channel, filename, offsetX, offsetY, |
771 | fileWidth, fileHeight, | 775 | fileWidth, fileHeight, |
@@ -799,9 +803,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
799 | TerrainData terrData = m_channel.GetTerrainData(); | 803 | TerrainData terrData = m_channel.GetTerrainData(); |
800 | 804 | ||
801 | bool shouldTaint = false; | 805 | bool shouldTaint = false; |
802 | for (int x = 0; x < terrData.SizeX; x += Constants.TerrainPatchSize) | 806 | for(int x = 0; x < terrData.SizeX; x += Constants.TerrainPatchSize) |
803 | { | 807 | { |
804 | for (int y = 0; y < terrData.SizeY; y += Constants.TerrainPatchSize) | 808 | for(int y = 0; y < terrData.SizeY; y += Constants.TerrainPatchSize) |
805 | { | 809 | { |
806 | if (terrData.IsTaintedAt(x, y)) | 810 | if (terrData.IsTaintedAt(x, y)) |
807 | { | 811 | { |
@@ -856,7 +860,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
856 | 860 | ||
857 | string[] tmpArgs = new string[args.Length - 2]; | 861 | string[] tmpArgs = new string[args.Length - 2]; |
858 | int i; | 862 | int i; |
859 | for (i = 2; i < args.Length; i++) | 863 | for(i = 2; i < args.Length; i++) |
860 | tmpArgs[i - 2] = args[i]; | 864 | tmpArgs[i - 2] = args[i]; |
861 | 865 | ||
862 | m_commander.ProcessConsoleCommand(args[1], tmpArgs); | 866 | m_commander.ProcessConsoleCommand(args[1], tmpArgs); |
@@ -890,7 +894,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
890 | presence.ControllingClient.OnUnackedTerrain -= client_OnUnackedTerrain; | 894 | presence.ControllingClient.OnUnackedTerrain -= client_OnUnackedTerrain; |
891 | } | 895 | } |
892 | 896 | ||
893 | lock (m_perClientPatchUpdates) | 897 | lock(m_perClientPatchUpdates) |
894 | m_perClientPatchUpdates.Remove(client); | 898 | m_perClientPatchUpdates.Remove(client); |
895 | } | 899 | } |
896 | 900 | ||
@@ -904,12 +908,12 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
904 | TerrainData terrData = m_channel.GetTerrainData(); | 908 | TerrainData terrData = m_channel.GetTerrainData(); |
905 | 909 | ||
906 | bool wasLimited = false; | 910 | bool wasLimited = false; |
907 | for (int x = 0; x < terrData.SizeX; x += Constants.TerrainPatchSize) | 911 | for(int x = 0; x < terrData.SizeX; x += Constants.TerrainPatchSize) |
908 | { | 912 | { |
909 | for (int y = 0; y < terrData.SizeY; y += Constants.TerrainPatchSize) | 913 | for(int y = 0; y < terrData.SizeY; y += Constants.TerrainPatchSize) |
910 | { | 914 | { |
911 | if (terrData.IsTaintedAt(x, y, false /* clearOnTest */)) | 915 | if (terrData.IsTaintedAt(x, y, false /* clearOnTest */)) |
912 | { | 916 | { |
913 | // If we should respect the estate settings then | 917 | // If we should respect the estate settings then |
914 | // fixup and height deltas that don't respect them. | 918 | // fixup and height deltas that don't respect them. |
915 | // Note that LimitChannelChanges() modifies the TerrainChannel with the limited height values. | 919 | // Note that LimitChannelChanges() modifies the TerrainChannel with the limited height values. |
@@ -933,9 +937,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
933 | 937 | ||
934 | // loop through the height map for this patch and compare it against | 938 | // loop through the height map for this patch and compare it against |
935 | // the revert map | 939 | // the revert map |
936 | for (int x = xStart; x < xStart + Constants.TerrainPatchSize; x++) | 940 | for(int x = xStart; x < xStart + Constants.TerrainPatchSize; x++) |
937 | { | 941 | { |
938 | for (int y = yStart; y < yStart + Constants.TerrainPatchSize; y++) | 942 | for(int y = yStart; y < yStart + Constants.TerrainPatchSize; y++) |
939 | { | 943 | { |
940 | float requestedHeight = terrData[x, y]; | 944 | float requestedHeight = terrData[x, y]; |
941 | float bakedHeight = (float)m_revert[x, y]; | 945 | float bakedHeight = (float)m_revert[x, y]; |
@@ -959,7 +963,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
959 | 963 | ||
960 | private void client_OnLandUndo(IClientAPI client) | 964 | private void client_OnLandUndo(IClientAPI client) |
961 | { | 965 | { |
962 | lock (m_undo) | 966 | lock(m_undo) |
963 | { | 967 | { |
964 | if (m_undo.Count > 0) | 968 | if (m_undo.Count > 0) |
965 | { | 969 | { |
@@ -981,19 +985,19 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
981 | if (m_sendTerrainUpdatesByViewDistance) | 985 | if (m_sendTerrainUpdatesByViewDistance) |
982 | { | 986 | { |
983 | // Add that this patch needs to be sent to the accounting for each client. | 987 | // Add that this patch needs to be sent to the accounting for each client. |
984 | lock (m_perClientPatchUpdates) | 988 | lock(m_perClientPatchUpdates) |
985 | { | 989 | { |
986 | m_scene.ForEachScenePresence(presence => | 990 | m_scene.ForEachScenePresence(presence => |
991 | { | ||
992 | PatchUpdates thisClientUpdates; | ||
993 | if (!m_perClientPatchUpdates.TryGetValue(presence.UUID, out thisClientUpdates)) | ||
987 | { | 994 | { |
988 | PatchUpdates thisClientUpdates; | 995 | // There is a ScenePresence without a send patch map. Create one. |
989 | if (!m_perClientPatchUpdates.TryGetValue(presence.UUID, out thisClientUpdates)) | 996 | thisClientUpdates = new PatchUpdates(terrData, presence); |
990 | { | 997 | 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 | } | 998 | } |
999 | thisClientUpdates.SetByXY(x, y, true); | ||
1000 | } | ||
997 | ); | 1001 | ); |
998 | } | 1002 | } |
999 | } | 1003 | } |
@@ -1005,11 +1009,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
1005 | float[] heightMap = new float[10]; | 1009 | float[] heightMap = new float[10]; |
1006 | m_scene.ForEachClient( | 1010 | m_scene.ForEachClient( |
1007 | delegate(IClientAPI controller) | 1011 | delegate(IClientAPI controller) |
1008 | { | 1012 | { |
1009 | controller.SendLayerData(x / Constants.TerrainPatchSize, | 1013 | controller.SendLayerData(x / Constants.TerrainPatchSize, |
1010 | y / Constants.TerrainPatchSize, | 1014 | y / Constants.TerrainPatchSize, |
1011 | heightMap); | 1015 | heightMap); |
1012 | } | 1016 | } |
1013 | ); | 1017 | ); |
1014 | } | 1018 | } |
1015 | } | 1019 | } |
@@ -1019,12 +1023,14 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
1019 | public int PatchX; | 1023 | public int PatchX; |
1020 | public int PatchY; | 1024 | public int PatchY; |
1021 | public float Dist; | 1025 | public float Dist; |
1026 | |||
1022 | public PatchesToSend(int pX, int pY, float pDist) | 1027 | public PatchesToSend(int pX, int pY, float pDist) |
1023 | { | 1028 | { |
1024 | PatchX = pX; | 1029 | PatchX = pX; |
1025 | PatchY = pY; | 1030 | PatchY = pY; |
1026 | Dist = pDist; | 1031 | Dist = pDist; |
1027 | } | 1032 | } |
1033 | |||
1028 | public int CompareTo(PatchesToSend other) | 1034 | public int CompareTo(PatchesToSend other) |
1029 | { | 1035 | { |
1030 | return Dist.CompareTo(other.Dist); | 1036 | return Dist.CompareTo(other.Dist); |
@@ -1036,9 +1042,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
1036 | // Loop through all the per-client info and send any patches necessary. | 1042 | // Loop through all the per-client info and send any patches necessary. |
1037 | private void CheckSendingPatchesToClients() | 1043 | private void CheckSendingPatchesToClients() |
1038 | { | 1044 | { |
1039 | lock (m_perClientPatchUpdates) | 1045 | lock(m_perClientPatchUpdates) |
1040 | { | 1046 | { |
1041 | foreach (PatchUpdates pups in m_perClientPatchUpdates.Values) | 1047 | foreach(PatchUpdates pups in m_perClientPatchUpdates.Values) |
1042 | { | 1048 | { |
1043 | if (pups.HasUpdates()) | 1049 | if (pups.HasUpdates()) |
1044 | { | 1050 | { |
@@ -1062,7 +1068,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
1062 | int[] yPieces = new int[toSend.Count]; | 1068 | int[] yPieces = new int[toSend.Count]; |
1063 | float[] patchPieces = new float[toSend.Count * 2]; | 1069 | float[] patchPieces = new float[toSend.Count * 2]; |
1064 | int pieceIndex = 0; | 1070 | int pieceIndex = 0; |
1065 | foreach (PatchesToSend pts in toSend) | 1071 | foreach(PatchesToSend pts in toSend) |
1066 | { | 1072 | { |
1067 | patchPieces[pieceIndex++] = pts.PatchX; | 1073 | patchPieces[pieceIndex++] = pts.PatchX; |
1068 | patchPieces[pieceIndex++] = pts.PatchY; | 1074 | patchPieces[pieceIndex++] = pts.PatchY; |
@@ -1083,25 +1089,25 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
1083 | return ret; | 1089 | return ret; |
1084 | 1090 | ||
1085 | // Compute the area of patches within our draw distance | 1091 | // Compute the area of patches within our draw distance |
1086 | int startX = (((int) (presence.AbsolutePosition.X - presence.DrawDistance))/Constants.TerrainPatchSize) - 2; | 1092 | int startX = (((int)(presence.AbsolutePosition.X - presence.DrawDistance)) / Constants.TerrainPatchSize) - 2; |
1087 | startX = Math.Max(startX, 0); | 1093 | startX = Math.Max(startX, 0); |
1088 | startX = Math.Min(startX, (int)m_scene.RegionInfo.RegionSizeX/Constants.TerrainPatchSize); | 1094 | startX = Math.Min(startX, (int)m_scene.RegionInfo.RegionSizeX / Constants.TerrainPatchSize); |
1089 | int startY = (((int) (presence.AbsolutePosition.Y - presence.DrawDistance))/Constants.TerrainPatchSize) - 2; | 1095 | int startY = (((int)(presence.AbsolutePosition.Y - presence.DrawDistance)) / Constants.TerrainPatchSize) - 2; |
1090 | startY = Math.Max(startY, 0); | 1096 | startY = Math.Max(startY, 0); |
1091 | startY = Math.Min(startY, (int)m_scene.RegionInfo.RegionSizeY/Constants.TerrainPatchSize); | 1097 | startY = Math.Min(startY, (int)m_scene.RegionInfo.RegionSizeY / Constants.TerrainPatchSize); |
1092 | int endX = (((int) (presence.AbsolutePosition.X + presence.DrawDistance))/Constants.TerrainPatchSize) + 2; | 1098 | int endX = (((int)(presence.AbsolutePosition.X + presence.DrawDistance)) / Constants.TerrainPatchSize) + 2; |
1093 | endX = Math.Max(endX, 0); | 1099 | endX = Math.Max(endX, 0); |
1094 | endX = Math.Min(endX, (int)m_scene.RegionInfo.RegionSizeX/Constants.TerrainPatchSize); | 1100 | endX = Math.Min(endX, (int)m_scene.RegionInfo.RegionSizeX / Constants.TerrainPatchSize); |
1095 | int endY = (((int) (presence.AbsolutePosition.Y + presence.DrawDistance))/Constants.TerrainPatchSize) + 2; | 1101 | int endY = (((int)(presence.AbsolutePosition.Y + presence.DrawDistance)) / Constants.TerrainPatchSize) + 2; |
1096 | endY = Math.Max(endY, 0); | 1102 | endY = Math.Max(endY, 0); |
1097 | endY = Math.Min(endY, (int)m_scene.RegionInfo.RegionSizeY/Constants.TerrainPatchSize); | 1103 | 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}>", | 1104 | // m_log.DebugFormat("{0} GetModifiedPatchesInViewDistance. rName={1}, ddist={2}, apos={3}, start=<{4},{5}>, end=<{6},{7}>", |
1099 | // LogHeader, m_scene.RegionInfo.RegionName, | 1105 | // LogHeader, m_scene.RegionInfo.RegionName, |
1100 | // presence.DrawDistance, presence.AbsolutePosition, | 1106 | // presence.DrawDistance, presence.AbsolutePosition, |
1101 | // startX, startY, endX, endY); | 1107 | // startX, startY, endX, endY); |
1102 | for (int x = startX; x < endX; x++) | 1108 | for(int x = startX; x < endX; x++) |
1103 | { | 1109 | { |
1104 | for (int y = startY; y < endY; y++) | 1110 | for(int y = startY; y < endY; y++) |
1105 | { | 1111 | { |
1106 | //Need to make sure we don't send the same ones over and over | 1112 | //Need to make sure we don't send the same ones over and over |
1107 | Vector3 presencePos = presence.AbsolutePosition; | 1113 | Vector3 presencePos = presence.AbsolutePosition; |
@@ -1133,28 +1139,28 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
1133 | bool allowed = false; | 1139 | bool allowed = false; |
1134 | if (north == south && east == west) | 1140 | if (north == south && east == west) |
1135 | { | 1141 | { |
1136 | if (m_painteffects.ContainsKey((StandardTerrainEffects) action)) | 1142 | if (m_painteffects.ContainsKey((StandardTerrainEffects)action)) |
1137 | { | 1143 | { |
1138 | bool[,] allowMask = new bool[m_channel.Width,m_channel.Height]; | 1144 | bool[,] allowMask = new bool[m_channel.Width, m_channel.Height]; |
1139 | allowMask.Initialize(); | 1145 | allowMask.Initialize(); |
1140 | int n = size + 1; | 1146 | int n = size + 1; |
1141 | if (n > 2) | 1147 | if (n > 2) |
1142 | n = 4; | 1148 | n = 4; |
1143 | 1149 | ||
1144 | int zx = (int) (west + 0.5); | 1150 | int zx = (int)(west + 0.5); |
1145 | int zy = (int) (north + 0.5); | 1151 | int zy = (int)(north + 0.5); |
1146 | 1152 | ||
1147 | int dx; | 1153 | int dx; |
1148 | for (dx=-n; dx<=n; dx++) | 1154 | for(dx=-n; dx<=n; dx++) |
1149 | { | 1155 | { |
1150 | int dy; | 1156 | int dy; |
1151 | for (dy=-n; dy<=n; dy++) | 1157 | for(dy=-n; dy<=n; dy++) |
1152 | { | 1158 | { |
1153 | int x = zx + dx; | 1159 | int x = zx + dx; |
1154 | int y = zy + dy; | 1160 | int y = zy + dy; |
1155 | if (x>=0 && y>=0 && x<m_channel.Width && y<m_channel.Height) | 1161 | if (x >= 0 && y >= 0 && x < m_channel.Width && y < m_channel.Height) |
1156 | { | 1162 | { |
1157 | if (m_scene.Permissions.CanTerraformLand(agentId, new Vector3(x,y,0))) | 1163 | if (m_scene.Permissions.CanTerraformLand(agentId, new Vector3(x, y, 0))) |
1158 | { | 1164 | { |
1159 | allowMask[x, y] = true; | 1165 | allowMask[x, y] = true; |
1160 | allowed = true; | 1166 | allowed = true; |
@@ -1165,7 +1171,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
1165 | if (allowed) | 1171 | if (allowed) |
1166 | { | 1172 | { |
1167 | StoreUndoState(); | 1173 | StoreUndoState(); |
1168 | m_painteffects[(StandardTerrainEffects) action].PaintEffect( | 1174 | m_painteffects[(StandardTerrainEffects)action].PaintEffect( |
1169 | m_channel, allowMask, west, south, height, size, seconds); | 1175 | m_channel, allowMask, west, south, height, size, seconds); |
1170 | 1176 | ||
1171 | //revert changes outside estate limits | 1177 | //revert changes outside estate limits |
@@ -1180,22 +1186,22 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
1180 | } | 1186 | } |
1181 | else | 1187 | else |
1182 | { | 1188 | { |
1183 | if (m_floodeffects.ContainsKey((StandardTerrainEffects) action)) | 1189 | if (m_floodeffects.ContainsKey((StandardTerrainEffects)action)) |
1184 | { | 1190 | { |
1185 | bool[,] fillArea = new bool[m_channel.Width,m_channel.Height]; | 1191 | bool[,] fillArea = new bool[m_channel.Width, m_channel.Height]; |
1186 | fillArea.Initialize(); | 1192 | fillArea.Initialize(); |
1187 | 1193 | ||
1188 | int x; | 1194 | int x; |
1189 | for (x = 0; x < m_channel.Width; x++) | 1195 | for(x = 0; x < m_channel.Width; x++) |
1190 | { | 1196 | { |
1191 | int y; | 1197 | int y; |
1192 | for (y = 0; y < m_channel.Height; y++) | 1198 | for(y = 0; y < m_channel.Height; y++) |
1193 | { | 1199 | { |
1194 | if (x < east && x > west) | 1200 | if (x < east && x > west) |
1195 | { | 1201 | { |
1196 | if (y < north && y > south) | 1202 | if (y < north && y > south) |
1197 | { | 1203 | { |
1198 | if (m_scene.Permissions.CanTerraformLand(agentId, new Vector3(x,y,0))) | 1204 | if (m_scene.Permissions.CanTerraformLand(agentId, new Vector3(x, y, 0))) |
1199 | { | 1205 | { |
1200 | fillArea[x, y] = true; | 1206 | fillArea[x, y] = true; |
1201 | allowed = true; | 1207 | allowed = true; |
@@ -1208,7 +1214,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
1208 | if (allowed) | 1214 | if (allowed) |
1209 | { | 1215 | { |
1210 | StoreUndoState(); | 1216 | StoreUndoState(); |
1211 | m_floodeffects[(StandardTerrainEffects) action].FloodEffect(m_channel, fillArea, size); | 1217 | m_floodeffects[(StandardTerrainEffects)action].FloodEffect(m_channel, fillArea, size); |
1212 | 1218 | ||
1213 | //revert changes outside estate limits | 1219 | //revert changes outside estate limits |
1214 | if (!god) | 1220 | if (!god) |
@@ -1243,7 +1249,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
1243 | 1249 | ||
1244 | private void StoreUndoState() | 1250 | private void StoreUndoState() |
1245 | { | 1251 | { |
1246 | lock (m_undo) | 1252 | lock(m_undo) |
1247 | { | 1253 | { |
1248 | if (m_undo.Count > 0) | 1254 | if (m_undo.Count > 0) |
1249 | { | 1255 | { |
@@ -1264,21 +1270,21 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
1264 | 1270 | ||
1265 | private void InterfaceLoadFile(Object[] args) | 1271 | private void InterfaceLoadFile(Object[] args) |
1266 | { | 1272 | { |
1267 | LoadFromFile((string) args[0]); | 1273 | LoadFromFile((string)args[0]); |
1268 | } | 1274 | } |
1269 | 1275 | ||
1270 | private void InterfaceLoadTileFile(Object[] args) | 1276 | private void InterfaceLoadTileFile(Object[] args) |
1271 | { | 1277 | { |
1272 | LoadFromFile((string) args[0], | 1278 | LoadFromFile((string)args[0], |
1273 | (int) args[1], | 1279 | (int)args[1], |
1274 | (int) args[2], | 1280 | (int)args[2], |
1275 | (int) args[3], | 1281 | (int)args[3], |
1276 | (int) args[4]); | 1282 | (int)args[4]); |
1277 | } | 1283 | } |
1278 | 1284 | ||
1279 | private void InterfaceSaveFile(Object[] args) | 1285 | private void InterfaceSaveFile(Object[] args) |
1280 | { | 1286 | { |
1281 | SaveToFile((string) args[0]); | 1287 | SaveToFile((string)args[0]); |
1282 | } | 1288 | } |
1283 | 1289 | ||
1284 | private void InterfaceSaveTileFile(Object[] args) | 1290 | private void InterfaceSaveTileFile(Object[] args) |
@@ -1298,8 +1304,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
1298 | private void InterfaceRevertTerrain(Object[] args) | 1304 | private void InterfaceRevertTerrain(Object[] args) |
1299 | { | 1305 | { |
1300 | int x, y; | 1306 | int x, y; |
1301 | for (x = 0; x < m_channel.Width; x++) | 1307 | for(x = 0; x < m_channel.Width; x++) |
1302 | for (y = 0; y < m_channel.Height; y++) | 1308 | for(y = 0; y < m_channel.Height; y++) |
1303 | m_channel[x, y] = m_revert[x, y]; | 1309 | m_channel[x, y] = m_revert[x, y]; |
1304 | 1310 | ||
1305 | } | 1311 | } |
@@ -1310,9 +1316,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
1310 | 1316 | ||
1311 | if (direction.ToLower().StartsWith("y")) | 1317 | if (direction.ToLower().StartsWith("y")) |
1312 | { | 1318 | { |
1313 | for (int x = 0; x < m_channel.Width; x++) | 1319 | for(int x = 0; x < m_channel.Width; x++) |
1314 | { | 1320 | { |
1315 | for (int y = 0; y < m_channel.Height / 2; y++) | 1321 | for(int y = 0; y < m_channel.Height / 2; y++) |
1316 | { | 1322 | { |
1317 | double height = m_channel[x, y]; | 1323 | double height = m_channel[x, y]; |
1318 | double flippedHeight = m_channel[x, (int)m_channel.Height - 1 - y]; | 1324 | double flippedHeight = m_channel[x, (int)m_channel.Height - 1 - y]; |
@@ -1324,9 +1330,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
1324 | } | 1330 | } |
1325 | else if (direction.ToLower().StartsWith("x")) | 1331 | else if (direction.ToLower().StartsWith("x")) |
1326 | { | 1332 | { |
1327 | for (int y = 0; y < m_channel.Height; y++) | 1333 | for(int y = 0; y < m_channel.Height; y++) |
1328 | { | 1334 | { |
1329 | for (int x = 0; x < m_channel.Width / 2; x++) | 1335 | for(int x = 0; x < m_channel.Width / 2; x++) |
1330 | { | 1336 | { |
1331 | double height = m_channel[x, y]; | 1337 | double height = m_channel[x, y]; |
1332 | double flippedHeight = m_channel[(int)m_channel.Width - 1 - x, y]; | 1338 | double flippedHeight = m_channel[(int)m_channel.Width - 1 - x, y]; |
@@ -1365,9 +1371,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
1365 | int width = m_channel.Width; | 1371 | int width = m_channel.Width; |
1366 | int height = m_channel.Height; | 1372 | int height = m_channel.Height; |
1367 | 1373 | ||
1368 | for (int x = 0; x < width; x++) | 1374 | for(int x = 0; x < width; x++) |
1369 | { | 1375 | { |
1370 | for (int y = 0; y < height; y++) | 1376 | for(int y = 0; y < height; y++) |
1371 | { | 1377 | { |
1372 | double currHeight = m_channel[x, y]; | 1378 | double currHeight = m_channel[x, y]; |
1373 | if (currHeight < currMin) | 1379 | if (currHeight < currMin) |
@@ -1388,12 +1394,12 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
1388 | //m_log.InfoFormat("Scale = {0}", scale); | 1394 | //m_log.InfoFormat("Scale = {0}", scale); |
1389 | 1395 | ||
1390 | // scale the heightmap accordingly | 1396 | // scale the heightmap accordingly |
1391 | for (int x = 0; x < width; x++) | 1397 | for(int x = 0; x < width; x++) |
1392 | { | 1398 | { |
1393 | for (int y = 0; y < height; y++) | 1399 | for(int y = 0; y < height; y++) |
1394 | { | 1400 | { |
1395 | double currHeight = m_channel[x, y] - currMin; | 1401 | double currHeight = m_channel[x, y] - currMin; |
1396 | m_channel[x, y] = desiredMin + (currHeight * scale); | 1402 | m_channel[x, y] = desiredMin + (currHeight * scale); |
1397 | } | 1403 | } |
1398 | } | 1404 | } |
1399 | 1405 | ||
@@ -1404,42 +1410,42 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
1404 | private void InterfaceElevateTerrain(Object[] args) | 1410 | private void InterfaceElevateTerrain(Object[] args) |
1405 | { | 1411 | { |
1406 | int x, y; | 1412 | int x, y; |
1407 | for (x = 0; x < m_channel.Width; x++) | 1413 | for(x = 0; x < m_channel.Width; x++) |
1408 | for (y = 0; y < m_channel.Height; y++) | 1414 | for(y = 0; y < m_channel.Height; y++) |
1409 | m_channel[x, y] += (double) args[0]; | 1415 | m_channel[x, y] += (double)args[0]; |
1410 | } | 1416 | } |
1411 | 1417 | ||
1412 | private void InterfaceMultiplyTerrain(Object[] args) | 1418 | private void InterfaceMultiplyTerrain(Object[] args) |
1413 | { | 1419 | { |
1414 | int x, y; | 1420 | int x, y; |
1415 | for (x = 0; x < m_channel.Width; x++) | 1421 | for(x = 0; x < m_channel.Width; x++) |
1416 | for (y = 0; y < m_channel.Height; y++) | 1422 | for(y = 0; y < m_channel.Height; y++) |
1417 | m_channel[x, y] *= (double) args[0]; | 1423 | m_channel[x, y] *= (double)args[0]; |
1418 | } | 1424 | } |
1419 | 1425 | ||
1420 | private void InterfaceLowerTerrain(Object[] args) | 1426 | private void InterfaceLowerTerrain(Object[] args) |
1421 | { | 1427 | { |
1422 | int x, y; | 1428 | int x, y; |
1423 | for (x = 0; x < m_channel.Width; x++) | 1429 | for(x = 0; x < m_channel.Width; x++) |
1424 | for (y = 0; y < m_channel.Height; y++) | 1430 | for(y = 0; y < m_channel.Height; y++) |
1425 | m_channel[x, y] -= (double) args[0]; | 1431 | m_channel[x, y] -= (double)args[0]; |
1426 | } | 1432 | } |
1427 | 1433 | ||
1428 | public void InterfaceFillTerrain(Object[] args) | 1434 | public void InterfaceFillTerrain(Object[] args) |
1429 | { | 1435 | { |
1430 | int x, y; | 1436 | int x, y; |
1431 | 1437 | ||
1432 | for (x = 0; x < m_channel.Width; x++) | 1438 | for(x = 0; x < m_channel.Width; x++) |
1433 | for (y = 0; y < m_channel.Height; y++) | 1439 | for(y = 0; y < m_channel.Height; y++) |
1434 | m_channel[x, y] = (double) args[0]; | 1440 | m_channel[x, y] = (double)args[0]; |
1435 | } | 1441 | } |
1436 | 1442 | ||
1437 | private void InterfaceMinTerrain(Object[] args) | 1443 | private void InterfaceMinTerrain(Object[] args) |
1438 | { | 1444 | { |
1439 | int x, y; | 1445 | int x, y; |
1440 | for (x = 0; x < m_channel.Width; x++) | 1446 | for(x = 0; x < m_channel.Width; x++) |
1441 | { | 1447 | { |
1442 | for (y = 0; y < m_channel.Height; y++) | 1448 | for(y = 0; y < m_channel.Height; y++) |
1443 | { | 1449 | { |
1444 | m_channel[x, y] = Math.Max((double)args[0], m_channel[x, y]); | 1450 | m_channel[x, y] = Math.Max((double)args[0], m_channel[x, y]); |
1445 | } | 1451 | } |
@@ -1449,9 +1455,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
1449 | private void InterfaceMaxTerrain(Object[] args) | 1455 | private void InterfaceMaxTerrain(Object[] args) |
1450 | { | 1456 | { |
1451 | int x, y; | 1457 | int x, y; |
1452 | for (x = 0; x < m_channel.Width; x++) | 1458 | for(x = 0; x < m_channel.Width; x++) |
1453 | { | 1459 | { |
1454 | for (y = 0; y < m_channel.Height; y++) | 1460 | for(y = 0; y < m_channel.Height; y++) |
1455 | { | 1461 | { |
1456 | m_channel[x, y] = Math.Min((double)args[0], m_channel[x, y]); | 1462 | m_channel[x, y] = Math.Min((double)args[0], m_channel[x, y]); |
1457 | } | 1463 | } |
@@ -1480,10 +1486,10 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
1480 | double sum = 0; | 1486 | double sum = 0; |
1481 | 1487 | ||
1482 | int x; | 1488 | int x; |
1483 | for (x = 0; x < m_channel.Width; x++) | 1489 | for(x = 0; x < m_channel.Width; x++) |
1484 | { | 1490 | { |
1485 | int y; | 1491 | int y; |
1486 | for (y = 0; y < m_channel.Height; y++) | 1492 | for(y = 0; y < m_channel.Height; y++) |
1487 | { | 1493 | { |
1488 | sum += m_channel[x, y]; | 1494 | sum += m_channel[x, y]; |
1489 | if (max < m_channel[x, y]) | 1495 | if (max < m_channel[x, y]) |
@@ -1501,7 +1507,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
1501 | 1507 | ||
1502 | private void InterfaceEnableExperimentalBrushes(Object[] args) | 1508 | private void InterfaceEnableExperimentalBrushes(Object[] args) |
1503 | { | 1509 | { |
1504 | if ((bool) args[0]) | 1510 | if ((bool)args[0]) |
1505 | { | 1511 | { |
1506 | m_painteffects[StandardTerrainEffects.Revert] = new WeatherSphere(); | 1512 | m_painteffects[StandardTerrainEffects.Revert] = new WeatherSphere(); |
1507 | m_painteffects[StandardTerrainEffects.Flatten] = new OlsenSphere(); | 1513 | m_painteffects[StandardTerrainEffects.Flatten] = new OlsenSphere(); |
@@ -1520,7 +1526,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
1520 | if (firstArg == "list") | 1526 | if (firstArg == "list") |
1521 | { | 1527 | { |
1522 | MainConsole.Instance.Output("List of loaded plugins"); | 1528 | MainConsole.Instance.Output("List of loaded plugins"); |
1523 | foreach (KeyValuePair<string, ITerrainEffect> kvp in m_plugineffects) | 1529 | foreach(KeyValuePair<string, ITerrainEffect> kvp in m_plugineffects) |
1524 | { | 1530 | { |
1525 | MainConsole.Instance.Output(kvp.Key); | 1531 | MainConsole.Instance.Output(kvp.Key); |
1526 | } | 1532 | } |
@@ -1668,6 +1674,18 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
1668 | // Add Feature command to Scene, since Command object requires fixed-length arglists | 1674 | // Add Feature command to Scene, since Command object requires fixed-length arglists |
1669 | m_scene.AddCommand("Terrain", this, "terrain feature", | 1675 | m_scene.AddCommand("Terrain", this, "terrain feature", |
1670 | "terrain feature <type> <parameters...>", "Constructs a feature of the requested type.", FeatureCommand); | 1676 | "terrain feature <type> <parameters...>", "Constructs a feature of the requested type.", FeatureCommand); |
1677 | // Add Modify command to Scene, since Command object requires fixed-length arglists | ||
1678 | m_scene.AddCommand("Terrain", this, "terrain modify", | ||
1679 | "terrain modify <operation> <value> [<area>] [<taper>]", | ||
1680 | "Modifies the terrain as instructed." + | ||
1681 | "\nEach operation can be limited to an area of effect:" + | ||
1682 | "\n * -ell=x,y,rx[,ry] constrains the operation to an ellipse centred at x,y" + | ||
1683 | "\n * -rec=x,y,dx[,dy] constrains the operation to a rectangle based at x,y" + | ||
1684 | "\nEach operation can have its effect tapered based on distance from centre:" + | ||
1685 | "\n * elliptical operations taper as cones" + | ||
1686 | "\n * rectangular operations taper as pyramids" | ||
1687 | , | ||
1688 | ModifyCommand); | ||
1671 | 1689 | ||
1672 | } | 1690 | } |
1673 | 1691 | ||
@@ -1683,7 +1701,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
1683 | { | 1701 | { |
1684 | result = String.Format("Terrain Feature \"{0}\" not found.", featureType); | 1702 | result = String.Format("Terrain Feature \"{0}\" not found.", featureType); |
1685 | } | 1703 | } |
1686 | else if ((cmd.Length > 3) && (cmd[3] == "usage")) | 1704 | else if ((cmd.Length > 3) && (cmd[3] == "usage")) |
1687 | { | 1705 | { |
1688 | result = "Usage: " + feature.GetUsage(); | 1706 | result = "Usage: " + feature.GetUsage(); |
1689 | } | 1707 | } |
@@ -1692,7 +1710,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
1692 | result = feature.CreateFeature(m_channel, cmd); | 1710 | result = feature.CreateFeature(m_channel, cmd); |
1693 | } | 1711 | } |
1694 | 1712 | ||
1695 | if(result == String.Empty) | 1713 | if (result == String.Empty) |
1696 | { | 1714 | { |
1697 | result = "Created Feature"; | 1715 | result = "Created Feature"; |
1698 | m_log.DebugFormat("Created terrain feature {0}", featureType); | 1716 | m_log.DebugFormat("Created terrain feature {0}", featureType); |
@@ -1704,7 +1722,42 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
1704 | } | 1722 | } |
1705 | MainConsole.Instance.Output(result); | 1723 | MainConsole.Instance.Output(result); |
1706 | } | 1724 | } |
1707 | #endregion | 1725 | |
1726 | public void ModifyCommand(string module, string[] cmd) | ||
1727 | { | ||
1728 | string result; | ||
1729 | if (cmd.Length > 2) | ||
1730 | { | ||
1731 | string operationType = cmd[2]; | ||
1732 | |||
1733 | ITerrainModifier operation; | ||
1734 | if (!m_modifyOperations.TryGetValue(operationType, out operation)) | ||
1735 | { | ||
1736 | result = String.Format("Terrain Modify \"{0}\" not found.", operationType); | ||
1737 | } | ||
1738 | else if ((cmd.Length > 3) && (cmd[3] == "usage")) | ||
1739 | { | ||
1740 | result = "Usage: " + operation.GetUsage(); | ||
1741 | } | ||
1742 | else | ||
1743 | { | ||
1744 | result = operation.ModifyTerrain(m_channel, cmd); | ||
1745 | } | ||
1746 | |||
1747 | if (result == String.Empty) | ||
1748 | { | ||
1749 | result = "Modified terrain"; | ||
1750 | m_log.DebugFormat("Performed terrain operation {0}", operationType); | ||
1751 | } | ||
1752 | } | ||
1753 | else | ||
1754 | { | ||
1755 | result = "Usage: <operation-name> <arg1> <arg2>..."; | ||
1756 | } | ||
1757 | MainConsole.Instance.Output(result); | ||
1758 | } | ||
1759 | |||
1760 | #endregion | ||
1708 | 1761 | ||
1709 | } | 1762 | } |
1710 | } | 1763 | } |