Skip to content

Commit

Permalink
Add inputExtent parameter and separate in/outputTransform for deformR…
Browse files Browse the repository at this point in the history
…egion
  • Loading branch information
TomyLobo committed Jul 25, 2024
1 parent 17e28bc commit cb59fab
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 14 deletions.
47 changes: 35 additions & 12 deletions worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import com.sk89q.worldedit.extension.platform.Watchdog;
import com.sk89q.worldedit.extent.ChangeSetExtent;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.extent.InputExtent;
import com.sk89q.worldedit.extent.MaskingExtent;
import com.sk89q.worldedit.extent.NullExtent;
import com.sk89q.worldedit.extent.TracingExtent;
Expand Down Expand Up @@ -2451,6 +2452,28 @@ public int deformRegion(final Region region, final Vector3 zero, final Vector3 u
return deformRegion(region, transform, expressionString, timeout);
}

/**
* Deforms the region by a given expression. A deform provides a block's x, y, and z coordinates (possibly scaled)
* to an expression, and then sets the block to the block given by the resulting values of the variables, if they
* have changed.
*
* @param region the region to deform
* @param targetTransform the target coordinate system
* @param expressionString the expression to evaluate for each block
* @param timeout maximum time for the expression to evaluate for each block. -1 for unlimited.
* @param sourceExtent the InputExtent to fetch blocks from, for instance a World or a Clipboard
* @param sourceTransform the source coordinate system
* @return number of blocks changed
* @throws ExpressionException thrown on invalid expression input
* @throws MaxChangedBlocksException thrown if too many blocks are changed
*/
public int deformRegion(final Region region, final Transform targetTransform, final String expressionString,
final int timeout, InputExtent sourceExtent, Transform sourceTransform) throws ExpressionException, MaxChangedBlocksException {
final Expression expression = Expression.compile(expressionString, "x", "y", "z");
expression.optimize();
return deformRegion(region, targetTransform, expression, timeout, sourceExtent, sourceTransform);
}

/**
* Deforms the region by a given expression. A deform provides a block's x, y, and z coordinates (possibly scaled)
* to an expression, and then sets the block to the block given by the resulting values of the variables, if they
Expand All @@ -2464,11 +2487,10 @@ public int deformRegion(final Region region, final Vector3 zero, final Vector3 u
* @throws ExpressionException thrown on invalid expression input
* @throws MaxChangedBlocksException thrown if too many blocks are changed
*/
@Deprecated
public int deformRegion(final Region region, final Transform transform, final String expressionString,
final int timeout) throws ExpressionException, MaxChangedBlocksException {
final Expression expression = Expression.compile(expressionString, "x", "y", "z");
expression.optimize();
return deformRegion(region, transform, expression, timeout);
return deformRegion(region, transform, expressionString, timeout, world, transform);
}

/**
Expand All @@ -2481,7 +2503,8 @@ public int deformRegion(final Region region, final Transform transform, final St
@Deprecated
public int deformRegion(final Region region, final Vector3 zero, final Vector3 unit, final Expression expression,
final int timeout) throws ExpressionException, MaxChangedBlocksException {
return deformRegion(region, new ScaleAndTranslateTransform(zero, unit), expression, timeout);
final Transform transform = new ScaleAndTranslateTransform(zero, unit);
return deformRegion(region, transform, expression, timeout, world, transform);
}

/**
Expand All @@ -2491,37 +2514,37 @@ public int deformRegion(final Region region, final Vector3 zero, final Vector3 u
* The Expression class is subject to change. Expressions should be provided via the string overload.
* </p>
*/
public int deformRegion(final Region region, final Transform transform, final Expression expression,
final int timeout) throws ExpressionException, MaxChangedBlocksException {
public int deformRegion(final Region region, final Transform targetTransform, final Expression expression,
final int timeout, InputExtent sourceExtent, final Transform sourceTransform) throws ExpressionException, MaxChangedBlocksException {
final Variable x = expression.getSlots().getVariable("x")
.orElseThrow(IllegalStateException::new);
final Variable y = expression.getSlots().getVariable("y")
.orElseThrow(IllegalStateException::new);
final Variable z = expression.getSlots().getVariable("z")
.orElseThrow(IllegalStateException::new);

final WorldEditExpressionEnvironment environment = new WorldEditExpressionEnvironment(this, transform);
final WorldEditExpressionEnvironment environment = new WorldEditExpressionEnvironment(this, targetTransform);
expression.setEnvironment(environment);

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

final Transform transformInverse = transform.inverse();
final Transform targetTransformInverse = targetTransform.inverse();
for (BlockVector3 targetBlockPosition : region) {
final Vector3 targetPosition = targetBlockPosition.toVector3();
environment.setCurrentBlock(targetPosition);

// transform from target coordinates
final Vector3 inputPosition = transformInverse.apply(targetPosition);
final Vector3 inputPosition = targetTransformInverse.apply(targetPosition);

// deform
expression.evaluate(new double[]{ inputPosition.x(), inputPosition.y(), inputPosition.z() }, timeout);
final Vector3 outputPosition = Vector3.at(x.value(), y.value(), z.value());

// transform to source coordinates, round-nearest
final BlockVector3 sourcePosition = transform.apply(outputPosition).add(0.5, 0.5, 0.5).toBlockPoint();
final BlockVector3 sourcePosition = sourceTransform.apply(outputPosition).add(0.5, 0.5, 0.5).toBlockPoint();

// read block from world
final BaseBlock material = world.getFullBlock(sourcePosition);
// read block from source extent (e.g. world/clipboard)
final BaseBlock material = sourceExtent.getFullBlock(sourcePosition);

// queue operation
queue.put(targetBlockPosition, material);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
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.function.GroundFunction;
import com.sk89q.worldedit.function.RegionFunction;
Expand Down Expand Up @@ -501,9 +502,10 @@ public int deform(Actor actor, LocalSession session, EditSession editSession,
boolean offsetCenter) throws WorldEditException {

final Transform transform = TransformUtil.createTransformForExpressionCommand(actor, session, region, useRawCoords, offsetPlacement, offsetCenter);
final InputExtent inputExtent = editSession.getWorld();

try {
final int affected = editSession.deformRegion(region, transform, String.join(" ", expression), session.getTimeout());
final int affected = editSession.deformRegion(region, transform, String.join(" ", expression), session.getTimeout(), inputExtent, transform);
if (actor instanceof Player) {
((Player) actor).findFreePosition();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,8 @@ private record DeformOperation(
public Operation resume(RunContext run) throws WorldEditException {
try {
// TODO: Move deformation code
((EditSession) destination).deformRegion(region, transform, expression, timeout);
final EditSession editSession = (EditSession) destination;
editSession.deformRegion(region, transform, expression, timeout, editSession.getWorld(), transform);
return null;
} catch (ExpressionException e) {
throw new RuntimeException("Failed to execute expression", e); // TODO: Better exception to throw here?
Expand Down

0 comments on commit cb59fab

Please sign in to comment.