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 //deform #2276

Open
wants to merge 8 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 @@ -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.RegionMaskingFilter;
Expand All @@ -49,13 +51,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 @@ -498,44 +502,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 @@ -33,6 +33,9 @@
import com.sk89q.worldedit.internal.expression.Expression;
import com.sk89q.worldedit.internal.expression.ExpressionException;
import com.sk89q.worldedit.math.Vector3;
import com.sk89q.worldedit.math.transform.Identity;
import com.sk89q.worldedit.math.transform.ScaleAndTranslateTransform;
import com.sk89q.worldedit.math.transform.Transform;
import com.sk89q.worldedit.regions.NullRegion;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.formatting.text.Component;
Expand Down Expand Up @@ -118,18 +121,16 @@ public String toString() {

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

Region region = firstNonNull(context.getRegion(), this.region);

final Transform transform;
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);
final Vector3 zero = max.add(min).multiply(0.5);
Vector3 unit = max.subtract(zero);

if (unit.x() == 0) {
unit = unit.withX(1.0);
Expand All @@ -140,35 +141,37 @@ public Operation createFromContext(final EditContext context) {
if (unit.z() == 0) {
unit = unit.withZ(1.0);
}

transform = new ScaleAndTranslateTransform(zero, unit);
break;

case RAW_COORD:
zero = Vector3.ZERO;
unit = Vector3.ONE;
transform = new Identity();
break;

case OFFSET:
default:
zero = offset;
unit = Vector3.ONE;
transform = new ScaleAndTranslateTransform(offset, Vector3.ONE);
break;
}

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

private record DeformOperation(
Extent destination,
Region region,
Vector3 zero,
Vector3 unit,
Transform transform,
Expression expression,
int timeout
) 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, 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
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

package com.sk89q.worldedit.internal.util;

import com.sk89q.worldedit.IncompleteRegionException;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.math.Vector3;
import com.sk89q.worldedit.math.transform.Identity;
import com.sk89q.worldedit.math.transform.ScaleAndTranslateTransform;
import com.sk89q.worldedit.math.transform.Transform;
import com.sk89q.worldedit.regions.Region;

/**
* Various internal utility methods related to {@link Transform}s.
*/
public final class TransformUtil {

private TransformUtil() {
}

/**
* Creates a {@link Transform} for various expression commands.
*
* @param actor Actor that ran the command
* @param session Session that the command was run in
* @param region Selection that the command was run in
* @param useRawCoords Use the game's coordinate origin
* @param offsetPlacement Use the placement's coordinate origin
* @param offsetCenter Use the selection's center as origin
* @return A transform from the expression coordinate system to the raw coordinate system
*/
public static Transform createTransformForExpressionCommand(Actor actor, LocalSession session, Region region, boolean useRawCoords, boolean offsetPlacement, boolean offsetCenter) throws IncompleteRegionException {
final Vector3 placement = session.getPlacementPosition(actor).toVector3();
final Vector3 min = region.getMinimumPoint().toVector3();
final Vector3 max = region.getMaximumPoint().toVector3();

return createTransformForExpressionCommand(useRawCoords, offsetPlacement, offsetCenter, min, max, placement);
}

/**
* Creates a {@link Transform} for the //deform command with clipboard support.
*
* @param useRawCoords Use the game's coordinate origin
* @param offsetPlacement Use the placement's coordinate origin
* @param offsetCenter Use the selection's center as origin
* @param min Minimum of the selection/clipboard
* @param max Maximum of the selection/clipboard
* @param placement Placement position
* @return A transform from the expression coordinate system to the world/clipboard coordinate system
*/
public static Transform createTransformForExpressionCommand(boolean useRawCoords, boolean offsetPlacement, boolean offsetCenter, Vector3 min, Vector3 max, Vector3 placement) {
if (useRawCoords) {
return new Identity();
}

if (offsetPlacement) {
return new ScaleAndTranslateTransform(placement, Vector3.ONE);
}

final Vector3 center = max.add(min).multiply(0.5);

if (offsetCenter) {
return new ScaleAndTranslateTransform(center, Vector3.ONE);
}

Vector3 scale = max.subtract(center);

if (scale.x() == 0) {
scale = scale.withX(1.0);
}
if (scale.y() == 0) {
scale = scale.withY(1.0);
}
if (scale.z() == 0) {
scale = scale.withZ(1.0);
}
return new ScaleAndTranslateTransform(center, scale);
}
}
Loading