Skip to content

Commit e7f8480

Browse files
committed
Add clipboard support to //deform and //brush deform
1 parent 168dec5 commit e7f8480

File tree

6 files changed

+268
-85
lines changed

6 files changed

+268
-85
lines changed

worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java

+49-8
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import com.sk89q.worldedit.extension.platform.Watchdog;
2929
import com.sk89q.worldedit.extent.ChangeSetExtent;
3030
import com.sk89q.worldedit.extent.Extent;
31+
import com.sk89q.worldedit.extent.InputExtent;
3132
import com.sk89q.worldedit.extent.MaskingExtent;
3233
import com.sk89q.worldedit.extent.NullExtent;
3334
import com.sk89q.worldedit.extent.TracingExtent;
@@ -95,6 +96,8 @@
9596
import com.sk89q.worldedit.math.interpolation.Node;
9697
import com.sk89q.worldedit.math.noise.RandomNoise;
9798
import com.sk89q.worldedit.math.transform.AffineTransform;
99+
import com.sk89q.worldedit.math.transform.SimpleTransform;
100+
import com.sk89q.worldedit.math.transform.Transform;
98101
import com.sk89q.worldedit.regions.CuboidRegion;
99102
import com.sk89q.worldedit.regions.CylinderRegion;
100103
import com.sk89q.worldedit.regions.EllipsoidRegion;
@@ -2247,7 +2250,7 @@ public int makeShape(final Region region, final Vector3 zero, final Vector3 unit
22472250
final Variable dataVariable = expression.getSlots().getVariable("data")
22482251
.orElseThrow(IllegalStateException::new);
22492252

2250-
final WorldEditExpressionEnvironment environment = new WorldEditExpressionEnvironment(this, unit, zero);
2253+
final WorldEditExpressionEnvironment environment = new WorldEditExpressionEnvironment(this, new SimpleTransform(zero, unit));
22512254
expression.setEnvironment(environment);
22522255

22532256
final int[] timedOut = {0};
@@ -2314,7 +2317,8 @@ protected BaseBlock getMaterial(int x, int y, int z, BaseBlock defaultMaterial)
23142317
*/
23152318
public int deformRegion(final Region region, final Vector3 zero, final Vector3 unit, final String expressionString)
23162319
throws ExpressionException, MaxChangedBlocksException {
2317-
return deformRegion(region, zero, unit, expressionString, WorldEdit.getInstance().getConfiguration().calculationTimeout);
2320+
final Transform transform = new SimpleTransform(zero, unit);
2321+
return deformRegion(region, transform, expressionString, WorldEdit.getInstance().getConfiguration().calculationTimeout, world, transform);
23182322
}
23192323

23202324
/**
@@ -2333,11 +2337,33 @@ public int deformRegion(final Region region, final Vector3 zero, final Vector3 u
23332337
* @throws ExpressionException thrown on invalid expression input
23342338
* @throws MaxChangedBlocksException thrown if too many blocks are changed
23352339
*/
2340+
@Deprecated
23362341
public int deformRegion(final Region region, final Vector3 zero, final Vector3 unit, final String expressionString,
23372342
final int timeout) throws ExpressionException, MaxChangedBlocksException {
2343+
final Transform transform = new SimpleTransform(zero, unit);
2344+
return deformRegion(region, transform, expressionString, timeout, world, transform);
2345+
}
2346+
2347+
/**
2348+
* Deforms the region by a given expression. A deform provides a block's x, y, and z coordinates (possibly scaled)
2349+
* to an expression, and then sets the block to the block given by the resulting values of the variables, if they
2350+
* have changed.
2351+
*
2352+
* @param region the region to deform
2353+
* @param outputTransform the output coordinate system
2354+
* @param expressionString the expression to evaluate for each block
2355+
* @param timeout maximum time for the expression to evaluate for each block. -1 for unlimited.
2356+
* @param inputExtent the InputExtent to fetch blocks from, for instance a World or a Clipboard
2357+
* @param inputTransform the input coordinate system
2358+
* @return number of blocks changed
2359+
* @throws ExpressionException thrown on invalid expression input
2360+
* @throws MaxChangedBlocksException thrown if too many blocks are changed
2361+
*/
2362+
public int deformRegion(final Region region, final Transform outputTransform, final String expressionString,
2363+
final int timeout, final InputExtent inputExtent, final Transform inputTransform) throws ExpressionException, MaxChangedBlocksException {
23382364
final Expression expression = Expression.compile(expressionString, "x", "y", "z");
23392365
expression.optimize();
2340-
return deformRegion(region, zero, unit, expression, timeout);
2366+
return deformRegion(region, outputTransform, expression, timeout, inputExtent, inputTransform);
23412367
}
23422368

23432369
/**
@@ -2347,32 +2373,47 @@ public int deformRegion(final Region region, final Vector3 zero, final Vector3 u
23472373
* The Expression class is subject to change. Expressions should be provided via the string overload.
23482374
* </p>
23492375
*/
2376+
@Deprecated
23502377
public int deformRegion(final Region region, final Vector3 zero, final Vector3 unit, final Expression expression,
23512378
final int timeout) throws ExpressionException, MaxChangedBlocksException {
2379+
final Transform transform = new SimpleTransform(zero, unit);
2380+
return deformRegion(region, transform, expression, timeout, world, transform);
2381+
}
2382+
2383+
/**
2384+
* Internal version of {@link EditSession#deformRegion(Region, Vector3, Vector3, String, int)}.
2385+
*
2386+
* <p>
2387+
* The Expression class is subject to change. Expressions should be provided via the string overload.
2388+
* </p>
2389+
*/
2390+
public int deformRegion(final Region region, final Transform outputTransform, final Expression expression,
2391+
final int timeout, InputExtent inputExtent, final Transform inputTransform) throws ExpressionException, MaxChangedBlocksException {
23522392
final Variable x = expression.getSlots().getVariable("x")
23532393
.orElseThrow(IllegalStateException::new);
23542394
final Variable y = expression.getSlots().getVariable("y")
23552395
.orElseThrow(IllegalStateException::new);
23562396
final Variable z = expression.getSlots().getVariable("z")
23572397
.orElseThrow(IllegalStateException::new);
23582398

2359-
final WorldEditExpressionEnvironment environment = new WorldEditExpressionEnvironment(this, unit, zero);
2399+
final WorldEditExpressionEnvironment environment = new WorldEditExpressionEnvironment(this, outputTransform);
23602400
expression.setEnvironment(environment);
23612401

23622402
final DoubleArrayList<BlockVector3, BaseBlock> queue = new DoubleArrayList<>(false);
23632403

2404+
final Transform outputTransformInverse = outputTransform.inverse();
23642405
for (BlockVector3 position : region) {
23652406
// transform
2366-
final Vector3 scaled = position.toVector3().subtract(zero).divide(unit);
2407+
final Vector3 scaled = outputTransformInverse.apply(position.toVector3());
23672408

23682409
// deform
23692410
expression.evaluate(new double[]{scaled.getX(), scaled.getY(), scaled.getZ()}, timeout);
23702411

23712412
// untransform, round-nearest
2372-
final BlockVector3 sourcePosition = environment.toWorld(x.getValue(), y.getValue(), z.getValue());
2413+
final BlockVector3 sourcePosition = inputTransform.apply(Vector3.at(x.getValue(), y.getValue(), z.getValue())).add(0.5, 0.5, 0.5).toBlockPoint();
23732414

2374-
// read block from world
2375-
final BaseBlock material = world.getFullBlock(sourcePosition);
2415+
// read block from world/clipboard
2416+
final BaseBlock material = inputExtent.getFullBlock(sourcePosition);
23762417

23772418
// queue operation
23782419
queue.put(position, material);

worldedit-core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -502,14 +502,17 @@ public void deform(Player player, LocalSession localSession,
502502
@Switch(name = 'r', desc = "Use the game's coordinate origin")
503503
boolean useRawCoords,
504504
@Switch(name = 'o', desc = "Use the placement position as the origin")
505-
boolean usePlacement) throws WorldEditException {
505+
boolean usePlacement,
506+
@Switch(name = 'l', desc = "Fetch from the clipboard instead of the world")
507+
boolean useClipboard) throws WorldEditException {
506508
Deform deform = new Deform(expression);
507509
if (useRawCoords) {
508510
deform.setMode(Deform.Mode.RAW_COORD);
509511
} else if (usePlacement) {
510512
deform.setMode(Deform.Mode.OFFSET);
511513
deform.setOffset(localSession.getPlacementPosition(player).toVector3());
512514
}
515+
deform.setUseClipboard(useClipboard);
513516
setOperationBasedBrush(player, localSession, radius,
514517
deform, shape, "worldedit.brush.deform");
515518
}

worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java

+64-30
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
import com.sk89q.worldedit.command.util.Logging;
3030
import com.sk89q.worldedit.entity.Player;
3131
import com.sk89q.worldedit.extension.platform.Actor;
32+
import com.sk89q.worldedit.extent.InputExtent;
33+
import com.sk89q.worldedit.extent.clipboard.Clipboard;
3234
import com.sk89q.worldedit.function.GroundFunction;
3335
import com.sk89q.worldedit.function.RegionFunction;
3436
import com.sk89q.worldedit.function.block.BlockReplace;
@@ -51,6 +53,9 @@
5153
import com.sk89q.worldedit.math.convolution.HeightMapFilter;
5254
import com.sk89q.worldedit.math.convolution.SnowHeightMap;
5355
import com.sk89q.worldedit.math.noise.RandomNoise;
56+
import com.sk89q.worldedit.math.transform.Identity;
57+
import com.sk89q.worldedit.math.transform.SimpleTransform;
58+
import com.sk89q.worldedit.math.transform.Transform;
5459
import com.sk89q.worldedit.regions.ConvexPolyhedralRegion;
5560
import com.sk89q.worldedit.regions.CuboidRegion;
5661
import com.sk89q.worldedit.regions.Region;
@@ -464,6 +469,44 @@ void regenerate(Actor actor, World world, LocalSession session, EditSession edit
464469
}
465470
}
466471

472+
/**
473+
* Creates a {@link Transform} for the //deform command.
474+
*
475+
* @param useRawCoords Use the game's coordinate origin
476+
* @param offsetPlacement Use the placement's coordinate origin
477+
* @param offsetCenter Use the selection's center as origin
478+
* @param min Minimum of the selection/clipboard
479+
* @param max Maximum of the selection/clipboard
480+
* @param placement Placement position
481+
* @return A transform from the expression coordinate sytem to the world/clipboard coordinate system
482+
*/
483+
private static Transform createTransform(boolean useRawCoords, boolean offsetPlacement, boolean offsetCenter, Vector3 min, Vector3 max, Vector3 placement) {
484+
if (useRawCoords) {
485+
return new Identity();
486+
} else if (offsetPlacement) {
487+
return new SimpleTransform(placement, Vector3.ONE);
488+
} else {
489+
final Vector3 offset = max.add(min).multiply(0.5);
490+
491+
if (offsetCenter) {
492+
return new SimpleTransform(offset, Vector3.ONE);
493+
}
494+
495+
Vector3 scale = max.subtract(offset);
496+
497+
if (scale.getX() == 0) {
498+
scale = scale.withX(1.0);
499+
}
500+
if (scale.getY() == 0) {
501+
scale = scale.withY(1.0);
502+
}
503+
if (scale.getZ() == 0) {
504+
scale = scale.withZ(1.0);
505+
}
506+
return new SimpleTransform(offset, scale);
507+
}
508+
}
509+
467510
@Command(
468511
name = "/deform",
469512
desc = "Deforms a selected region with an expression",
@@ -482,42 +525,33 @@ public int deform(Actor actor, LocalSession session, EditSession editSession,
482525
@Switch(name = 'o', desc = "Use the placement's coordinate origin")
483526
boolean offsetPlacement,
484527
@Switch(name = 'c', desc = "Use the selection's center as origin")
485-
boolean offsetCenter) throws WorldEditException {
486-
final Vector3 zero;
487-
Vector3 unit;
528+
boolean offsetCenter,
529+
@Switch(name = 'l', desc = "Fetch from the clipboard instead of the world")
530+
boolean useClipboard) throws WorldEditException {
488531

489-
if (useRawCoords) {
490-
zero = Vector3.ZERO;
491-
unit = Vector3.ONE;
492-
} else if (offsetPlacement) {
493-
zero = session.getPlacementPosition(actor).toVector3();
494-
unit = Vector3.ONE;
495-
} else if (offsetCenter) {
496-
final Vector3 min = region.getMinimumPoint().toVector3();
497-
final Vector3 max = region.getMaximumPoint().toVector3();
498-
499-
zero = max.add(min).multiply(0.5);
500-
unit = Vector3.ONE;
501-
} else {
502-
final Vector3 min = region.getMinimumPoint().toVector3();
503-
final Vector3 max = region.getMaximumPoint().toVector3();
532+
final Vector3 min = region.getMinimumPoint().toVector3();
533+
final Vector3 max = region.getMaximumPoint().toVector3();
534+
final Vector3 placement = session.getPlacementPosition(actor).toVector3();
504535

505-
zero = max.add(min).divide(2);
506-
unit = max.subtract(zero);
536+
final Transform outputTransform = createTransform(useRawCoords, offsetPlacement, offsetCenter, min, max, placement);
507537

508-
if (unit.getX() == 0) {
509-
unit = unit.withX(1.0);
510-
}
511-
if (unit.getY() == 0) {
512-
unit = unit.withY(1.0);
513-
}
514-
if (unit.getZ() == 0) {
515-
unit = unit.withZ(1.0);
516-
}
538+
final InputExtent inputExtent;
539+
final Transform inputTransform;
540+
if (useClipboard) {
541+
final Clipboard clipboard = session.getClipboard().getClipboard();
542+
inputExtent = clipboard;
543+
544+
final Vector3 clipboardMin = clipboard.getMinimumPoint().toVector3();
545+
final Vector3 clipboardMax = clipboard.getMaximumPoint().toVector3();
546+
547+
inputTransform = createTransform(useRawCoords, offsetPlacement, offsetCenter, clipboardMin, clipboardMax, clipboardMin);
548+
} else {
549+
inputExtent = editSession.getWorld();
550+
inputTransform = outputTransform;
517551
}
518552

519553
try {
520-
final int affected = editSession.deformRegion(region, zero, unit, String.join(" ", expression), session.getTimeout());
554+
final int affected = editSession.deformRegion(region, outputTransform, String.join(" ", expression), session.getTimeout(), inputExtent, inputTransform);
521555
if (actor instanceof Player) {
522556
((Player) actor).findFreePosition();
523557
}

0 commit comments

Comments
 (0)