Add catenary brush

This commit is contained in:
Jesse Boyd 2017-08-11 17:23:38 +10:00
parent f85a9f08d0
commit 8948645832
No known key found for this signature in database
GPG Key ID: 59F1DE6293AF6E1F
4 changed files with 104 additions and 3 deletions

View File

@ -128,6 +128,8 @@ public enum BBC {
BRUSH_HEIGHT_INVALID("Invalid height map file (%s0)", "WorldEdit.Brush"), BRUSH_HEIGHT_INVALID("Invalid height map file (%s0)", "WorldEdit.Brush"),
BRUSH_SMOOTH("Note: Use the blend brush if you want to smooth overhangs or caves.", "WorldEdit.Brush"), BRUSH_SMOOTH("Note: Use the blend brush if you want to smooth overhangs or caves.", "WorldEdit.Brush"),
BRUSH_SPLINE("Click to add a point, click the same spot to finish", "WorldEdit.Brush"), BRUSH_SPLINE("Click to add a point, click the same spot to finish", "WorldEdit.Brush"),
BRUSH_LINE_PRIMARY("Added point %s0, click another position to create the line", "WorldEdit.Brush"),
BRUSH_LINE_SECONDARY("Created pline", "WorldEdit.Brush"),
BRUSH_SPLINE_PRIMARY_2("Added position, Click the same spot to join!", "WorldEdit.Brush"), BRUSH_SPLINE_PRIMARY_2("Added position, Click the same spot to join!", "WorldEdit.Brush"),
BRUSH_SPLINE_SECONDARY_ERROR("Not enough positions set!", "WorldEdit.Brush"), BRUSH_SPLINE_SECONDARY_ERROR("Not enough positions set!", "WorldEdit.Brush"),
BRUSH_SPLINE_SECONDARY("Created spline", "WorldEdit.Brush"), BRUSH_SPLINE_SECONDARY("Created spline", "WorldEdit.Brush"),

View File

@ -0,0 +1,74 @@
package com.boydti.fawe.object.brush;
import com.boydti.fawe.config.BBC;
import com.boydti.fawe.object.brush.visualization.VisualExtent;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.command.tool.brush.Brush;
import com.sk89q.worldedit.function.pattern.Pattern;
import java.util.Arrays;
import java.util.List;
public class CatenaryBrush implements Brush, ResettableTool {
private final boolean shell, select;
private final double slack;
private Vector pos1;
public CatenaryBrush(boolean shell, boolean select, double lengthFactor) {
this.shell = shell;
this.select = select;
this.slack = lengthFactor;
}
@Override
public void build(EditSession editSession, Vector pos2, final Pattern pattern, double size) throws MaxChangedBlocksException {
boolean visual = (editSession.getExtent() instanceof VisualExtent);
if (pos1 == null || pos2.equals(pos1)) {
if (!visual) {
pos1 = pos2;
BBC.BRUSH_LINE_PRIMARY.send(editSession.getPlayer(), pos2);
}
return;
}
Vector vertex = getVertex(pos1, pos2, slack);
List<Vector> nodes = Arrays.asList(pos1, vertex, pos2);
editSession.drawSpline(pattern, nodes, 0, 0, 0, 10, size, !shell);
if (!visual) {
BBC.BRUSH_LINE_SECONDARY.send(editSession.getPlayer());
if (!select) {
pos1 = null;
return;
} else {
pos1 = pos2;
}
}
}
@Override
public boolean reset() {
pos1 = null;
return true;
}
public Vector getVertex(Vector pos1, Vector pos2, double lenPercent) {
double len = pos1.distance(pos2) * lenPercent;
double dy = pos2.getY() - pos1.getY();
double dx = pos2.getX() - pos1.getX();
double dz = pos2.getZ() - pos1.getZ();
double h = Math.sqrt(dx * dx + dz * dz);
double t = Math.sqrt(len * len - dy * dy) / h;
double z = 0.001;
for (; Math.sinh(z) < t*z; z += 0.001); // close enough
double a = (h / 2) / z;
double p = (h - a * Math.log((len + dy) / (len - dy)))/2;
double q = (dy - len * Math.cosh(z) / Math.sinh(z)) / 2;
double y = a * 1 + q;
return pos1.add(pos2.subtract(pos1).multiply(p / h).add(0, y, 0)).round();
}
}

View File

@ -1,5 +1,6 @@
package com.boydti.fawe.object.brush; package com.boydti.fawe.object.brush;
import com.boydti.fawe.config.BBC;
import com.boydti.fawe.object.brush.visualization.VisualExtent; import com.boydti.fawe.object.brush.visualization.VisualExtent;
import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.MaxChangedBlocksException; import com.sk89q.worldedit.MaxChangedBlocksException;
@ -22,11 +23,15 @@ public class LineBrush implements Brush, ResettableTool {
public void build(EditSession editSession, Vector position, final Pattern pattern, double size) throws MaxChangedBlocksException { public void build(EditSession editSession, Vector position, final Pattern pattern, double size) throws MaxChangedBlocksException {
boolean visual = (editSession.getExtent() instanceof VisualExtent); boolean visual = (editSession.getExtent() instanceof VisualExtent);
if (pos1 == null) { if (pos1 == null) {
if (!visual) pos1 = position; if (!visual) {
pos1 = position;
BBC.BRUSH_LINE_PRIMARY.send(editSession.getPlayer(), position);
}
return; return;
} }
editSession.drawLine(pattern, pos1, position, size, !shell, flat); editSession.drawLine(pattern, pos1, position, size, !shell, flat);
if (!visual) { if (!visual) {
BBC.BRUSH_LINE_SECONDARY.send(editSession.getPlayer());
if (!select) { if (!select) {
pos1 = null; pos1 = null;
return; return;

View File

@ -27,6 +27,7 @@ import com.boydti.fawe.object.FaweLimit;
import com.boydti.fawe.object.FawePlayer; import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.brush.BlendBall; import com.boydti.fawe.object.brush.BlendBall;
import com.boydti.fawe.object.brush.BrushSettings; import com.boydti.fawe.object.brush.BrushSettings;
import com.boydti.fawe.object.brush.CatenaryBrush;
import com.boydti.fawe.object.brush.CircleBrush; import com.boydti.fawe.object.brush.CircleBrush;
import com.boydti.fawe.object.brush.CommandBrush; import com.boydti.fawe.object.brush.CommandBrush;
import com.boydti.fawe.object.brush.CopyPastaBrush; import com.boydti.fawe.object.brush.CopyPastaBrush;
@ -84,6 +85,7 @@ import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.session.ClipboardHolder; import com.sk89q.worldedit.session.ClipboardHolder;
import com.sk89q.worldedit.util.command.InvalidUsageException; import com.sk89q.worldedit.util.command.InvalidUsageException;
import com.sk89q.worldedit.util.command.binding.Range;
import com.sk89q.worldedit.util.command.binding.Switch; import com.sk89q.worldedit.util.command.binding.Switch;
import com.sk89q.worldedit.util.command.parametric.Optional; import com.sk89q.worldedit.util.command.parametric.Optional;
import java.awt.Color; import java.awt.Color;
@ -245,7 +247,25 @@ public class BrushCommands extends MethodCommands {
.setFill(fill); .setFill(fill);
} }
// final double tension, final double bias, final double continuity, final double quality @Command(
aliases = {"catenary", "cat", "gravityline", "saggedline"},
usage = "<pattern> [length-factor=1.2] [size=0]",
desc = "Create a hanging line between two points",
help = "Create a hanging line between two points.\n" +
"The length-factor controls how long the line is\n" +
"The -h flag creates only a shell\n" +
"The -s flag selects the clicked point after drawing\n",
min = 1,
max = 3
)
@CommandPermissions("worldedit.brush.spline")
public BrushSettings catenaryBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("1.2") @Range(min=1) double lengthFactor, @Optional("0") double radius, @Switch('h') boolean shell, @Switch('s') boolean select, CommandContext context) throws WorldEditException {
worldEdit.checkMaxBrushRadius(radius);
return get(context)
.setBrush(new CatenaryBrush(shell, select, lengthFactor))
.setSize(radius)
.setFill(fill);
}
@Command( @Command(
aliases = {"sspl", "sspline", "surfacespline"}, aliases = {"sspl", "sspline", "surfacespline"},
@ -254,7 +274,7 @@ public class BrushCommands extends MethodCommands {
help = "Create a spline on the surface\n" + help = "Create a spline on the surface\n" +
"Video: https://www.youtube.com/watch?v=zSN-2jJxXlM", "Video: https://www.youtube.com/watch?v=zSN-2jJxXlM",
min = 0, min = 0,
max = 2 max = 6
) )
@CommandPermissions("worldedit.brush.surfacespline") // 0, 0, 0, 10, 0, @CommandPermissions("worldedit.brush.surfacespline") // 0, 0, 0, 10, 0,
public BrushSettings surfaceSpline(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("0") double radius, @Optional("0") double tension, @Optional("0") double bias, @Optional("0") double continuity, @Optional("10") double quality, CommandContext context) throws WorldEditException { public BrushSettings surfaceSpline(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("0") double radius, @Optional("0") double tension, @Optional("0") double bias, @Optional("0") double continuity, @Optional("10") double quality, CommandContext context) throws WorldEditException {