Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add clipboard support to //brush deform #2580

Draft
wants to merge 11 commits into
base: master
Choose a base branch
from
146 changes: 126 additions & 20 deletions worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.TimeZone;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
Expand Down Expand Up @@ -451,6 +452,15 @@ public ClipboardHolder getClipboard() throws EmptyClipboardException {
return clipboard;
}

/**
* Gets the clipboard.
*
* @return clipboard
*/
public Optional<ClipboardHolder> getClipboardOptional() {
return Optional.ofNullable(clipboard);
}

/**
* Sets the clipboard.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -506,14 +506,17 @@ public void deform(Player player, LocalSession localSession,
@Switch(name = 'r', desc = "Use the game's coordinate origin")
boolean useRawCoords,
@Switch(name = 'o', desc = "Use the placement position as the origin")
boolean usePlacement) throws WorldEditException {
boolean usePlacement,
@Switch(name = 'l', desc = "Fetch from the clipboard instead of the world")
boolean useClipboard) throws WorldEditException {
Deform deform = new Deform(expression);
if (useRawCoords) {
deform.setMode(Deform.Mode.RAW_COORD);
} else if (usePlacement) {
deform.setMode(Deform.Mode.OFFSET);
deform.setOffset(localSession.getPlacementPosition(player).toVector3());
}
deform.setUseClipboard(useClipboard);
setOperationBasedBrush(player, localSession, radius,
deform, shape, "worldedit.brush.deform");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,9 @@
import com.sk89q.worldedit.internal.annotation.Radii;
import com.sk89q.worldedit.internal.annotation.Selection;
import com.sk89q.worldedit.internal.expression.ExpressionException;
import com.sk89q.worldedit.internal.util.TransformUtil;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.math.Vector3;
import com.sk89q.worldedit.math.transform.Transform;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.TreeGenerator.TreeType;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
Expand Down Expand Up @@ -370,45 +371,13 @@ public int generate(Actor actor, LocalSession session, EditSession editSession,
@Switch(name = 'r', desc = "Use the game's coordinate origin")
boolean useRawCoords,
@Switch(name = 'o', desc = "Use the placement's coordinate origin")
boolean offset,
boolean offsetPlacement,
@Switch(name = 'c', desc = "Use the selection's center as origin")
boolean offsetCenter) throws WorldEditException {

final Vector3 zero;
Vector3 unit;

if (useRawCoords) {
zero = Vector3.ZERO;
unit = Vector3.ONE;
} else if (offset) {
zero = session.getPlacementPosition(actor).toVector3();
unit = Vector3.ONE;
} else if (offsetCenter) {
final Vector3 min = region.getMinimumPoint().toVector3();
final Vector3 max = region.getMaximumPoint().toVector3();

zero = max.add(min).multiply(0.5);
unit = Vector3.ONE;
} else {
final Vector3 min = region.getMinimumPoint().toVector3();
final Vector3 max = region.getMaximumPoint().toVector3();

zero = max.add(min).multiply(0.5);
unit = max.subtract(zero);

if (unit.x() == 0) {
unit = unit.withX(1.0);
}
if (unit.y() == 0) {
unit = unit.withY(1.0);
}
if (unit.z() == 0) {
unit = unit.withZ(1.0);
}
}
final Transform transform = TransformUtil.createTransformForExpressionCommand(actor, session, region, useRawCoords, offsetPlacement, offsetCenter);

try {
final int affected = editSession.makeShape(region, zero, unit, pattern, String.join(" ", expression), hollow, session.getTimeout());
final int affected = editSession.makeShape(region, transform, pattern, String.join(" ", expression), hollow, session.getTimeout());
if (actor instanceof Player) {
((Player) actor).findFreePosition();
}
Expand Down Expand Up @@ -439,44 +408,13 @@ public int generateBiome(Actor actor, LocalSession session, EditSession editSess
@Switch(name = 'r', desc = "Use the game's coordinate origin")
boolean useRawCoords,
@Switch(name = 'o', desc = "Use the placement's coordinate origin")
boolean offset,
boolean offsetPlacement,
@Switch(name = 'c', desc = "Use the selection's center as origin")
boolean offsetCenter) throws WorldEditException {
final Vector3 zero;
Vector3 unit;

if (useRawCoords) {
zero = Vector3.ZERO;
unit = Vector3.ONE;
} else if (offset) {
zero = session.getPlacementPosition(actor).toVector3();
unit = Vector3.ONE;
} else if (offsetCenter) {
final Vector3 min = region.getMinimumPoint().toVector3();
final Vector3 max = region.getMaximumPoint().toVector3();

zero = max.add(min).multiply(0.5);
unit = Vector3.ONE;
} else {
final Vector3 min = region.getMinimumPoint().toVector3();
final Vector3 max = region.getMaximumPoint().toVector3();

zero = max.add(min).multiply(0.5);
unit = max.subtract(zero);

if (unit.x() == 0) {
unit = unit.withX(1.0);
}
if (unit.y() == 0) {
unit = unit.withY(1.0);
}
if (unit.z() == 0) {
unit = unit.withZ(1.0);
}
}
final Transform transform = TransformUtil.createTransformForExpressionCommand(actor, session, region, useRawCoords, offsetPlacement, offsetCenter);

try {
final int affected = editSession.makeBiomeShape(region, zero, unit, target, String.join(" ", expression), hollow, session.getTimeout());
final int affected = editSession.makeBiomeShape(region, transform, target, String.join(" ", expression), hollow, session.getTimeout());
actor.printInfo(TranslatableComponent.of("worldedit.generatebiome.changed", TextComponent.of(affected)));
return affected;
} catch (ExpressionException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.extent.InputExtent;
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.function.GroundFunction;
import com.sk89q.worldedit.function.RegionFunction;
import com.sk89q.worldedit.function.block.BlockReplace;
Expand All @@ -47,13 +49,15 @@
import com.sk89q.worldedit.internal.annotation.Offset;
import com.sk89q.worldedit.internal.annotation.Selection;
import com.sk89q.worldedit.internal.expression.ExpressionException;
import com.sk89q.worldedit.internal.util.TransformUtil;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.math.Vector3;
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.math.convolution.SnowHeightMap;
import com.sk89q.worldedit.math.noise.RandomNoise;
import com.sk89q.worldedit.math.transform.Transform;
import com.sk89q.worldedit.regions.ConvexPolyhedralRegion;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.Region;
Expand Down Expand Up @@ -495,44 +499,30 @@ public int deform(Actor actor, LocalSession session, EditSession editSession,
@Switch(name = 'r', desc = "Use the game's coordinate origin")
boolean useRawCoords,
@Switch(name = 'o', desc = "Use the placement's coordinate origin")
boolean offset,
boolean offsetPlacement,
@Switch(name = 'c', desc = "Use the selection's center as origin")
boolean offsetCenter) throws WorldEditException {
final Vector3 zero;
Vector3 unit;

if (useRawCoords) {
zero = Vector3.ZERO;
unit = Vector3.ONE;
} else if (offset) {
zero = session.getPlacementPosition(actor).toVector3();
unit = Vector3.ONE;
} else if (offsetCenter) {
final Vector3 min = region.getMinimumPoint().toVector3();
final Vector3 max = region.getMaximumPoint().toVector3();

zero = max.add(min).multiply(0.5);
unit = Vector3.ONE;
} else {
final Vector3 min = region.getMinimumPoint().toVector3();
final Vector3 max = region.getMaximumPoint().toVector3();
boolean offsetCenter,
@Switch(name = 'l', desc = "Fetch from the clipboard instead of the world")
boolean useClipboard) throws WorldEditException {
final Transform targetTransform = TransformUtil.createTransformForExpressionCommand(actor, session, region, useRawCoords, offsetPlacement, offsetCenter);

zero = max.add(min).divide(2);
unit = max.subtract(zero);
final InputExtent sourceExtent;
final Transform sourceTransform;
if (useClipboard) {
final Clipboard clipboard = session.getClipboard().getClipboard();
sourceExtent = clipboard;

if (unit.x() == 0) {
unit = unit.withX(1.0);
}
if (unit.y() == 0) {
unit = unit.withY(1.0);
}
if (unit.z() == 0) {
unit = unit.withZ(1.0);
}
final Vector3 clipboardMin = clipboard.getMinimumPoint().toVector3();
final Vector3 clipboardMax = clipboard.getMaximumPoint().toVector3();

sourceTransform = TransformUtil.createTransformForExpressionCommand(useRawCoords, offsetPlacement, offsetCenter, clipboardMin, clipboardMax, clipboardMin);
} else {
sourceExtent = editSession.getWorld();
sourceTransform = targetTransform;
}

try {
final int affected = editSession.deformRegion(region, zero, unit, String.join(" ", expression), session.getTimeout());
final int affected = editSession.deformRegion(region, targetTransform, String.join(" ", expression), session.getTimeout(), sourceExtent, sourceTransform);
if (actor instanceof Player) {
((Player) actor).findFreePosition();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
import com.sk89q.worldedit.internal.expression.Expression;
import com.sk89q.worldedit.internal.expression.ExpressionException;
import com.sk89q.worldedit.internal.registry.InputParser;
import com.sk89q.worldedit.math.Vector3;
import com.sk89q.worldedit.math.transform.Identity;
import com.sk89q.worldedit.regions.shape.WorldEditExpressionEnvironment;
import com.sk89q.worldedit.session.SessionOwner;
import com.sk89q.worldedit.util.formatting.text.TranslatableComponent;
Expand Down Expand Up @@ -58,7 +58,7 @@ public Mask parseFromInput(String input, ParserContext context) throws InputPars
try {
Expression exp = Expression.compile(input.substring(1), "x", "y", "z");
WorldEditExpressionEnvironment env = new WorldEditExpressionEnvironment(
context.requireExtent(), Vector3.ONE, Vector3.ZERO);
context.requireExtent(), new Identity());
exp.setEnvironment(env);
if (context.getActor() != null) {
SessionOwner owner = context.getActor();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,21 +25,28 @@
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.extent.InputExtent;
import com.sk89q.worldedit.extent.NullExtent;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.function.Contextual;
import com.sk89q.worldedit.function.EditContext;
import com.sk89q.worldedit.function.operation.Operation;
import com.sk89q.worldedit.function.operation.RunContext;
import com.sk89q.worldedit.internal.expression.Expression;
import com.sk89q.worldedit.internal.expression.ExpressionException;
import com.sk89q.worldedit.internal.util.TransformUtil;
import com.sk89q.worldedit.math.Vector3;
import com.sk89q.worldedit.math.transform.Transform;
import com.sk89q.worldedit.regions.NullRegion;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.session.ClipboardHolder;
import com.sk89q.worldedit.util.formatting.text.Component;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import com.sk89q.worldedit.util.formatting.text.TranslatableComponent;
import com.sk89q.worldedit.util.formatting.text.format.TextColor;

import java.util.Optional;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.sk89q.worldedit.util.GuavaUtil.firstNonNull;

Expand All @@ -50,6 +57,7 @@ public class Deform implements Contextual<Operation> {
private final Expression expression;
private Mode mode;
private Vector3 offset = Vector3.ZERO;
private boolean useClipboard;

public Deform(String expression) {
this(new NullExtent(), new NullRegion(), expression);
Expand Down Expand Up @@ -111,64 +119,66 @@ public void setOffset(Vector3 offset) {
this.offset = offset;
}

public boolean useClipboard() {
return useClipboard;
}

public void setUseClipboard(boolean useClipboard) {
this.useClipboard = useClipboard;
}

@Override
public String toString() {
return "deformation of " + expression.getSource();
}

@Override
public Operation createFromContext(final EditContext context) {
final Vector3 zero;
Vector3 unit;

Region region = firstNonNull(context.getRegion(), this.region);
final Vector3 min = region.getMinimumPoint().toVector3();
final Vector3 max = region.getMaximumPoint().toVector3();

switch (mode) {
case UNIT_CUBE:
final Vector3 min = region.getMinimumPoint().toVector3();
final Vector3 max = region.getMaximumPoint().toVector3();

zero = max.add(min).multiply(0.5);
unit = max.subtract(zero);

if (unit.x() == 0) {
unit = unit.withX(1.0);
}
if (unit.y() == 0) {
unit = unit.withY(1.0);
}
if (unit.z() == 0) {
unit = unit.withZ(1.0);
}
break;
case RAW_COORD:
zero = Vector3.ZERO;
unit = Vector3.ONE;
break;
case OFFSET:
default:
zero = offset;
unit = Vector3.ONE;
LocalSession session = context.getSession();
EditSession editSession = (EditSession) context.getDestination();
final Optional<Clipboard> clipboardOptional = Optional.ofNullable(session)
.flatMap(LocalSession::getClipboardOptional)
.map(ClipboardHolder::getClipboard);

final Transform targetTransform = TransformUtil.createTransformForExpressionCommand(mode, min, max, offset);
final InputExtent sourceExtent;
final Transform sourceTransform;
if (useClipboard && clipboardOptional.isPresent()) {
final Clipboard clipboard = clipboardOptional.get();
final Vector3 clipboardMin = clipboard.getMinimumPoint().toVector3();
final Vector3 clipboardMax = clipboard.getMaximumPoint().toVector3();

sourceExtent = clipboard;
sourceTransform = TransformUtil.createTransformForExpressionCommand(mode, clipboardMin, clipboardMax, offset);
} else {
sourceExtent = editSession.getWorld();
sourceTransform = targetTransform;
}

LocalSession session = context.getSession();
return new DeformOperation(context.getDestination(), region, zero, unit, expression,
session == null ? WorldEdit.getInstance().getConfiguration().calculationTimeout : session.getTimeout());
return new DeformOperation(context.getDestination(), region, targetTransform, expression,
session == null ? WorldEdit.getInstance().getConfiguration().calculationTimeout : session.getTimeout(), sourceExtent, sourceTransform);
}

private record DeformOperation(
Extent destination,
Region region,
Vector3 zero,
Vector3 unit,
Transform targetTransform,
Expression expression,
int timeout
int timeout,
InputExtent sourceExtent,
Transform sourceTransform
) implements Operation {
@Override
public Operation resume(RunContext run) throws WorldEditException {
try {
// TODO: Move deformation code
((EditSession) destination).deformRegion(region, zero, unit, expression, timeout);
final EditSession editSession = (EditSession) destination;
editSession.deformRegion(region, targetTransform, expression, timeout, sourceExtent, sourceTransform);
return null;
} catch (ExpressionException e) {
throw new RuntimeException("Failed to execute expression", e); // TODO: Better exception to throw here?
Expand Down
Loading