minecraft-src/net/minecraft/client/gui/screens/AccessibilityOnboardingScreen.java
2025-09-18 12:27:44 +00:00

168 lines
5.6 KiB
Java

package net.minecraft.client.gui.screens;
import com.mojang.text2speech.Narrator;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.Util;
import net.minecraft.client.Minecraft;
import net.minecraft.client.Options;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.components.Button;
import net.minecraft.client.gui.components.CommonButtons;
import net.minecraft.client.gui.components.CycleButton;
import net.minecraft.client.gui.components.FocusableTextWidget;
import net.minecraft.client.gui.components.LogoRenderer;
import net.minecraft.client.gui.layouts.HeaderAndFooterLayout;
import net.minecraft.client.gui.layouts.LinearLayout;
import net.minecraft.client.gui.screens.options.AccessibilityOptionsScreen;
import net.minecraft.client.gui.screens.options.LanguageSelectScreen;
import net.minecraft.network.chat.CommonComponents;
import net.minecraft.network.chat.Component;
import net.minecraft.util.Mth;
import org.jetbrains.annotations.Nullable;
@Environment(EnvType.CLIENT)
public class AccessibilityOnboardingScreen extends Screen {
private static final Component TITLE = Component.translatable("accessibility.onboarding.screen.title");
private static final Component ONBOARDING_NARRATOR_MESSAGE = Component.translatable("accessibility.onboarding.screen.narrator");
private static final int PADDING = 4;
private static final int TITLE_PADDING = 16;
private static final float FADE_OUT_TIME = 1000.0F;
private final LogoRenderer logoRenderer;
private final Options options;
private final boolean narratorAvailable;
private boolean hasNarrated;
private float timer;
private final Runnable onClose;
@Nullable
private FocusableTextWidget textWidget;
private final HeaderAndFooterLayout layout = new HeaderAndFooterLayout(this, this.initTitleYPos(), 33);
private float fadeInStart;
private boolean fadingIn = true;
private float fadeOutStart;
public AccessibilityOnboardingScreen(Options options, Runnable onClose) {
super(TITLE);
this.options = options;
this.onClose = onClose;
this.logoRenderer = new LogoRenderer(true);
this.narratorAvailable = Minecraft.getInstance().getNarrator().isActive();
}
@Override
public void init() {
LinearLayout linearLayout = this.layout.addToContents(LinearLayout.vertical());
linearLayout.defaultCellSetting().alignHorizontallyCenter().padding(4);
this.textWidget = linearLayout.addChild(new FocusableTextWidget(this.width, this.title, this.font), layoutSettings -> layoutSettings.padding(8));
if (this.options.narrator().createButton(this.options) instanceof CycleButton cycleButton) {
this.narratorButton = cycleButton;
this.narratorButton.active = this.narratorAvailable;
linearLayout.addChild(this.narratorButton);
}
linearLayout.addChild(CommonButtons.accessibility(150, button -> this.closeAndSetScreen(new AccessibilityOptionsScreen(this, this.minecraft.options)), false));
linearLayout.addChild(
CommonButtons.language(
150, button -> this.closeAndSetScreen(new LanguageSelectScreen(this, this.minecraft.options, this.minecraft.getLanguageManager())), false
)
);
this.layout.addToFooter(Button.builder(CommonComponents.GUI_CONTINUE, button -> this.onClose()).build());
this.layout.visitWidgets(this::addRenderableWidget);
this.repositionElements();
}
@Override
protected void repositionElements() {
if (this.textWidget != null) {
this.textWidget.containWithin(this.width);
}
this.layout.arrangeElements();
}
@Override
protected void setInitialFocus() {
if (this.narratorAvailable && this.narratorButton != null) {
this.setInitialFocus(this.narratorButton);
} else {
super.setInitialFocus();
}
}
private int initTitleYPos() {
return 90;
}
@Override
public void onClose() {
this.fadeOutStart = (float)Util.getMillis();
}
private void closeAndSetScreen(Screen screen) {
this.close(false, () -> this.minecraft.setScreen(screen));
}
private void close(boolean markAsFinished, Runnable onClose) {
if (markAsFinished) {
this.options.onboardingAccessibilityFinished();
}
Narrator.getNarrator().clear();
onClose.run();
}
@Override
public void render(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick) {
super.render(guiGraphics, mouseX, mouseY, partialTick);
this.handleInitialNarrationDelay();
if (this.fadeInStart == 0.0F && this.fadingIn) {
this.fadeInStart = (float)Util.getMillis();
}
if (this.fadeInStart > 0.0F) {
float f = ((float)Util.getMillis() - this.fadeInStart) / 2000.0F;
float g = 1.0F;
if (f >= 1.0F) {
this.fadingIn = false;
this.fadeInStart = 0.0F;
} else {
f = Mth.clamp(f, 0.0F, 1.0F);
g = Mth.clampedMap(f, 0.5F, 1.0F, 0.0F, 1.0F);
}
this.fadeWidgets(g);
}
if (this.fadeOutStart > 0.0F) {
float f = 1.0F - ((float)Util.getMillis() - this.fadeOutStart) / 1000.0F;
float g = 0.0F;
if (f <= 0.0F) {
this.fadeOutStart = 0.0F;
this.close(true, this.onClose);
} else {
f = Mth.clamp(f, 0.0F, 1.0F);
g = Mth.clampedMap(f, 0.5F, 1.0F, 0.0F, 1.0F);
}
this.fadeWidgets(g);
}
this.logoRenderer.renderLogo(guiGraphics, this.width, 1.0F);
}
@Override
protected void renderPanorama(GuiGraphics guiGraphics, float partialTick) {
this.minecraft.gameRenderer.getPanorama().render(guiGraphics, this.width, this.height, false);
}
private void handleInitialNarrationDelay() {
if (!this.hasNarrated && this.narratorAvailable) {
if (this.timer < 40.0F) {
this.timer++;
} else if (this.minecraft.isWindowActive()) {
Narrator.getNarrator().say(ONBOARDING_NARRATOR_MESSAGE.getString(), true, 1.0F);
this.hasNarrated = true;
}
}
}
}