Off axis rotation
This commit is contained in:
parent
920095a2de
commit
3c4a709efc
@ -469,12 +469,6 @@ public class ClipboardCommands extends MethodCommands {
|
||||
)
|
||||
@CommandPermissions("worldedit.clipboard.rotate")
|
||||
public void rotate(Player player, LocalSession session, Double yRotate, @Optional Double xRotate, @Optional Double zRotate) throws WorldEditException {
|
||||
if ((yRotate != null && Math.abs(yRotate % 90) > 0.001) ||
|
||||
xRotate != null && Math.abs(xRotate % 90) > 0.001 ||
|
||||
zRotate != null && Math.abs(zRotate % 90) > 0.001) {
|
||||
player.printDebug("Note: Interpolation is not yet supported, so angles that are multiples of 90 is recommended.");
|
||||
}
|
||||
|
||||
ClipboardHolder holder = session.getClipboard();
|
||||
AffineTransform transform = new AffineTransform();
|
||||
transform = transform.rotateY(-(yRotate != null ? yRotate : 0));
|
||||
|
@ -0,0 +1,82 @@
|
||||
package com.sk89q.worldedit.function.operation;
|
||||
|
||||
import com.sk89q.worldedit.MutableBlockVector;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.function.RegionFunction;
|
||||
import com.sk89q.worldedit.math.transform.Transform;
|
||||
import com.sk89q.worldedit.regions.CuboidRegion;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import java.util.List;
|
||||
|
||||
public class BackwardsExtentBlockCopy implements Operation {
|
||||
private final Region region;
|
||||
private final Transform transform;
|
||||
private final Extent destination;
|
||||
private final Extent source;
|
||||
private final RegionFunction function;
|
||||
private final Vector origin;
|
||||
|
||||
private Vector mutable = new MutableBlockVector();
|
||||
|
||||
public BackwardsExtentBlockCopy(Extent source, Region region, Extent destination, Vector origin, Transform transform, RegionFunction function) {
|
||||
this.source = source;
|
||||
this.region = region;
|
||||
this.destination = destination;
|
||||
this.transform = transform;
|
||||
this.function = function;
|
||||
this.origin = origin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Operation resume(RunContext run) throws WorldEditException {
|
||||
CuboidRegion destRegion = transform(this.transform, this.region);
|
||||
Transform inverse = this.transform.inverse();
|
||||
for (Vector pt : destRegion) {
|
||||
Vector copyFrom = transform(inverse, pt);
|
||||
if (region.contains(copyFrom)) {
|
||||
function.apply(pt);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private CuboidRegion transform(Transform transform, Region region) {
|
||||
Vector min = new MutableBlockVector(Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE);
|
||||
Vector max = new MutableBlockVector(Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MIN_VALUE);
|
||||
Vector pos1 = region.getMinimumPoint();
|
||||
Vector pos2 = region.getMaximumPoint();
|
||||
for (int x : new int[] { pos1.getBlockX(), pos2.getBlockX() }) {
|
||||
for (int y : new int[] { pos1.getBlockY(), pos2.getBlockY() }) {
|
||||
for (int z : new int[] { pos1.getBlockZ(), pos2.getBlockZ() }) {
|
||||
Vector pt = transform(transform, new Vector(x, y, z)).toBlockVector();
|
||||
min = Vector.getMinimum(min, pt);
|
||||
max = Vector.getMaximum(max, pt);
|
||||
}
|
||||
}
|
||||
}
|
||||
return new CuboidRegion(min, max);
|
||||
}
|
||||
|
||||
private Vector transform(Transform transform, Vector pt) {
|
||||
mutable.mutX(((pt.getBlockX() - origin.getBlockX())));
|
||||
mutable.mutY(((pt.getBlockY() - origin.getBlockY())));
|
||||
mutable.mutZ(((pt.getBlockZ() - origin.getBlockZ())));
|
||||
Vector tmp = transform.apply(mutable);
|
||||
tmp.mutX((tmp.getBlockX() + origin.getBlockX()));
|
||||
tmp.mutY((tmp.getBlockY() + origin.getBlockY()));
|
||||
tmp.mutZ((tmp.getBlockZ() + origin.getBlockZ()));
|
||||
return tmp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addStatusMessages(List<String> messages) {
|
||||
|
||||
}
|
||||
}
|
@ -39,6 +39,7 @@ import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.function.mask.Masks;
|
||||
import com.sk89q.worldedit.function.visitor.EntityVisitor;
|
||||
import com.sk89q.worldedit.function.visitor.RegionVisitor;
|
||||
import com.sk89q.worldedit.math.transform.AffineTransform;
|
||||
import com.sk89q.worldedit.math.transform.Identity;
|
||||
import com.sk89q.worldedit.math.transform.Transform;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
@ -253,30 +254,50 @@ public class ForwardExtentCopy implements Operation {
|
||||
if (!translation.equals(Vector.ZERO)) {
|
||||
finalDest = new BlockTranslateExtent(finalDest, translation.getBlockX(), translation.getBlockY(), translation.getBlockZ());
|
||||
}
|
||||
PositionTransformExtent transExt;
|
||||
|
||||
Operation blockCopy = null;
|
||||
PositionTransformExtent transExt = null;
|
||||
if (!currentTransform.isIdentity()) {
|
||||
transExt = new PositionTransformExtent(finalDest, currentTransform);
|
||||
transExt.setOrigin(from);
|
||||
finalDest = transExt;
|
||||
} else {
|
||||
transExt = null;
|
||||
if (!(currentTransform instanceof AffineTransform) || ((AffineTransform) currentTransform).isOffAxis()) {
|
||||
transExt = new PositionTransformExtent(source, currentTransform.inverse());
|
||||
transExt.setOrigin(from);
|
||||
|
||||
RegionFunction copy = new SimpleBlockCopy(transExt, finalDest);
|
||||
if (sourceMask != Masks.alwaysTrue()) {
|
||||
copy = new RegionMaskingFilter(sourceMask, copy);
|
||||
}
|
||||
if (sourceFunction != null) {
|
||||
copy = new CombinedRegionFunction(copy, sourceFunction);
|
||||
}
|
||||
if (copyBiomes && (!(source instanceof BlockArrayClipboard) || ((BlockArrayClipboard) source).IMP.hasBiomes())) {
|
||||
copy = new CombinedRegionFunction(copy, new BiomeCopy(source, finalDest));
|
||||
}
|
||||
blockCopy = new BackwardsExtentBlockCopy(transExt, region, finalDest, from, transform, copy);
|
||||
} else {
|
||||
transExt = new PositionTransformExtent(finalDest, currentTransform);
|
||||
transExt.setOrigin(from);
|
||||
finalDest = transExt;
|
||||
}
|
||||
}
|
||||
RegionFunction copy = new SimpleBlockCopy(source, finalDest);
|
||||
if (sourceMask != Masks.alwaysTrue()) {
|
||||
copy = new RegionMaskingFilter(sourceMask, copy);
|
||||
|
||||
if (blockCopy == null) {
|
||||
RegionFunction copy = new SimpleBlockCopy(source, finalDest);
|
||||
if (sourceMask != Masks.alwaysTrue()) {
|
||||
copy = new RegionMaskingFilter(sourceMask, copy);
|
||||
}
|
||||
if (sourceFunction != null) {
|
||||
copy = new CombinedRegionFunction(copy, sourceFunction);
|
||||
}
|
||||
if (copyBiomes && (!(source instanceof BlockArrayClipboard) || ((BlockArrayClipboard) source).IMP.hasBiomes())) {
|
||||
copy = new CombinedRegionFunction(copy, new BiomeCopy(source, finalDest));
|
||||
}
|
||||
blockCopy = new RegionVisitor(region, copy, queue instanceof MappedFaweQueue ? (MappedFaweQueue) queue : null);
|
||||
}
|
||||
if (sourceFunction != null) {
|
||||
copy = new CombinedRegionFunction(copy, sourceFunction);
|
||||
}
|
||||
if (copyBiomes && (!(source instanceof BlockArrayClipboard) || ((BlockArrayClipboard) source).IMP.hasBiomes())) {
|
||||
copy = new CombinedRegionFunction(copy, new BiomeCopy(source, finalDest));
|
||||
}
|
||||
RegionVisitor blockVisitor = new RegionVisitor(region, copy, queue instanceof MappedFaweQueue ? (MappedFaweQueue) queue : null);
|
||||
|
||||
List<? extends Entity> entities = isCopyEntities() ? source.getEntities(region) : new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < repetitions; i++) {
|
||||
Operations.completeBlindly(blockVisitor);
|
||||
Operations.completeBlindly(blockCopy);
|
||||
|
||||
if (!entities.isEmpty()) {
|
||||
ExtentEntityCopy entityCopy = new ExtentEntityCopy(from, destination, to, currentTransform);
|
||||
@ -291,7 +312,7 @@ public class ForwardExtentCopy implements Operation {
|
||||
}
|
||||
|
||||
}
|
||||
affected = blockVisitor.getAffected();
|
||||
affected = region.getArea();
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -133,6 +133,18 @@ public class AffineTransform implements Transform, Serializable {
|
||||
return new double[]{m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23};
|
||||
}
|
||||
|
||||
public boolean isOffAxis() {
|
||||
double[] c = coefficients();
|
||||
for (int i = 0; i < c.length; i++) {
|
||||
if ((i + 1) % 4 != 0) {
|
||||
if (Math.abs(c[i]) != 1 && c[i] != 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the determinant of this transform. Can be zero.
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user