Initial commit
This commit is contained in:
@@ -135,6 +135,8 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'org.jetbrains:annotations:22.0.0'
|
||||
|
||||
minecraft "net.minecraftforge:forge:${minecraft_version}-${forge_version}"
|
||||
|
||||
|
||||
@@ -144,6 +146,9 @@ dependencies {
|
||||
|
||||
implementation fg.deobf("curse.maven:jade-324717:${jade_id}")
|
||||
|
||||
if (System.getProperty('idea.sync.active') != 'true') {
|
||||
annotationProcessor "org.spongepowered:mixin:${mixin_version}:processor"
|
||||
}
|
||||
}
|
||||
|
||||
// This block of code expands all declared replace properties in the specified resource targets.
|
||||
|
||||
@@ -8,11 +8,13 @@ forge_version_range=[47,)
|
||||
loader_version_range=[47,)
|
||||
mapping_channel=official
|
||||
mapping_version=1.20.1
|
||||
mixin_version = 0.8.5
|
||||
|
||||
|
||||
modid=mechanical_lemon_ui
|
||||
mod_name=Mechanical Lemon UI
|
||||
mod_license=MIT
|
||||
mod_version=0.0.2
|
||||
mod_version=0.1.3
|
||||
mod_group_id=com.oierbravo
|
||||
author=oierbravo
|
||||
mod_description=Library
|
||||
@@ -23,4 +25,4 @@ jei_version = 15.2.0.22
|
||||
curios_minecraft_version = 1.20.1
|
||||
curios_version = 5.2.0-beta.3
|
||||
|
||||
jade_id = 4654448
|
||||
jade_id = 5672013
|
||||
@@ -0,0 +1,71 @@
|
||||
package com.oierbravo.mechanical_lemon_ui.foundation.gui.widget;
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.oierbravo.mechanical_lemon_ui.foundation.gui.widget.AbstractSimiWidget;
|
||||
import com.oierbravo.mechanical_lemon_ui.foundation.utility.ScreenElement;
|
||||
import com.oierbravo.mechanical_lemon_ui.register.LibGuiTextures;
|
||||
import net.minecraft.client.gui.GuiGraphics;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.MutableComponent;
|
||||
|
||||
public class ToggleIconButton extends AbstractSimiWidget {
|
||||
|
||||
protected ScreenElement[] icons;
|
||||
protected MutableComponent[] labels;
|
||||
|
||||
private int currentIndex;
|
||||
|
||||
public ToggleIconButton(int x, int y, ScreenElement[] icons, MutableComponent[] labels) {
|
||||
this(x, y, 18, 18, icons,labels,0);
|
||||
}
|
||||
public ToggleIconButton(int x, int y, ScreenElement[] icons, MutableComponent[] labels,int currentIndex) {
|
||||
this(x, y, 18, 18, icons,labels,currentIndex);
|
||||
}
|
||||
|
||||
public ToggleIconButton(int x, int y, int w, int h, ScreenElement[] icons, MutableComponent[] labels) {
|
||||
this(x, y, w, h,icons,labels,0);
|
||||
}
|
||||
public ToggleIconButton(int x, int y, int w, int h, ScreenElement[] icons, MutableComponent[] labels, int currentIndex) {
|
||||
super(x, y, w, h);
|
||||
this.icons = icons;
|
||||
this.labels = labels;
|
||||
this.currentIndex = currentIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doRender(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) {
|
||||
if (visible) {
|
||||
isHovered = mouseX >= getX() && mouseY >= getY() && mouseX < getX() + width && mouseY < getY() + height;
|
||||
|
||||
LibGuiTextures button = !active ? LibGuiTextures.BUTTON_DOWN
|
||||
: isMouseOver(mouseX, mouseY) ? LibGuiTextures.BUTTON_HOVER : LibGuiTextures.BUTTON;
|
||||
|
||||
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
|
||||
drawBg(graphics, button);
|
||||
icons[currentIndex].render(graphics, getX() + 1, getY() + 1);
|
||||
setToolTip(getLabel(currentIndex));
|
||||
}
|
||||
}
|
||||
|
||||
protected void drawBg(GuiGraphics graphics, LibGuiTextures button) {
|
||||
graphics.blit(button.location, getX(), getY(), button.startX, button.startY, button.width, button.height);
|
||||
}
|
||||
|
||||
public void setToolTip(Component text) {
|
||||
toolTip.clear();
|
||||
toolTip.add(text);
|
||||
}
|
||||
|
||||
public void setCurrentIndex(int pIndex){
|
||||
this.currentIndex = pIndex;
|
||||
}
|
||||
public void setIcons(ScreenElement[] icon) {
|
||||
this.icons = icons;
|
||||
}
|
||||
public void setLabels(MutableComponent[] labels) {
|
||||
this.labels = labels;
|
||||
}
|
||||
public MutableComponent getLabel(int pIndex){
|
||||
return this.labels[pIndex];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.oierbravo.mechanical_lemon_ui.foundation.utility;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.Direction.Axis;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
|
||||
public class Iterate {
|
||||
|
||||
public static final boolean[] trueAndFalse = { true, false };
|
||||
public static final boolean[] falseAndTrue = { false, true };
|
||||
public static final int[] zeroAndOne = { 0, 1 };
|
||||
public static final int[] positiveAndNegative = { 1, -1 };
|
||||
public static final Direction[] directions = Direction.values();
|
||||
public static final Direction[] horizontalDirections = getHorizontals();
|
||||
public static final Axis[] axes = Axis.values();
|
||||
public static final EnumSet<Axis> axisSet = EnumSet.allOf(Axis.class);
|
||||
|
||||
private static Direction[] getHorizontals() {
|
||||
Direction[] directions = new Direction[4];
|
||||
for (int i = 0; i < 4; i++)
|
||||
directions[i] = Direction.from2DDataValue(i);
|
||||
return directions;
|
||||
}
|
||||
|
||||
public static Direction[] directionsInAxis(Axis axis) {
|
||||
switch (axis) {
|
||||
case X:
|
||||
return new Direction[] { Direction.EAST, Direction.WEST };
|
||||
case Y:
|
||||
return new Direction[] { Direction.UP, Direction.DOWN };
|
||||
default:
|
||||
case Z:
|
||||
return new Direction[] { Direction.SOUTH, Direction.NORTH };
|
||||
}
|
||||
}
|
||||
|
||||
public static List<BlockPos> hereAndBelow(BlockPos pos) {
|
||||
return Arrays.asList(pos, pos.below());
|
||||
}
|
||||
|
||||
public static List<BlockPos> hereBelowAndAbove(BlockPos pos) {
|
||||
return Arrays.asList(pos, pos.below(), pos.above());
|
||||
}
|
||||
|
||||
public static <T> T cycleValue(List<T> list, T current) {
|
||||
int currentIndex = list.indexOf(current);
|
||||
if (currentIndex == -1) {
|
||||
throw new IllegalArgumentException("Current value not found in list");
|
||||
}
|
||||
int nextIndex = (currentIndex + 1) % list.size();
|
||||
return list.get(nextIndex);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package com.oierbravo.mechanical_lemon_ui.foundation.utility;
|
||||
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.phys.shapes.BooleanOp;
|
||||
import net.minecraft.world.phys.shapes.Shapes;
|
||||
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
import static net.minecraft.core.Direction.UP;
|
||||
|
||||
public class ShapeBuilder {
|
||||
private VoxelShape shape;
|
||||
|
||||
public ShapeBuilder(VoxelShape shape) {
|
||||
this.shape = shape;
|
||||
}
|
||||
|
||||
public ShapeBuilder add(VoxelShape shape) {
|
||||
this.shape = Shapes.or(this.shape, shape);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ShapeBuilder add(double x1, double y1, double z1, double x2, double y2, double z2) {
|
||||
return add(cuboid(x1, y1, z1, x2, y2, z2));
|
||||
}
|
||||
|
||||
public ShapeBuilder erase(double x1, double y1, double z1, double x2, double y2, double z2) {
|
||||
this.shape = Shapes.join(shape, cuboid(x1, y1, z1, x2, y2, z2), BooleanOp.ONLY_FIRST);
|
||||
return this;
|
||||
}
|
||||
|
||||
public VoxelShape build() {
|
||||
return shape;
|
||||
}
|
||||
|
||||
public VoxelShaper build(BiFunction<VoxelShape, Direction, VoxelShaper> factory, Direction direction) {
|
||||
return factory.apply(shape, direction);
|
||||
}
|
||||
|
||||
public VoxelShaper build(BiFunction<VoxelShape, Direction.Axis, VoxelShaper> factory, Direction.Axis axis) {
|
||||
return factory.apply(shape, axis);
|
||||
}
|
||||
|
||||
public VoxelShaper forDirectional(Direction direction) {
|
||||
return build(VoxelShaper::forDirectional, direction);
|
||||
}
|
||||
|
||||
public VoxelShaper forAxis() {
|
||||
return build(VoxelShaper::forAxis, Direction.Axis.Y);
|
||||
}
|
||||
|
||||
public VoxelShaper forHorizontalAxis() {
|
||||
return build(VoxelShaper::forHorizontalAxis, Direction.Axis.Z);
|
||||
}
|
||||
|
||||
public VoxelShaper forHorizontal(Direction direction) {
|
||||
return build(VoxelShaper::forHorizontal, direction);
|
||||
}
|
||||
|
||||
public VoxelShaper forDirectional() {
|
||||
return forDirectional(UP);
|
||||
}
|
||||
|
||||
public static ShapeBuilder shape(VoxelShape shape) {
|
||||
return new ShapeBuilder(shape);
|
||||
}
|
||||
|
||||
public static ShapeBuilder shape(double x1, double y1, double z1, double x2, double y2, double z2) {
|
||||
return shape(cuboid(x1, y1, z1, x2, y2, z2));
|
||||
}
|
||||
|
||||
public static VoxelShape cuboid(double x1, double y1, double z1, double x2, double y2, double z2) {
|
||||
return Block.box(x1, y1, z1, x2, y2, z2);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,297 @@
|
||||
package com.oierbravo.mechanical_lemon_ui.foundation.utility;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.Direction.Axis;
|
||||
import net.minecraft.core.Vec3i;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.DoubleTag;
|
||||
import net.minecraft.nbt.ListTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.level.block.Mirror;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class VecHelper {
|
||||
|
||||
public static final Vec3 CENTER_OF_ORIGIN = new Vec3(.5, .5, .5);
|
||||
|
||||
public static Vec3 rotate(Vec3 vec, Vec3 rotationVec) {
|
||||
return rotate(vec, rotationVec.x, rotationVec.y, rotationVec.z);
|
||||
}
|
||||
|
||||
public static Vec3 rotate(Vec3 vec, double xRot, double yRot, double zRot) {
|
||||
return rotate(rotate(rotate(vec, xRot, Axis.X), yRot, Axis.Y), zRot, Axis.Z);
|
||||
}
|
||||
|
||||
public static Vec3 rotateCentered(Vec3 vec, double deg, Axis axis) {
|
||||
Vec3 shift = getCenterOf(BlockPos.ZERO);
|
||||
return VecHelper.rotate(vec.subtract(shift), deg, axis)
|
||||
.add(shift);
|
||||
}
|
||||
|
||||
public static Vec3 rotate(Vec3 vec, double deg, Axis axis) {
|
||||
if (deg == 0)
|
||||
return vec;
|
||||
if (vec == Vec3.ZERO)
|
||||
return vec;
|
||||
|
||||
float angle = (float) (deg / 180f * Math.PI);
|
||||
double sin = Mth.sin(angle);
|
||||
double cos = Mth.cos(angle);
|
||||
double x = vec.x;
|
||||
double y = vec.y;
|
||||
double z = vec.z;
|
||||
|
||||
if (axis == Axis.X)
|
||||
return new Vec3(x, y * cos - z * sin, z * cos + y * sin);
|
||||
if (axis == Axis.Y)
|
||||
return new Vec3(x * cos + z * sin, y, z * cos - x * sin);
|
||||
if (axis == Axis.Z)
|
||||
return new Vec3(x * cos - y * sin, y * cos + x * sin, z);
|
||||
return vec;
|
||||
}
|
||||
|
||||
public static Vec3 mirrorCentered(Vec3 vec, Mirror mirror) {
|
||||
Vec3 shift = getCenterOf(BlockPos.ZERO);
|
||||
return VecHelper.mirror(vec.subtract(shift), mirror)
|
||||
.add(shift);
|
||||
}
|
||||
|
||||
public static Vec3 mirror(Vec3 vec, Mirror mirror) {
|
||||
if (mirror == null || mirror == Mirror.NONE)
|
||||
return vec;
|
||||
if (vec == Vec3.ZERO)
|
||||
return vec;
|
||||
|
||||
double x = vec.x;
|
||||
double y = vec.y;
|
||||
double z = vec.z;
|
||||
|
||||
if (mirror == Mirror.LEFT_RIGHT)
|
||||
return new Vec3(x, y, -z);
|
||||
if (mirror == Mirror.FRONT_BACK)
|
||||
return new Vec3(-x, y, z);
|
||||
return vec;
|
||||
}
|
||||
|
||||
public static Vec3 lookAt(Vec3 vec, Vec3 fwd) {
|
||||
fwd = fwd.normalize();
|
||||
Vec3 up = new Vec3(0, 1, 0);
|
||||
double dot = fwd.dot(up);
|
||||
if (Math.abs(dot) > 1 - 1.0E-3)
|
||||
up = new Vec3(0, 0, dot > 0 ? 1 : -1);
|
||||
Vec3 right = fwd.cross(up)
|
||||
.normalize();
|
||||
up = right.cross(fwd)
|
||||
.normalize();
|
||||
double x = vec.x * right.x + vec.y * up.x + vec.z * fwd.x;
|
||||
double y = vec.x * right.y + vec.y * up.y + vec.z * fwd.y;
|
||||
double z = vec.x * right.z + vec.y * up.z + vec.z * fwd.z;
|
||||
return new Vec3(x, y, z);
|
||||
}
|
||||
|
||||
public static boolean isVecPointingTowards(Vec3 vec, Direction direction) {
|
||||
return Vec3.atLowerCornerOf(direction.getNormal())
|
||||
.dot(vec.normalize()) > 0.125; // slight tolerance to activate perpendicular movement actors
|
||||
}
|
||||
|
||||
public static Vec3 getCenterOf(Vec3i pos) {
|
||||
if (pos.equals(Vec3i.ZERO))
|
||||
return CENTER_OF_ORIGIN;
|
||||
return Vec3.atLowerCornerOf(pos)
|
||||
.add(.5f, .5f, .5f);
|
||||
}
|
||||
|
||||
public static Vec3 offsetRandomly(Vec3 vec, RandomSource r, float radius) {
|
||||
return new Vec3(vec.x + (r.nextFloat() - .5f) * 2 * radius, vec.y + (r.nextFloat() - .5f) * 2 * radius,
|
||||
vec.z + (r.nextFloat() - .5f) * 2 * radius);
|
||||
}
|
||||
|
||||
public static Vec3 axisAlingedPlaneOf(Vec3 vec) {
|
||||
vec = vec.normalize();
|
||||
return new Vec3(1, 1, 1).subtract(Math.abs(vec.x), Math.abs(vec.y), Math.abs(vec.z));
|
||||
}
|
||||
|
||||
public static Vec3 axisAlingedPlaneOf(Direction face) {
|
||||
return axisAlingedPlaneOf(Vec3.atLowerCornerOf(face.getNormal()));
|
||||
}
|
||||
|
||||
public static ListTag writeNBT(Vec3 vec) {
|
||||
ListTag listnbt = new ListTag();
|
||||
listnbt.add(DoubleTag.valueOf(vec.x));
|
||||
listnbt.add(DoubleTag.valueOf(vec.y));
|
||||
listnbt.add(DoubleTag.valueOf(vec.z));
|
||||
return listnbt;
|
||||
}
|
||||
|
||||
public static CompoundTag writeNBTCompound(Vec3 vec) {
|
||||
CompoundTag compoundTag = new CompoundTag();
|
||||
compoundTag.put("V", writeNBT(vec));
|
||||
return compoundTag;
|
||||
}
|
||||
|
||||
public static Vec3 readNBT(ListTag list) {
|
||||
if (list.isEmpty())
|
||||
return Vec3.ZERO;
|
||||
return new Vec3(list.getDouble(0), list.getDouble(1), list.getDouble(2));
|
||||
}
|
||||
|
||||
public static Vec3 readNBTCompound(CompoundTag nbt) {
|
||||
return readNBT(nbt.getList("V", Tag.TAG_DOUBLE));
|
||||
}
|
||||
|
||||
public static void write(Vec3 vec, FriendlyByteBuf buffer) {
|
||||
buffer.writeDouble(vec.x);
|
||||
buffer.writeDouble(vec.y);
|
||||
buffer.writeDouble(vec.z);
|
||||
}
|
||||
|
||||
public static Vec3 read(FriendlyByteBuf buffer) {
|
||||
return new Vec3(buffer.readDouble(), buffer.readDouble(), buffer.readDouble());
|
||||
}
|
||||
|
||||
public static Vec3 voxelSpace(double x, double y, double z) {
|
||||
return new Vec3(x, y, z).scale(1 / 16f);
|
||||
}
|
||||
|
||||
public static int getCoordinate(Vec3i pos, Axis axis) {
|
||||
return axis.choose(pos.getX(), pos.getY(), pos.getZ());
|
||||
}
|
||||
|
||||
public static float getCoordinate(Vec3 vec, Axis axis) {
|
||||
return (float) axis.choose(vec.x, vec.y, vec.z);
|
||||
}
|
||||
|
||||
public static boolean onSameAxis(BlockPos pos1, BlockPos pos2, Axis axis) {
|
||||
if (pos1.equals(pos2))
|
||||
return true;
|
||||
for (Axis otherAxis : Axis.values())
|
||||
if (axis != otherAxis)
|
||||
if (getCoordinate(pos1, otherAxis) != getCoordinate(pos2, otherAxis))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public static Vec3 clamp(Vec3 vec, float maxLength) {
|
||||
return vec.lengthSqr() > maxLength * maxLength ? vec.normalize()
|
||||
.scale(maxLength) : vec;
|
||||
}
|
||||
|
||||
public static Vec3 lerp(float p, Vec3 from, Vec3 to) {
|
||||
return from.add(to.subtract(from)
|
||||
.scale(p));
|
||||
}
|
||||
|
||||
public static Vec3 slerp(float p, Vec3 from, Vec3 to) {
|
||||
double theta = Math.acos(from.dot(to));
|
||||
return from.scale(Mth.sin(1 - p) * theta)
|
||||
.add(to.scale(Mth.sin((float) (theta * p))))
|
||||
.scale(1 / Mth.sin((float) theta));
|
||||
}
|
||||
|
||||
public static Vec3 clampComponentWise(Vec3 vec, float maxLength) {
|
||||
return new Vec3(Mth.clamp(vec.x, -maxLength, maxLength), Mth.clamp(vec.y, -maxLength, maxLength),
|
||||
Mth.clamp(vec.z, -maxLength, maxLength));
|
||||
}
|
||||
|
||||
public static Vec3 componentMin(Vec3 vec1, Vec3 vec2) {
|
||||
return new Vec3(Math.min(vec1.x, vec2.x), Math.min(vec1.y, vec2.y), Math.min(vec1.z, vec2.z));
|
||||
}
|
||||
|
||||
public static Vec3 componentMax(Vec3 vec1, Vec3 vec2) {
|
||||
return new Vec3(Math.max(vec1.x, vec2.x), Math.max(vec1.y, vec2.y), Math.max(vec1.z, vec2.z));
|
||||
}
|
||||
|
||||
public static Vec3 project(Vec3 vec, Vec3 ontoVec) {
|
||||
if (ontoVec.equals(Vec3.ZERO))
|
||||
return Vec3.ZERO;
|
||||
return ontoVec.scale(vec.dot(ontoVec) / ontoVec.lengthSqr());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static Vec3 intersectSphere(Vec3 origin, Vec3 lineDirection, Vec3 sphereCenter, double radius) {
|
||||
if (lineDirection.equals(Vec3.ZERO))
|
||||
return null;
|
||||
if (lineDirection.lengthSqr() != 1)
|
||||
lineDirection = lineDirection.normalize();
|
||||
|
||||
Vec3 diff = origin.subtract(sphereCenter);
|
||||
double lineDotDiff = lineDirection.dot(diff);
|
||||
double delta = lineDotDiff * lineDotDiff - (diff.lengthSqr() - radius * radius);
|
||||
if (delta < 0)
|
||||
return null;
|
||||
double t = -lineDotDiff + Math.sqrt(delta);
|
||||
return origin.add(lineDirection.scale(t));
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static Vec3 bezier(Vec3 p1, Vec3 p2, Vec3 q1, Vec3 q2, float t) {
|
||||
Vec3 v1 = lerp(t, p1, q1);
|
||||
Vec3 v2 = lerp(t, q1, q2);
|
||||
Vec3 v3 = lerp(t, q2, p2);
|
||||
Vec3 inner1 = lerp(t, v1, v2);
|
||||
Vec3 inner2 = lerp(t, v2, v3);
|
||||
Vec3 result = lerp(t, inner1, inner2);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Vec3 bezierDerivative(Vec3 p1, Vec3 p2, Vec3 q1, Vec3 q2, float t) {
|
||||
return p1.scale(-3 * t * t + 6 * t - 3)
|
||||
.add(q1.scale(9 * t * t - 12 * t + 3))
|
||||
.add(q2.scale(-9 * t * t + 6 * t))
|
||||
.add(p2.scale(3 * t * t));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static double[] intersectRanged(Vec3 p1, Vec3 q1, Vec3 p2, Vec3 q2, Axis plane) {
|
||||
Vec3 pDiff = p2.subtract(p1);
|
||||
Vec3 qDiff = q2.subtract(q1);
|
||||
double[] intersect = intersect(p1, q1, pDiff.normalize(), qDiff.normalize(), plane);
|
||||
if (intersect == null)
|
||||
return null;
|
||||
if (intersect[0] < 0 || intersect[1] < 0)
|
||||
return null;
|
||||
if (intersect[0] * intersect[0] > pDiff.lengthSqr() || intersect[1] * intersect[1] > qDiff.lengthSqr())
|
||||
return null;
|
||||
return intersect;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static double[] intersect(Vec3 p1, Vec3 p2, Vec3 r, Vec3 s, Axis plane) {
|
||||
if (plane == Axis.X) {
|
||||
p1 = new Vec3(p1.y, 0, p1.z);
|
||||
p2 = new Vec3(p2.y, 0, p2.z);
|
||||
r = new Vec3(r.y, 0, r.z);
|
||||
s = new Vec3(s.y, 0, s.z);
|
||||
}
|
||||
|
||||
if (plane == Axis.Z) {
|
||||
p1 = new Vec3(p1.x, 0, p1.y);
|
||||
p2 = new Vec3(p2.x, 0, p2.y);
|
||||
r = new Vec3(r.x, 0, r.y);
|
||||
s = new Vec3(s.x, 0, s.y);
|
||||
}
|
||||
|
||||
Vec3 qminusp = p2.subtract(p1);
|
||||
double rcs = r.x * s.z - r.z * s.x;
|
||||
if (Mth.equal(rcs, 0))
|
||||
return null;
|
||||
Vec3 rdivrcs = r.scale(1 / rcs);
|
||||
Vec3 sdivrcs = s.scale(1 / rcs);
|
||||
double t = qminusp.x * sdivrcs.z - qminusp.z * sdivrcs.x;
|
||||
double u = qminusp.x * rdivrcs.z - qminusp.z * rdivrcs.x;
|
||||
return new double[] { t, u };
|
||||
}
|
||||
|
||||
public static double alignedDistanceToFace(Vec3 pos, BlockPos blockPos, Direction face) {
|
||||
Axis axis = face.getAxis();
|
||||
return Math.abs(getCoordinate(pos, axis) - (blockPos.get(axis) + (face.getAxisDirection() == Direction.AxisDirection.POSITIVE ? 1 : 0)));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
package com.oierbravo.mechanical_lemon_ui.foundation.utility;
|
||||
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.Direction.Axis;
|
||||
import net.minecraft.core.Direction.AxisDirection;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraft.world.phys.shapes.Shapes;
|
||||
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||
import org.apache.commons.lang3.mutable.MutableObject;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class VoxelShaper {
|
||||
|
||||
private Map<Direction, VoxelShape> shapes = new HashMap<>();
|
||||
|
||||
public VoxelShape get(Direction direction) {
|
||||
return shapes.get(direction);
|
||||
}
|
||||
|
||||
public VoxelShape get(Axis axis) {
|
||||
return shapes.get(axisAsFace(axis));
|
||||
}
|
||||
|
||||
public static VoxelShaper forHorizontal(VoxelShape shape, Direction facing) {
|
||||
return forDirectionsWithRotation(shape, facing, Direction.Plane.HORIZONTAL, new HorizontalRotationValues());
|
||||
}
|
||||
|
||||
public static VoxelShaper forHorizontalAxis(VoxelShape shape, Axis along) {
|
||||
return forDirectionsWithRotation(shape, axisAsFace(along), Arrays.asList(Direction.SOUTH, Direction.EAST),
|
||||
new HorizontalRotationValues());
|
||||
}
|
||||
|
||||
public static VoxelShaper forDirectional(VoxelShape shape, Direction facing) {
|
||||
return forDirectionsWithRotation(shape, facing, Arrays.asList(Iterate.directions), new DefaultRotationValues());
|
||||
}
|
||||
|
||||
public static VoxelShaper forAxis(VoxelShape shape, Axis along) {
|
||||
return forDirectionsWithRotation(shape, axisAsFace(along),
|
||||
Arrays.asList(Direction.SOUTH, Direction.EAST, Direction.UP), new DefaultRotationValues());
|
||||
}
|
||||
|
||||
public VoxelShaper withVerticalShapes(VoxelShape upShape) {
|
||||
shapes.put(Direction.UP, upShape);
|
||||
shapes.put(Direction.DOWN, rotatedCopy(upShape, new Vec3(180, 0, 0)));
|
||||
return this;
|
||||
}
|
||||
|
||||
public VoxelShaper withShape(VoxelShape shape, Direction facing) {
|
||||
shapes.put(facing, shape);
|
||||
return this;
|
||||
}
|
||||
|
||||
public static Direction axisAsFace(Axis axis) {
|
||||
return Direction.get(AxisDirection.POSITIVE, axis);
|
||||
}
|
||||
|
||||
protected static float horizontalAngleFromDirection(Direction direction) {
|
||||
return (float) ((Math.max(direction.get2DDataValue(), 0) & 3) * 90);
|
||||
}
|
||||
|
||||
protected static VoxelShaper forDirectionsWithRotation(VoxelShape shape, Direction facing,
|
||||
Iterable<Direction> directions, Function<Direction, Vec3> rotationValues) {
|
||||
VoxelShaper voxelShaper = new VoxelShaper();
|
||||
for (Direction dir : directions) {
|
||||
voxelShaper.shapes.put(dir, rotate(shape, facing, dir, rotationValues));
|
||||
}
|
||||
return voxelShaper;
|
||||
}
|
||||
|
||||
protected static VoxelShape rotate(VoxelShape shape, Direction from, Direction to,
|
||||
Function<Direction, Vec3> usingValues) {
|
||||
if (from == to)
|
||||
return shape;
|
||||
|
||||
return rotatedCopy(shape, usingValues.apply(from)
|
||||
.reverse()
|
||||
.add(usingValues.apply(to)));
|
||||
}
|
||||
|
||||
protected static VoxelShape rotatedCopy(VoxelShape shape, Vec3 rotation) {
|
||||
if (rotation.equals(Vec3.ZERO))
|
||||
return shape;
|
||||
|
||||
MutableObject<VoxelShape> result = new MutableObject<>(Shapes.empty());
|
||||
Vec3 center = new Vec3(8, 8, 8);
|
||||
|
||||
shape.forAllBoxes((x1, y1, z1, x2, y2, z2) -> {
|
||||
Vec3 v1 = new Vec3(x1, y1, z1).scale(16)
|
||||
.subtract(center);
|
||||
Vec3 v2 = new Vec3(x2, y2, z2).scale(16)
|
||||
.subtract(center);
|
||||
|
||||
v1 = VecHelper.rotate(v1, (float) rotation.x, Axis.X);
|
||||
v1 = VecHelper.rotate(v1, (float) rotation.y, Axis.Y);
|
||||
v1 = VecHelper.rotate(v1, (float) rotation.z, Axis.Z)
|
||||
.add(center);
|
||||
|
||||
v2 = VecHelper.rotate(v2, (float) rotation.x, Axis.X);
|
||||
v2 = VecHelper.rotate(v2, (float) rotation.y, Axis.Y);
|
||||
v2 = VecHelper.rotate(v2, (float) rotation.z, Axis.Z)
|
||||
.add(center);
|
||||
|
||||
VoxelShape rotated = blockBox(v1, v2);
|
||||
result.setValue(Shapes.or(result.getValue(), rotated));
|
||||
});
|
||||
|
||||
return result.getValue();
|
||||
}
|
||||
|
||||
protected static VoxelShape blockBox(Vec3 v1, Vec3 v2) {
|
||||
return Block.box(
|
||||
Math.min(v1.x, v2.x),
|
||||
Math.min(v1.y, v2.y),
|
||||
Math.min(v1.z, v2.z),
|
||||
Math.max(v1.x, v2.x),
|
||||
Math.max(v1.y, v2.y),
|
||||
Math.max(v1.z, v2.z)
|
||||
);
|
||||
}
|
||||
|
||||
protected static class DefaultRotationValues implements Function<Direction, Vec3> {
|
||||
// assume facing up as the default rotation
|
||||
@Override
|
||||
public Vec3 apply(Direction direction) {
|
||||
return new Vec3(direction == Direction.UP ? 0 : (Direction.Plane.VERTICAL.test(direction) ? 180 : 90),
|
||||
-horizontalAngleFromDirection(direction), 0);
|
||||
}
|
||||
}
|
||||
|
||||
protected static class HorizontalRotationValues implements Function<Direction, Vec3> {
|
||||
@Override
|
||||
public Vec3 apply(Direction direction) {
|
||||
return new Vec3(0, -horizontalAngleFromDirection(direction), 0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user