Plex-FAWE/worldedit-core/src/main/java/com/boydti/fawe/object/brush/ImageBrush.java
2019-04-01 03:09:20 +11:00

139 lines
5.4 KiB
Java

package com.boydti.fawe.object.brush;
import com.boydti.fawe.object.collection.SummedColorTable;
import com.boydti.fawe.object.mask.SurfaceMask;
import com.boydti.fawe.util.TextureUtil;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.command.tool.brush.Brush;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.operation.Operations;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.function.visitor.RecursiveVisitor;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.math.MutableVector3;
import com.sk89q.worldedit.math.Vector3;
import com.sk89q.worldedit.math.transform.AffineTransform;
import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockType;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Arrays;
public class ImageBrush implements Brush {
private final LocalSession session;
private final SummedColorTable table;
private final int width, height;
private final double centerX, centerZ;
private final ColorFunction colorFunction;
public ImageBrush(BufferedImage image, LocalSession session, boolean alpha /*, boolean glass */) throws IOException {
this.session = session;
this.table = new SummedColorTable(image, alpha);
this.width = image.getWidth();
this.height = image.getHeight();
this.centerX = width / 2d;
this.centerZ = height / 2d;
if (alpha) {
colorFunction = (x1, z1, x2, z2, extent, pos) -> {
int color = table.averageRGBA(x1, z1, x2, z2);
int alpha1 = (color >> 24) & 0xFF;
switch (alpha1) {
case 0:
return 0;
case 255:
return color;
default:
BlockStateHolder block = extent.getBlock(pos);
TextureUtil tu = session.getTextureUtil();
int existingColor = tu.getColor(block.getBlockType());
return tu.combineTransparency(color, existingColor);
}
};
} else {
colorFunction = (x1, z1, x2, z2, extent, pos) -> table.averageRGB(x1, z1, x2, z2);
}
}
private interface ColorFunction {
int call(int x1, int z1, int x2, int z2, Extent extent, BlockVector3 pos);
}
private interface BlockFunction {
void apply(int color, Extent extent, BlockVector3 pos);
}
@Override
public void build(EditSession editSession, BlockVector3 position, Pattern pattern, double sizeDouble) throws MaxChangedBlocksException {
TextureUtil texture = session.getTextureUtil();
final int cx = position.getBlockX();
final int cy = position.getBlockY();
final int cz = position.getBlockZ();
final Mask solid = new SurfaceMask(editSession);
double scale = Math.max(width, height) / sizeDouble;
Location loc = editSession.getPlayer().getPlayer().getLocation();
float yaw = loc.getYaw();
float pitch = loc.getPitch();
AffineTransform transform = new AffineTransform().rotateY((-yaw) % 360).rotateX((pitch - 90) % 360).inverse();
RecursiveVisitor visitor = new RecursiveVisitor(new Mask() {
private final MutableVector3 mutable = new MutableVector3();
@Override
public boolean test(BlockVector3 vector) {
if (solid.test(vector)) {
int dx = vector.getBlockX() - cx;
int dy = vector.getBlockY() - cy;
int dz = vector.getBlockZ() - cz;
Vector3 pos1 = transform.apply(mutable.setComponents(dx - 0.5, dy - 0.5, dz - 0.5));
int x1 = (int) (pos1.getX() * scale + centerX);
int z1 = (int) (pos1.getZ() * scale + centerZ);
Vector3 pos2 = transform.apply(mutable.setComponents(dx + 0.5, dy + 0.5, dz + 0.5));
int x2 = (int) (pos2.getX() * scale + centerX);
int z2 = (int) (pos2.getZ() * scale + centerZ);
if (x2 < x1) {
int tmp = x1;
x1 = x2;
x2 = tmp;
}
if (z2 < z1) {
int tmp = z1;
z1 = z2;
z2 = tmp;
}
if (x1 >= width || x2 < 0 || z1 >= height || z2 < 0) return false;
int color = colorFunction.call(x1, z1, x2, z2, editSession, vector);
if (color != 0) {
BlockType block = texture.getNearestBlock(color);
if (block != null) {
editSession.setBlock(vector, block.getDefaultState());
}
}
return true;
}
return false;
}
}, vector -> true, Integer.MAX_VALUE, editSession);
visitor.setDirections(Arrays.asList(visitor.DIAGONAL_DIRECTIONS));
visitor.visit(position);
Operations.completeBlindly(visitor);
}
private void apply(double val) {
}
}