Add flatten brush (needs testing)
This commit is contained in:
parent
85ac3dff41
commit
49fc44bb4d
@ -0,0 +1,28 @@
|
||||
package com.boydti.fawe.object.brush;
|
||||
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.MaxChangedBlocksException;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.function.mask.Masks;
|
||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
import java.io.InputStream;
|
||||
|
||||
public class FlattenBrush extends HeightBrush {
|
||||
|
||||
public FlattenBrush(InputStream stream, int rotation, double yscale, DoubleActionBrushTool tool, Clipboard clipboard) {
|
||||
super(stream, rotation, yscale, tool, clipboard);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void build(DoubleActionBrushTool.BrushAction action, EditSession editSession, Vector position, Pattern pattern, double sizeDouble) throws MaxChangedBlocksException {
|
||||
int size = (int) sizeDouble;
|
||||
Mask mask = tool.getMask();
|
||||
if (mask == Masks.alwaysTrue() || mask == Masks.alwaysTrue2D()) {
|
||||
mask = null;
|
||||
}
|
||||
heightMap.setSize(size);
|
||||
heightMap.apply(editSession, mask, position, size, rotation, action == DoubleActionBrushTool.BrushAction.PRIMARY ? yscale : -yscale, true, true);
|
||||
}
|
||||
}
|
@ -16,9 +16,9 @@ import java.io.InputStream;
|
||||
public class HeightBrush implements DoubleActionBrush {
|
||||
|
||||
public final ScalableHeightMap heightMap;
|
||||
private final int rotation;
|
||||
double yscale = 1;
|
||||
private final DoubleActionBrushTool tool;
|
||||
public final int rotation;
|
||||
public final double yscale;
|
||||
public final DoubleActionBrushTool tool;
|
||||
|
||||
public HeightBrush(InputStream stream, int rotation, double yscale, DoubleActionBrushTool tool, Clipboard clipboard) {
|
||||
this.tool = tool;
|
||||
@ -45,6 +45,6 @@ public class HeightBrush implements DoubleActionBrush {
|
||||
mask = null;
|
||||
}
|
||||
heightMap.setSize(size);
|
||||
heightMap.apply(editSession, mask, position, size, rotation, action == DoubleActionBrushTool.BrushAction.PRIMARY ? yscale : -yscale, true);
|
||||
heightMap.apply(editSession, mask, position, size, rotation, action == DoubleActionBrushTool.BrushAction.PRIMARY ? yscale : -yscale, true, false);
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,6 @@ package com.boydti.fawe.object.brush.heightmap;
|
||||
|
||||
import com.boydti.fawe.object.IntegerPair;
|
||||
import com.boydti.fawe.object.PseudoRandom;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.boydti.fawe.util.MathMan;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.MaxChangedBlocksException;
|
||||
@ -12,9 +11,7 @@ import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.internal.LocalWorldAdapter;
|
||||
import com.sk89q.worldedit.math.convolution.GaussianKernel;
|
||||
import com.sk89q.worldedit.math.convolution.HeightMap;
|
||||
import com.sk89q.worldedit.math.convolution.HeightMapFilter;
|
||||
import com.sk89q.worldedit.regions.CuboidRegion;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import java.awt.image.BufferedImage;
|
||||
@ -103,7 +100,7 @@ public class ScalableHeightMap {
|
||||
return new ArrayHeightMap(array);
|
||||
}
|
||||
|
||||
public void apply(EditSession session, Mask mask, Vector pos, int size, int rotationMode, double yscale, boolean smooth) throws MaxChangedBlocksException {
|
||||
public void apply(EditSession session, Mask mask, Vector pos, int size, int rotationMode, double yscale, boolean smooth, boolean towards) throws MaxChangedBlocksException {
|
||||
Vector top = session.getMaximumPoint();
|
||||
int maxY = top.getBlockY();
|
||||
int diameter = 2 * size + 1;
|
||||
@ -113,31 +110,65 @@ public class ScalableHeightMap {
|
||||
int startY = pos.getBlockY() - size;
|
||||
int[] newData = new int[diameter * diameter];
|
||||
Vector mutablePos = new Vector(0, 0, 0);
|
||||
for (int x = -size; x <= size; x++) {
|
||||
int xx = centerX + x;
|
||||
mutablePos.mutX(xx);
|
||||
for (int z = -size; z <= size; z++) {
|
||||
int index = (z + size) * diameter + (x + size);
|
||||
int zz = centerZ + z;
|
||||
double raise;
|
||||
switch (rotationMode) {
|
||||
default:
|
||||
raise = getHeight(x, z);
|
||||
break;
|
||||
case 1:
|
||||
raise = getHeight(z, x);
|
||||
break;
|
||||
case 2:
|
||||
raise = getHeight(-x, -z);
|
||||
break;
|
||||
case 3:
|
||||
raise = getHeight(-z, -x);
|
||||
break;
|
||||
if (towards) {
|
||||
int targetY = pos.getBlockY();
|
||||
for (int x = -size; x <= size; x++) {
|
||||
int xx = centerX + x;
|
||||
mutablePos.mutX(xx);
|
||||
for (int z = -size; z <= size; z++) {
|
||||
int index = (z + size) * diameter + (x + size);
|
||||
int zz = centerZ + z;
|
||||
double raise;
|
||||
switch (rotationMode) {
|
||||
default:
|
||||
raise = getHeight(x, z);
|
||||
break;
|
||||
case 1:
|
||||
raise = getHeight(z, x);
|
||||
break;
|
||||
case 2:
|
||||
raise = getHeight(-x, -z);
|
||||
break;
|
||||
case 3:
|
||||
raise = getHeight(-z, -x);
|
||||
break;
|
||||
}
|
||||
raise = (yscale * raise);
|
||||
int height = session.getHighestTerrainBlock(xx, zz, 0, 255, true);
|
||||
int diff = targetY - height;
|
||||
double raiseScaled = 1 + diff * (raise / (double) size);
|
||||
int random = PseudoRandom.random.random(maxY + 1) < (int) ((raiseScaled - (int) raiseScaled) * (maxY + 1)) ? 1 : 0;
|
||||
int raiseScaledInt = (int) raiseScaled + random;
|
||||
newData[index] = height + raiseScaledInt;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int x = -size; x <= size; x++) {
|
||||
int xx = centerX + x;
|
||||
mutablePos.mutX(xx);
|
||||
for (int z = -size; z <= size; z++) {
|
||||
int index = (z + size) * diameter + (x + size);
|
||||
int zz = centerZ + z;
|
||||
double raise;
|
||||
switch (rotationMode) {
|
||||
default:
|
||||
raise = getHeight(x, z);
|
||||
break;
|
||||
case 1:
|
||||
raise = getHeight(z, x);
|
||||
break;
|
||||
case 2:
|
||||
raise = getHeight(-x, -z);
|
||||
break;
|
||||
case 3:
|
||||
raise = getHeight(-z, -x);
|
||||
break;
|
||||
}
|
||||
raise = (yscale * raise);
|
||||
int random = PseudoRandom.random.random(maxY + 1) < (int) ((raise - (int) raise) * (maxY + 1)) ? 1 : 0;
|
||||
int height = session.getHighestTerrainBlock(xx, zz, 0, maxY, true) + (int) raise + random;
|
||||
newData[index] = height;
|
||||
}
|
||||
raise = (yscale * raise);
|
||||
int random = PseudoRandom.random.random(maxY + 1) < (int) ((raise - (int) raise) * (maxY + 1)) ? 1 : 0;
|
||||
int height = session.getHighestTerrainBlock(xx, zz, 0, maxY, true) + (int) raise + random;
|
||||
newData[index] = height;
|
||||
}
|
||||
}
|
||||
int iterations = 1;
|
||||
@ -145,14 +176,14 @@ public class ScalableHeightMap {
|
||||
Vector max = pos.add(size, maxY, size);
|
||||
Region region = new CuboidRegion(session.getWorld(), min, max);
|
||||
HeightMap heightMap = new HeightMap(session, region, true);
|
||||
if (smooth) {
|
||||
try {
|
||||
HeightMapFilter filter = (HeightMapFilter) HeightMapFilter.class.getConstructors()[0].newInstance(GaussianKernel.class.getConstructors()[0].newInstance(5, 1));
|
||||
newData = filter.filter(newData, diameter, diameter);
|
||||
} catch (Throwable e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
}
|
||||
// if (smooth) {
|
||||
// try {
|
||||
// HeightMapFilter filter = (HeightMapFilter) HeightMapFilter.class.getConstructors()[0].newInstance(GaussianKernel.class.getConstructors()[0].newInstance(5, 1));
|
||||
// newData = filter.filter(newData, diameter, diameter);
|
||||
// } catch (Throwable e) {
|
||||
// MainUtil.handleError(e);
|
||||
// }
|
||||
// }
|
||||
heightMap.apply(newData);
|
||||
}
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ import com.boydti.fawe.object.brush.CommandBrush;
|
||||
import com.boydti.fawe.object.brush.CopyPastaBrush;
|
||||
import com.boydti.fawe.object.brush.DoubleActionBrushTool;
|
||||
import com.boydti.fawe.object.brush.ErodeBrush;
|
||||
import com.boydti.fawe.object.brush.FlattenBrush;
|
||||
import com.boydti.fawe.object.brush.HeightBrush;
|
||||
import com.boydti.fawe.object.brush.LineBrush;
|
||||
import com.boydti.fawe.object.brush.RecurseBrush;
|
||||
@ -405,6 +406,58 @@ public class BrushCommands {
|
||||
player.print(BBC.getPrefix() + BBC.BRUSH_HEIGHT.f(radius));
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "flatten", "flatmap", "flat" },
|
||||
usage = "[radius] [file|#clipboard|null] [rotation] [yscale]",
|
||||
flags = "h",
|
||||
desc = "Flatten brush",
|
||||
help =
|
||||
"This brush raises and lowers land towards the clicked point\n",
|
||||
min = 1,
|
||||
max = 4
|
||||
)
|
||||
@CommandPermissions("worldedit.brush.height")
|
||||
public void flattenBrush(Player player, LocalSession session, @Optional("5") double radius, @Optional("") final String filename, @Optional("0") final int rotation, @Optional("1") final double yscale) throws WorldEditException {
|
||||
worldEdit.checkMaxBrushRadius(radius);
|
||||
String filenamePng = (filename.endsWith(".png") ? filename : filename + ".png");
|
||||
File file = new File(Fawe.imp().getDirectory(), "heightmap" + File.separator + filenamePng);
|
||||
InputStream stream = null;
|
||||
if (!file.exists()) {
|
||||
if (!filename.equals("#clipboard") && filename.length() >= 7) {
|
||||
try {
|
||||
URL url;
|
||||
if (filename.startsWith("http")) {
|
||||
url = new URL(filename);
|
||||
if (!url.getHost().equals("i.imgur.com")) {
|
||||
throw new FileNotFoundException(filename);
|
||||
}
|
||||
} else {
|
||||
url = new URL("https://i.imgur.com/" + filenamePng);
|
||||
}
|
||||
ReadableByteChannel rbc = Channels.newChannel(url.openStream());
|
||||
stream = Channels.newInputStream(rbc);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
} else if (!filename.equalsIgnoreCase("#clipboard")){
|
||||
try {
|
||||
stream = new FileInputStream(file);
|
||||
} catch (FileNotFoundException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
DoubleActionBrushTool tool = session.getDoubleActionBrushTool(player.getItemInHand());
|
||||
tool.setSize(radius);
|
||||
try {
|
||||
tool.setBrush(new FlattenBrush(stream, rotation, yscale, tool, filename.equalsIgnoreCase("#clipboard") ? session.getClipboard().getClipboard() : null), "worldedit.brush.height");
|
||||
} catch (EmptyClipboardException ignore) {
|
||||
tool.setBrush(new FlattenBrush(stream, rotation, yscale, tool, null), "worldedit.brush.height");
|
||||
}
|
||||
player.print(BBC.getPrefix() + BBC.BRUSH_HEIGHT.f(radius));
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "copypaste", "copy", "paste", "cp", "copypasta" },
|
||||
usage = "[depth]",
|
||||
|
Loading…
Reference in New Issue
Block a user