*More off axis rotation changes
Fix off axis rotation for certain angles - Math error when calculating the inverse affine transform Add -a flag to copyPaste brush (rotates based on view)
This commit is contained in:
parent
70e1e00e23
commit
d14b267cfd
@ -24,18 +24,20 @@ import com.sk89q.worldedit.function.visitor.RecursiveVisitor;
|
|||||||
import com.sk89q.worldedit.math.transform.AffineTransform;
|
import com.sk89q.worldedit.math.transform.AffineTransform;
|
||||||
import com.sk89q.worldedit.regions.Region;
|
import com.sk89q.worldedit.regions.Region;
|
||||||
import com.sk89q.worldedit.session.ClipboardHolder;
|
import com.sk89q.worldedit.session.ClipboardHolder;
|
||||||
|
import com.sk89q.worldedit.util.Location;
|
||||||
|
|
||||||
public class CopyPastaBrush implements Brush, ResettableTool {
|
public class CopyPastaBrush implements Brush, ResettableTool {
|
||||||
|
|
||||||
private final LocalSession session;
|
private final LocalSession session;
|
||||||
private final boolean randomRotate;
|
|
||||||
private final Player player;
|
private final Player player;
|
||||||
|
public boolean autoRotate, randomRotate;
|
||||||
|
|
||||||
public CopyPastaBrush(Player player, LocalSession session, boolean randomRotate) {
|
public CopyPastaBrush(Player player, LocalSession session, boolean randomRotate, boolean autoRotate) {
|
||||||
session.setClipboard(null);
|
session.setClipboard(null);
|
||||||
this.player = player;
|
this.player = player;
|
||||||
this.session = session;
|
this.session = session;
|
||||||
this.randomRotate = randomRotate;
|
this.randomRotate = randomRotate;
|
||||||
|
this.autoRotate = autoRotate;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -65,7 +67,7 @@ public class CopyPastaBrush implements Brush, ResettableTool {
|
|||||||
public boolean test(Vector vector) {
|
public boolean test(Vector vector) {
|
||||||
if (super.test(vector) && vector.getBlockY() >= minY) {
|
if (super.test(vector) && vector.getBlockY() >= minY) {
|
||||||
BaseBlock block = editSession.getLazyBlock(vector);
|
BaseBlock block = editSession.getLazyBlock(vector);
|
||||||
if (block != EditSession.nullBlock) {
|
if (block.getId() != 0) {
|
||||||
builder.add(vector, EditSession.nullBlock, block);
|
builder.add(vector, EditSession.nullBlock, block);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -87,19 +89,33 @@ public class CopyPastaBrush implements Brush, ResettableTool {
|
|||||||
BBC.COMMAND_COPY.send(fp, blocks);
|
BBC.COMMAND_COPY.send(fp, blocks);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
|
AffineTransform transform = null;
|
||||||
if (randomRotate) {
|
if (randomRotate) {
|
||||||
|
if (transform == null) transform = new AffineTransform();
|
||||||
int rotate = 90 * PseudoRandom.random.nextInt(4);
|
int rotate = 90 * PseudoRandom.random.nextInt(4);
|
||||||
clipboard.setTransform(rotate != 0 ? new AffineTransform().rotateY(rotate) : new AffineTransform());
|
transform = transform.rotateY(rotate);
|
||||||
|
}
|
||||||
|
if (autoRotate) {
|
||||||
|
if (transform == null) transform = new AffineTransform();
|
||||||
|
Location loc = editSession.getPlayer().getPlayer().getLocation();
|
||||||
|
float yaw = loc.getYaw();
|
||||||
|
float pitch = loc.getPitch();
|
||||||
|
transform = transform.rotateY((-yaw) % 360);
|
||||||
|
transform = transform.rotateX(pitch - 90);
|
||||||
|
}
|
||||||
|
if (transform != null && !transform.isIdentity()) {
|
||||||
|
clipboard.setTransform(transform);
|
||||||
}
|
}
|
||||||
Clipboard faweClip = clipboard.getClipboard();
|
Clipboard faweClip = clipboard.getClipboard();
|
||||||
Region region = faweClip.getRegion();
|
Region region = faweClip.getRegion();
|
||||||
Vector centerOffset = region.getCenter().subtract(faweClip.getOrigin());
|
|
||||||
Operation operation = clipboard
|
Operation operation = clipboard
|
||||||
.createPaste(editSession, editSession.getWorld().getWorldData())
|
.createPaste(editSession, editSession.getWorldData())
|
||||||
.to(position.add(0, 1, 0))
|
.to(position.add(0, 1, 0))
|
||||||
.ignoreAirBlocks(true)
|
.ignoreAirBlocks(true)
|
||||||
.build();
|
.build();
|
||||||
Operations.completeLegacy(operation);
|
Operations.completeLegacy(operation);
|
||||||
|
editSession.flushQueue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ public class PopulateSchem implements Brush {
|
|||||||
public void build(EditSession editSession, Vector position, Pattern pattern, double size) throws MaxChangedBlocksException {
|
public void build(EditSession editSession, Vector position, Pattern pattern, double size) throws MaxChangedBlocksException {
|
||||||
new MaskTraverser(mask).reset(editSession);
|
new MaskTraverser(mask).reset(editSession);
|
||||||
SchemGen gen = new SchemGen(mask, editSession, editSession.getWorldData(), clipboards, randomRotate);
|
SchemGen gen = new SchemGen(mask, editSession, editSession.getWorldData(), clipboards, randomRotate);
|
||||||
CuboidRegion cuboid = new CuboidRegion(position.subtract(size, size, size), position.add(size, size, size));
|
CuboidRegion cuboid = new CuboidRegion(editSession.getWorld(), position.subtract(size, size, size), position.add(size, size, size));
|
||||||
try {
|
try {
|
||||||
editSession.addSchems(cuboid, mask, editSession.getWorldData(), clipboards, rarity, randomRotate);
|
editSession.addSchems(cuboid, mask, editSession.getWorldData(), clipboards, rarity, randomRotate);
|
||||||
} catch (WorldEditException e) {
|
} catch (WorldEditException e) {
|
||||||
|
@ -7,6 +7,7 @@ import com.sk89q.worldedit.command.tool.brush.Brush;
|
|||||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||||
|
|
||||||
public class SpikeBrush implements Brush {
|
public class SpikeBrush implements Brush {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void build(EditSession editSession, Vector position, Pattern pattern, double size) throws MaxChangedBlocksException {
|
public void build(EditSession editSession, Vector position, Pattern pattern, double size) throws MaxChangedBlocksException {
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ public class StencilBrush extends HeightBrush {
|
|||||||
int cutoff = onlyWhite ? maxY : 0;
|
int cutoff = onlyWhite ? maxY : 0;
|
||||||
final SolidBlockMask solid = new SolidBlockMask(editSession);
|
final SolidBlockMask solid = new SolidBlockMask(editSession);
|
||||||
final AdjacentAnyMask adjacent = new AdjacentAnyMask(Masks.negate(solid));
|
final AdjacentAnyMask adjacent = new AdjacentAnyMask(Masks.negate(solid));
|
||||||
RegionMask region = new RegionMask(new CuboidRegion(position.subtract(size, size, size), position.add(size, size, size)));
|
RegionMask region = new RegionMask(new CuboidRegion(editSession.getWorld(), position.subtract(size, size, size), position.add(size, size, size)));
|
||||||
RecursiveVisitor visitor = new RecursiveVisitor(new Mask() {
|
RecursiveVisitor visitor = new RecursiveVisitor(new Mask() {
|
||||||
@Override
|
@Override
|
||||||
public boolean test(Vector vector) {
|
public boolean test(Vector vector) {
|
||||||
|
@ -3,7 +3,6 @@ package com.boydti.fawe.object.brush.heightmap;
|
|||||||
import com.boydti.fawe.object.IntegerPair;
|
import com.boydti.fawe.object.IntegerPair;
|
||||||
import com.boydti.fawe.util.MainUtil;
|
import com.boydti.fawe.util.MainUtil;
|
||||||
import com.boydti.fawe.util.MathMan;
|
import com.boydti.fawe.util.MathMan;
|
||||||
import com.sk89q.worldedit.EditSession;
|
|
||||||
import com.sk89q.worldedit.Vector;
|
import com.sk89q.worldedit.Vector;
|
||||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||||
@ -79,7 +78,7 @@ public class ScalableHeightMap implements com.boydti.fawe.object.brush.heightmap
|
|||||||
for (int y = minY; y <= maxY; y++) {
|
for (int y = minY; y <= maxY; y++) {
|
||||||
pos.mutY(y);
|
pos.mutY(y);
|
||||||
BaseBlock block = clipboard.getBlock(pos);
|
BaseBlock block = clipboard.getBlock(pos);
|
||||||
if (block != EditSession.nullBlock) {
|
if (block.getId() != 0) {
|
||||||
highestY = y + 1;
|
highestY = y + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -114,7 +114,7 @@ public class PNGWriter implements ClipboardWriter {
|
|||||||
mutableTop.mutY(y + 1);
|
mutableTop.mutY(y + 1);
|
||||||
mutableRight.mutY(y);
|
mutableRight.mutY(y);
|
||||||
mutableLeft.mutY(y);
|
mutableLeft.mutY(y);
|
||||||
if (clipboard.getBlock(mutableTop) != EditSession.nullBlock && clipboard.getBlock(mutableRight) != EditSession.nullBlock && clipboard.getBlock(mutableLeft) != EditSession.nullBlock) {
|
if (clipboard.getBlock(mutableTop).getId() != 0 && clipboard.getBlock(mutableRight) != EditSession.nullBlock && clipboard.getBlock(mutableLeft).getId() != 0 ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
double cpy = cpy2 - dpxi[y - y0];
|
double cpy = cpy2 - dpxi[y - y0];
|
||||||
|
@ -1430,13 +1430,13 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
|
|||||||
int freeSpot = startCheckY;
|
int freeSpot = startCheckY;
|
||||||
for (int y = startCheckY; y <= endY; y++) {
|
for (int y = startCheckY; y <= endY; y++) {
|
||||||
if (y < startPerformY) {
|
if (y < startPerformY) {
|
||||||
if (getLazyBlock(x, y, z) != EditSession.nullBlock) {
|
if (getLazyBlock(x, y, z).getId() != 0) {
|
||||||
freeSpot = y + 1;
|
freeSpot = y + 1;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
BaseBlock block = getLazyBlock(x, y, z);
|
BaseBlock block = getLazyBlock(x, y, z);
|
||||||
if (block != EditSession.nullBlock) {
|
if (block.getId() != 0) {
|
||||||
if (freeSpot != y) {
|
if (freeSpot != y) {
|
||||||
setBlock(x, freeSpot, z, block);
|
setBlock(x, freeSpot, z, block);
|
||||||
setBlock(x, y, z, replace);
|
setBlock(x, y, z, replace);
|
||||||
@ -2217,11 +2217,11 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
|
|||||||
return makeCylinder(pos, block, radiusX, radiusZ, height, 0, filled);
|
return makeCylinder(pos, block, radiusX, radiusZ, height, 0, filled);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int makeHollowCylinder(Vector pos, final Pattern block, double radiusX, double radiusZ, int height, int thickness) {
|
public int makeHollowCylinder(Vector pos, final Pattern block, double radiusX, double radiusZ, int height, double thickness) {
|
||||||
return makeCylinder(pos, block, radiusX, radiusZ, height, thickness, false);
|
return makeCylinder(pos, block, radiusX, radiusZ, height, thickness, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int makeCylinder(Vector pos, final Pattern block, double radiusX, double radiusZ, int height, int thickness, final boolean filled) {
|
private int makeCylinder(Vector pos, final Pattern block, double radiusX, double radiusZ, int height, double thickness, final boolean filled) {
|
||||||
radiusX += 0.5;
|
radiusX += 0.5;
|
||||||
radiusZ += 0.5;
|
radiusZ += 0.5;
|
||||||
|
|
||||||
|
@ -783,17 +783,19 @@ public class BrushCommands extends MethodCommands {
|
|||||||
help = "Left click the base of an object to copy.\n" +
|
help = "Left click the base of an object to copy.\n" +
|
||||||
"Right click to paste\n" +
|
"Right click to paste\n" +
|
||||||
"The -r flag Will apply random rotation on paste\n" +
|
"The -r flag Will apply random rotation on paste\n" +
|
||||||
|
"The -a flag Will apply auto view based rotation on paste\n" +
|
||||||
"Note: Works well with the clipboard scroll action\n" +
|
"Note: Works well with the clipboard scroll action\n" +
|
||||||
"Video: https://www.youtube.com/watch?v=RPZIaTbqoZw",
|
"Video: https://www.youtube.com/watch?v=RPZIaTbqoZw",
|
||||||
min = 0,
|
min = 0,
|
||||||
max = 1
|
max = 1
|
||||||
)
|
)
|
||||||
@CommandPermissions("worldedit.brush.copy")
|
@CommandPermissions("worldedit.brush.copy")
|
||||||
public BrushSettings copy(Player player, LocalSession session, @Optional("5") double radius, @Switch('r') boolean rotate, CommandContext context) throws WorldEditException {
|
public BrushSettings copy(Player player, LocalSession session, @Optional("5") double radius, @Switch('r') boolean randomRotate, @Switch('a') boolean autoRotate, CommandContext context) throws WorldEditException {
|
||||||
worldEdit.checkMaxBrushRadius(radius);
|
worldEdit.checkMaxBrushRadius(radius);
|
||||||
player.print(BBC.getPrefix() + BBC.BRUSH_COPY.f(radius));
|
player.print(BBC.getPrefix() + BBC.BRUSH_COPY.f(radius));
|
||||||
|
|
||||||
return get(context)
|
return get(context)
|
||||||
.setBrush(new CopyPastaBrush(player, session, rotate))
|
.setBrush(new CopyPastaBrush(player, session, randomRotate, autoRotate))
|
||||||
.setSize(radius);
|
.setSize(radius);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,7 +184,7 @@ public class GenerationCommands extends MethodCommands {
|
|||||||
)
|
)
|
||||||
@CommandPermissions("worldedit.generation.cylinder")
|
@CommandPermissions("worldedit.generation.cylinder")
|
||||||
@Logging(PLACEMENT)
|
@Logging(PLACEMENT)
|
||||||
public void hcyl(FawePlayer fp, Player player, LocalSession session, EditSession editSession, Pattern pattern, Vector2D radius, @Optional("1") int height, @Range(min = 1) @Optional("1") int thickness, CommandContext context) throws WorldEditException, ParameterException {
|
public void hcyl(FawePlayer fp, Player player, LocalSession session, EditSession editSession, Pattern pattern, Vector2D radius, @Optional("1") int height, @Range(min = 1) @Optional("1") double thickness, CommandContext context) throws WorldEditException, ParameterException {
|
||||||
double max = MathMan.max(radius.getBlockX(), radius.getBlockZ());
|
double max = MathMan.max(radius.getBlockX(), radius.getBlockZ());
|
||||||
worldEdit.checkMaxRadius(max);
|
worldEdit.checkMaxRadius(max);
|
||||||
fp.checkConfirmationRadius(getArguments(context), (int) max);
|
fp.checkConfirmationRadius(getArguments(context), (int) max);
|
||||||
|
@ -25,6 +25,7 @@ import com.boydti.fawe.object.extent.BlockTranslateExtent;
|
|||||||
import com.boydti.fawe.object.extent.PositionTransformExtent;
|
import com.boydti.fawe.object.extent.PositionTransformExtent;
|
||||||
import com.boydti.fawe.object.function.block.BiomeCopy;
|
import com.boydti.fawe.object.function.block.BiomeCopy;
|
||||||
import com.boydti.fawe.object.function.block.SimpleBlockCopy;
|
import com.boydti.fawe.object.function.block.SimpleBlockCopy;
|
||||||
|
import com.boydti.fawe.util.MaskTraverser;
|
||||||
import com.sk89q.worldedit.EditSession;
|
import com.sk89q.worldedit.EditSession;
|
||||||
import com.sk89q.worldedit.Vector;
|
import com.sk89q.worldedit.Vector;
|
||||||
import com.sk89q.worldedit.WorldEditException;
|
import com.sk89q.worldedit.WorldEditException;
|
||||||
@ -249,8 +250,10 @@ public class ForwardExtentCopy implements Operation {
|
|||||||
} else {
|
} else {
|
||||||
queue = null;
|
queue = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Extent finalDest = destination;
|
Extent finalDest = destination;
|
||||||
Vector translation = to.subtract(from);
|
Vector translation = to.subtract(from);
|
||||||
|
|
||||||
if (!translation.equals(Vector.ZERO)) {
|
if (!translation.equals(Vector.ZERO)) {
|
||||||
finalDest = new BlockTranslateExtent(finalDest, translation.getBlockX(), translation.getBlockY(), translation.getBlockZ());
|
finalDest = new BlockTranslateExtent(finalDest, translation.getBlockX(), translation.getBlockY(), translation.getBlockZ());
|
||||||
}
|
}
|
||||||
@ -264,6 +267,7 @@ public class ForwardExtentCopy implements Operation {
|
|||||||
|
|
||||||
RegionFunction copy = new SimpleBlockCopy(transExt, finalDest);
|
RegionFunction copy = new SimpleBlockCopy(transExt, finalDest);
|
||||||
if (sourceMask != Masks.alwaysTrue()) {
|
if (sourceMask != Masks.alwaysTrue()) {
|
||||||
|
new MaskTraverser(sourceMask).reset(transExt);
|
||||||
copy = new RegionMaskingFilter(sourceMask, copy);
|
copy = new RegionMaskingFilter(sourceMask, copy);
|
||||||
}
|
}
|
||||||
if (sourceFunction != null) {
|
if (sourceFunction != null) {
|
||||||
|
@ -150,7 +150,7 @@ public class AffineTransform implements Transform, Serializable {
|
|||||||
*
|
*
|
||||||
* @return the determinant of the transform.
|
* @return the determinant of the transform.
|
||||||
*/
|
*/
|
||||||
private double determinant() {
|
public double determinant() {
|
||||||
return m00 * (m11 * m22 - m12 * m21) - m01 * (m10 * m22 - m20 * m12)
|
return m00 * (m11 * m22 - m12 * m21) - m01 * (m10 * m22 - m20 * m12)
|
||||||
+ m02 * (m10 * m21 - m20 * m11);
|
+ m02 * (m10 * m21 - m20 * m11);
|
||||||
}
|
}
|
||||||
@ -163,17 +163,17 @@ public class AffineTransform implements Transform, Serializable {
|
|||||||
double det = this.determinant();
|
double det = this.determinant();
|
||||||
return new AffineTransform(
|
return new AffineTransform(
|
||||||
(m11 * m22 - m21 * m12) / det,
|
(m11 * m22 - m21 * m12) / det,
|
||||||
(m21 * m01 - m01 * m22) / det,
|
(m02 * m21 - m22 * m01) / det,
|
||||||
(m01 * m12 - m11 * m02) / det,
|
(m01 * m12 - m11 * m02) / det,
|
||||||
(m01 * (m22 * m13 - m12 * m23) + m02 * (m11 * m23 - m21 * m13)
|
(m01 * (m22 * m13 - m12 * m23) + m02 * (m11 * m23 - m21 * m13)
|
||||||
- m03 * (m11 * m22 - m21 * m12)) / det,
|
- m03 * (m11 * m22 - m21 * m12)) / det,
|
||||||
(m20 * m12 - m10 * m22) / det,
|
(m12 * m20 - m22 * m10) / det,
|
||||||
(m00 * m22 - m20 * m02) / det,
|
(m00 * m22 - m20 * m02) / det,
|
||||||
(m10 * m02 - m00 * m12) / det,
|
(m02 * m10 - m12 * m00) / det,
|
||||||
(m00 * (m12 * m23 - m22 * m13) - m02 * (m10 * m23 - m20 * m13)
|
(m00 * (m12 * m23 - m22 * m13) - m02 * (m10 * m23 - m20 * m13)
|
||||||
+ m03 * (m10 * m22 - m20 * m12)) / det,
|
+ m03 * (m10 * m22 - m20 * m12)) / det,
|
||||||
(m10 * m21 - m20 * m11) / det,
|
(m10 * m21 - m20 * m11) / det,
|
||||||
(m20 * m01 - m00 * m21) / det,
|
(m01 * m20 - m21 * m00) / det,
|
||||||
(m00 * m11 - m10 * m01) / det,
|
(m00 * m11 - m10 * m01) / det,
|
||||||
(m00 * (m21 * m13 - m11 * m23) + m01 * (m10 * m23 - m20 * m13)
|
(m00 * (m21 * m13 - m11 * m23) + m01 * (m10 * m23 - m20 * m13)
|
||||||
- m03 * (m10 * m21 - m20 * m11)) / det);
|
- m03 * (m10 * m21 - m20 * m11)) / det);
|
||||||
|
@ -137,8 +137,8 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion {
|
|||||||
if (pos1 == null || pos2 == null) {
|
if (pos1 == null || pos2 == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
pos1 = pos1.clampY(0, world == null ? 255 : world.getMaxY());
|
pos1 = pos1.clampY(world == null ? Integer.MIN_VALUE : 0, world == null ? Integer.MAX_VALUE : world.getMaxY());
|
||||||
pos2 = pos2.clampY(0, world == null ? 255 : world.getMaxY());
|
pos2 = pos2.clampY(world == null ? Integer.MIN_VALUE : 0, world == null ? Integer.MAX_VALUE : world.getMaxY());
|
||||||
Vector min = getMinimumPoint();
|
Vector min = getMinimumPoint();
|
||||||
Vector max = getMaximumPoint();
|
Vector max = getMaximumPoint();
|
||||||
minX = min.getBlockX();
|
minX = min.getBlockX();
|
||||||
|
Loading…
Reference in New Issue
Block a user