Pick a side

- Ponder's Identify mode now supports blocks with ray-specific pick block results
This commit is contained in:
simibubi 2022-10-07 19:33:10 +02:00
parent c4eb62c862
commit 7cd149ba06
2 changed files with 16 additions and 9 deletions

View file

@ -35,6 +35,7 @@ import com.simibubi.create.foundation.ponder.ui.PonderUI;
import com.simibubi.create.foundation.render.ForcedDiffuseState; import com.simibubi.create.foundation.render.ForcedDiffuseState;
import com.simibubi.create.foundation.render.SuperRenderTypeBuffer; import com.simibubi.create.foundation.render.SuperRenderTypeBuffer;
import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.AnimationTickHolder;
import com.simibubi.create.foundation.utility.BlockFace;
import com.simibubi.create.foundation.utility.Pair; import com.simibubi.create.foundation.utility.Pair;
import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.foundation.utility.animation.LerpedFloat; import com.simibubi.create.foundation.utility.animation.LerpedFloat;
@ -134,14 +135,14 @@ public class PonderScene {
} }
public Pair<ItemStack, BlockPos> rayTraceScene(Vec3 from, Vec3 to) { public Pair<ItemStack, BlockPos> rayTraceScene(Vec3 from, Vec3 to) {
MutableObject<Pair<WorldSectionElement, BlockPos>> nearestHit = new MutableObject<>(); MutableObject<Pair<WorldSectionElement, Pair<Vec3, BlockFace>>> nearestHit = new MutableObject<>();
MutableDouble bestDistance = new MutableDouble(0); MutableDouble bestDistance = new MutableDouble(0);
forEach(WorldSectionElement.class, wse -> { forEach(WorldSectionElement.class, wse -> {
wse.resetSelectedBlock(); wse.resetSelectedBlock();
if (!wse.isVisible()) if (!wse.isVisible())
return; return;
Pair<Vec3, BlockPos> rayTrace = wse.rayTrace(world, from, to); Pair<Vec3, BlockFace> rayTrace = wse.rayTrace(world, from, to);
if (rayTrace == null) if (rayTrace == null)
return; return;
double distanceTo = rayTrace.getFirst() double distanceTo = rayTrace.getFirst()
@ -149,15 +150,20 @@ public class PonderScene {
if (nearestHit.getValue() != null && distanceTo >= bestDistance.getValue()) if (nearestHit.getValue() != null && distanceTo >= bestDistance.getValue())
return; return;
nearestHit.setValue(Pair.of(wse, rayTrace.getSecond())); nearestHit.setValue(Pair.of(wse, rayTrace));
bestDistance.setValue(distanceTo); bestDistance.setValue(distanceTo);
}); });
if (nearestHit.getValue() == null) if (nearestHit.getValue() == null)
return Pair.of(ItemStack.EMPTY, null); return Pair.of(ItemStack.EMPTY, null);
BlockPos selectedPos = nearestHit.getValue() Pair<Vec3, BlockFace> selectedHit = nearestHit.getValue()
.getSecond(); .getSecond();
BlockPos selectedPos = selectedHit.getSecond()
.getPos();
Direction selectedFace = selectedHit.getSecond()
.getFace();
Vec3 selectedVec = selectedHit.getFirst();
BlockPos origin = new BlockPos(basePlateOffsetX, 0, basePlateOffsetZ); BlockPos origin = new BlockPos(basePlateOffsetX, 0, basePlateOffsetZ);
if (!world.getBounds() if (!world.getBounds()
@ -176,9 +182,9 @@ public class PonderScene {
.getFirst() .getFirst()
.selectBlock(selectedPos); .selectBlock(selectedPos);
BlockState blockState = world.getBlockState(selectedPos); BlockState blockState = world.getBlockState(selectedPos);
ItemStack pickBlock = blockState.getCloneItemStack( ItemStack pickBlock =
new BlockHitResult(VecHelper.getCenterOf(selectedPos), Direction.UP, selectedPos, true), world, selectedPos, blockState.getCloneItemStack(new BlockHitResult(selectedVec, selectedFace, selectedPos, true), world,
Minecraft.getInstance().player); selectedPos, Minecraft.getInstance().player);
return Pair.of(pickBlock, selectedPos); return Pair.of(pickBlock, selectedPos);
} }

View file

@ -26,6 +26,7 @@ import com.simibubi.create.foundation.render.SuperByteBufferCache;
import com.simibubi.create.foundation.render.SuperRenderTypeBuffer; import com.simibubi.create.foundation.render.SuperRenderTypeBuffer;
import com.simibubi.create.foundation.render.TileEntityRenderHelper; import com.simibubi.create.foundation.render.TileEntityRenderHelper;
import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.AnimationTickHolder;
import com.simibubi.create.foundation.utility.BlockFace;
import com.simibubi.create.foundation.utility.Pair; import com.simibubi.create.foundation.utility.Pair;
import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.foundation.utility.outliner.AABBOutline; import com.simibubi.create.foundation.utility.outliner.AABBOutline;
@ -181,7 +182,7 @@ public class WorldSectionElement extends AnimatedSceneElement {
BlockPos worldPos; BlockPos worldPos;
} }
public Pair<Vec3, BlockPos> rayTrace(PonderWorld world, Vec3 source, Vec3 target) { public Pair<Vec3, BlockFace> rayTrace(PonderWorld world, Vec3 source, Vec3 target) {
world.setMask(this.section); world.setMask(this.section);
Vec3 transformedTarget = reverseTransformVec(target); Vec3 transformedTarget = reverseTransformVec(target);
BlockHitResult rayTraceBlocks = world.clip(new ClipContext(reverseTransformVec(source), transformedTarget, BlockHitResult rayTraceBlocks = world.clip(new ClipContext(reverseTransformVec(source), transformedTarget,
@ -199,7 +200,7 @@ public class WorldSectionElement extends AnimatedSceneElement {
/ source.subtract(target) / source.subtract(target)
.lengthSqr(); .lengthSqr();
Vec3 actualHit = VecHelper.lerp((float) t, target, source); Vec3 actualHit = VecHelper.lerp((float) t, target, source);
return Pair.of(actualHit, rayTraceBlocks.getBlockPos()); return Pair.of(actualHit, new BlockFace(rayTraceBlocks.getBlockPos(), rayTraceBlocks.getDirection()));
} }
private Vec3 reverseTransformVec(Vec3 in) { private Vec3 reverseTransformVec(Vec3 in) {