diff --git a/src/main/java/dev/dubhe/anvilcraft/client/gui/screen/AnvilHammerScreen.java b/src/main/java/dev/dubhe/anvilcraft/client/gui/screen/AnvilHammerScreen.java index 6de803e0d..01124c78e 100644 --- a/src/main/java/dev/dubhe/anvilcraft/client/gui/screen/AnvilHammerScreen.java +++ b/src/main/java/dev/dubhe/anvilcraft/client/gui/screen/AnvilHammerScreen.java @@ -34,6 +34,7 @@ import java.lang.invoke.MethodType; import java.util.ArrayList; import java.util.List; +import java.util.Objects; @ParametersAreNonnullByDefault public class AnvilHammerScreen extends Screen implements IHasHammerEffect { @@ -41,6 +42,7 @@ public class AnvilHammerScreen extends Screen implements IHasHammerEffect { public static final int DELAY = 80;//ms public static final int ANIMATION_T = 300;//ms public static final int CLOSING_ANIMATION_T = 150;//ms + public static final int SELECTION_TRANSFORMATION = 80; public static final float ZOOM = 13.5f; public static final int IGNORE_CURSOR_MOVE_LENGTH = 15; @@ -50,7 +52,8 @@ public class AnvilHammerScreen extends Screen implements IHasHammerEffect { private static final int RING_INNER_DIAMETER = 55; private static final int RING_OUTER_DIAMETER = 105; - private static final int SELECTION_EFFECT_COLOR = 0xddFFFF00; + private static final int SELECTION_EFFECT_ALPHA = 0xdd; + private static final int SELECTION_EFFECT_COLOR = 0xffFFFF00; private static final int SELECTION_EFFECT_RADIUS = 20; private static final float TEXT_SCALE = 1f; @@ -79,6 +82,7 @@ public class AnvilHammerScreen extends Screen implements IHasHammerEffect { private final List possibleStates; private BlockState currentBlockState; + private SelectionItem currentSelection; private final List items = new ArrayList<>(); private long displayTime = System.currentTimeMillis(); private boolean animationStarted = false; @@ -130,7 +134,11 @@ protected void init() { } catch (Throwable ignored) { } } - + this.currentSelection = items.stream() + .filter(it -> it.state == currentBlockState) + .findFirst() + .orElseThrow(); + this.currentSelection.selected = true; } @Override @@ -157,7 +165,23 @@ public boolean mouseDragged(double mouseX, double mouseY, int button, double dra return rotation >= it.detectionAngleStart && rotation <= it.detectionAngleEnd; }) .findFirst() - .ifPresent(it -> currentBlockState = it.state); + .ifPresent(it -> { + SelectionItem oldSelection = currentSelection; + currentSelection = it; + if (!currentSelection.equals(oldSelection)) { + if (oldSelection != null) { + oldSelection.transformation = TransformationType.EXTINGUISH; + oldSelection.transformationStartTime = System.currentTimeMillis(); + } + currentSelection.transformation = TransformationType.LIT; + currentSelection.transformationStartTime = System.currentTimeMillis(); + } + if (oldSelection != null) { + oldSelection.selected = false; + } + currentSelection.selected = true; + currentBlockState = it.state; + }); return super.mouseDragged(mouseX, mouseY, button, dragX, dragY); } @@ -187,24 +211,42 @@ private void renderProgressAnimation(GuiGraphics guiGraphics, float progress, fl RING_OUTER_DIAMETER * progress ); poseStack.popPose(); - float finalProgress = progress; - items.stream() - .filter(it -> it.state == currentBlockState) - .findFirst() - .ifPresent(it -> { - Vector2f center = new Vector2f( - (it.center.x - centerX) / RADIUS, - (it.center.y - centerY) / RADIUS - ).mul(RADIUS * finalProgress) - .add(centerX, centerY); - renderSelectionEffect( - guiGraphics, - center.x, - center.y, - SELECTION_EFFECT_COLOR, - SELECTION_EFFECT_RADIUS - ); - }); + for (SelectionItem value : items) { + Vector2f center = new Vector2f( + (value.center.x - centerX) / RADIUS, + (value.center.y - centerY) / RADIUS + ).mul(RADIUS * progress) + .add(centerX, centerY); + float x = center.x; + float y = center.y; + if (value.shouldRenderTransformation()) { + float selectionTrProgress = switch (value.transformation) { + case LIT -> value.getTransformationProgress(); + case EXTINGUISH -> 1 - value.getTransformationProgress(); + }; + if (selectionTrProgress != 0) { + int alpha = ((int) (0xff * selectionTrProgress)) << 24; + int color = alpha | 0xFFFF00; + renderSelectionEffect( + guiGraphics, + x, + y, + color, + SELECTION_EFFECT_RADIUS + ); + } + } else { + if (value.selected) { + renderSelectionEffect( + guiGraphics, + x, + y, + SELECTION_EFFECT_COLOR, + SELECTION_EFFECT_RADIUS + ); + } + } + } for (SelectionItem value : items) { Vector2f center = new Vector2f( (value.center.x - centerX) / RADIUS, @@ -248,6 +290,7 @@ private void renderProgressAnimation(GuiGraphics guiGraphics, float progress, fl public void render(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick) { RenderSystem.enableDepthTest(); RenderSystem.enableBlend(); + RenderSystem.defaultBlendFunc(); float centerX = this.width / 2f; float centerY = this.height / 2f; renderClosingAnimation(guiGraphics, mouseX, mouseY, partialTick); @@ -276,7 +319,38 @@ public void render(GuiGraphics guiGraphics, int mouseX, int mouseY, float partia RING_INNER_DIAMETER, RING_OUTER_DIAMETER ); - renderSelection(guiGraphics); + //renderSelection(guiGraphics); + for (SelectionItem value : items) { + float x = value.center.x; + float y = value.center.y; + if (value.shouldRenderTransformation()) { + float selectionTrProgress = switch (value.transformation) { + case LIT -> value.getTransformationProgress(); + case EXTINGUISH -> 1 - value.getTransformationProgress(); + }; + if (selectionTrProgress != 0) { + int alpha = ((int) (0xff * selectionTrProgress)) << 24; + int color = alpha | 0xFFFF00; + renderSelectionEffect( + guiGraphics, + x, + y, + color, + SELECTION_EFFECT_RADIUS + ); + } + } else { + if (value.selected) { + renderSelectionEffect( + guiGraphics, + x, + y, + SELECTION_EFFECT_COLOR, + SELECTION_EFFECT_RADIUS + ); + } + } + } for (SelectionItem value : items) { float x = value.center.x; float y = value.center.y; @@ -313,21 +387,6 @@ public void render(GuiGraphics guiGraphics, int mouseX, int mouseY, float partia RenderSystem.disableBlend(); } - private void renderSelection(GuiGraphics guiGraphics) { - items.stream() - .filter(it -> it.state == currentBlockState) - .findFirst() - .ifPresent(it -> { - renderSelectionEffect( - guiGraphics, - it.center.x, - it.center.y, - SELECTION_EFFECT_COLOR, - SELECTION_EFFECT_RADIUS - ); - }); - } - private static void renderSelectionEffect( GuiGraphics guiGraphics, float centerX, @@ -474,12 +533,63 @@ public RenderType renderType() { return ModRenderTypes.TRANSLUCENT_COLORED_OVERLAY; } - private record SelectionItem( - Vector2f center, - float detectionAngleStart, - float detectionAngleEnd, - BlockState state, - Component description - ) { + private static final class SelectionItem { + private final Vector2f center; + private final float detectionAngleStart; + private final float detectionAngleEnd; + private final BlockState state; + private final Component description; + private TransformationType transformation = TransformationType.LIT; + private long transformationStartTime = 0; + private boolean selected = false; + + private SelectionItem( + Vector2f center, + float detectionAngleStart, + float detectionAngleEnd, + BlockState state, + Component description + ) { + this.center = center; + this.detectionAngleStart = detectionAngleStart; + this.detectionAngleEnd = detectionAngleEnd; + this.state = state; + this.description = description; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) return true; + if (obj == null || obj.getClass() != this.getClass()) return false; + var that = (SelectionItem) obj; + return Objects.equals(this.center, that.center) && + Float.floatToIntBits(this.detectionAngleStart) == Float.floatToIntBits(that.detectionAngleStart) && + Float.floatToIntBits(this.detectionAngleEnd) == Float.floatToIntBits(that.detectionAngleEnd) && + Objects.equals(this.state, that.state) && + Objects.equals(this.description, that.description); + } + + @Override + public int hashCode() { + return Objects.hash(center, detectionAngleStart, detectionAngleEnd, state, description); + } + + public boolean shouldRenderTransformation() { + if (transformationStartTime == 0) return false; + return System.currentTimeMillis() - transformationStartTime <= SELECTION_TRANSFORMATION; + } + + public float getTransformationProgress() { + if (!shouldRenderTransformation()) return 1; + return Math.clamp( + (System.currentTimeMillis() - transformationStartTime) / (float) SELECTION_TRANSFORMATION, + 0f, + 1f + ); + } + } + + enum TransformationType { + LIT, EXTINGUISH } } diff --git a/src/main/resources/assets/anvilcraft/shaders/core/selection.fsh b/src/main/resources/assets/anvilcraft/shaders/core/selection.fsh index 1c1d2fb09..8eae13b30 100644 --- a/src/main/resources/assets/anvilcraft/shaders/core/selection.fsh +++ b/src/main/resources/assets/anvilcraft/shaders/core/selection.fsh @@ -16,7 +16,7 @@ void main() { vec4 color = vec4(0, 0, 0, 0); if (distance <= Radius) { color = vertexColor; - color.a = smoothstep(Radius, 0.0, distance); + color.a = smoothstep(Radius, 0.0, distance) * vertexColor.a; } fragColor = color * ColorModulator;