Add overlay for keyboard screen, hide hotbar. Improve input handling.

This commit is contained in:
Florian Nücke
2022-02-04 16:41:31 +01:00
parent 5e605c3400
commit 2b9b2399f5
2 changed files with 115 additions and 6 deletions

View File

@@ -3,6 +3,8 @@
package li.cil.oc2.client.gui;
import com.mojang.blaze3d.platform.InputConstants;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.*;
import li.cil.oc2.common.blockentity.KeyboardBlockEntity;
import li.cil.oc2.common.item.Items;
import li.cil.oc2.common.network.Network;
@@ -10,10 +12,29 @@ import li.cil.oc2.common.network.message.KeyboardInputMessage;
import net.minecraft.client.Minecraft;
import net.minecraft.client.MouseHandler;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.client.gui.ForgeIngameGui;
import net.minecraftforge.client.gui.OverlayRegistry;
import org.lwjgl.glfw.GLFW;
import java.util.Random;
public final class KeyboardScreen extends Screen {
private static final int BORDER_SIZE = 4;
private static final float ARM_SWING_RATE = 0.8f;
private static final int BORDER_COLOR = 0xFFFFFFFF;
private static final int ESCAPE_DOUBLE_TAP_WINDOW = 300;
private static final TranslatableComponent CLOSE_INFO = new TranslatableComponent("gui.oc2.keyboard.close_info");
///////////////////////////////////////////////////////////////////
private final KeyboardBlockEntity keyboard;
private long lastEscapePress;
///////////////////////////////////////////////////////////////////
@@ -31,6 +52,11 @@ public final class KeyboardScreen extends Screen {
// Grabbing the mouse allows us to let the player keep turning the camera (to get a better
// look at the projection of a projector, e.g.), while still grabbing all keyboard input.
grabMouse();
lastEscapePress = 0;
// Disable hotbar since we don't need it here, and it just blocks screen space.
OverlayRegistry.enableOverlay(ForgeIngameGui.HOTBAR_ELEMENT, false);
}
@Override
@@ -47,19 +73,49 @@ public final class KeyboardScreen extends Screen {
@Override
public boolean keyPressed(final int keycode, final int scancode, final int modifiers) {
sendInputMessage(keycode, true);
return super.keyPressed(keycode, scancode, modifiers);
if (keycode == GLFW.GLFW_KEY_ESCAPE) {
if (lastEscapePress != 0 && System.currentTimeMillis() - lastEscapePress <= ESCAPE_DOUBLE_TAP_WINDOW) {
lastEscapePress = 0;
onClose();
} else {
lastEscapePress = System.currentTimeMillis();
sendInputMessage(keycode, true);
}
} else if (!super.keyPressed(keycode, scancode, modifiers)) {
sendInputMessage(keycode, true);
}
return true;
}
@Override
public boolean keyReleased(final int keycode, final int scancode, final int modifiers) {
sendInputMessage(keycode, false);
return super.keyReleased(keycode, scancode, modifiers);
if (keycode == GLFW.GLFW_KEY_ESCAPE) {
sendInputMessage(keycode, false);
} else if (!super.keyReleased(keycode, scancode, modifiers)) {
sendInputMessage(keycode, false);
}
return true;
}
@Override
public void mouseMoved(final double p_94758_, final double p_94759_) {
super.mouseMoved(p_94758_, p_94759_);
public boolean mouseClicked(final double mouseX, final double mouseY, final int button) {
if (button == GLFW.GLFW_MOUSE_BUTTON_2) {
onClose();
return true;
} else {
return super.mouseClicked(mouseX, mouseY, button);
}
}
@Override
public void render(final PoseStack stack, final int mouseX, final int mouseY, final float partialTicks) {
super.render(stack, mouseX, mouseY, partialTicks);
renderBorderOverlay(stack);
font.drawWordWrap(CLOSE_INFO,
BORDER_SIZE * 3, height - BORDER_SIZE * 3 - font.lineHeight,
width - BORDER_SIZE * 6, 0x88FFFFFF);
}
@Override
@@ -67,8 +123,34 @@ public final class KeyboardScreen extends Screen {
return false;
}
@Override
public void removed() {
super.removed();
OverlayRegistry.enableOverlay(ForgeIngameGui.HOTBAR_ELEMENT, true);
}
///////////////////////////////////////////////////////////////////
private void renderBorderOverlay(final PoseStack stack) {
blitQuad(stack, BORDER_SIZE, BORDER_SIZE, width - BORDER_SIZE, BORDER_SIZE * 2, BORDER_COLOR);
blitQuad(stack, BORDER_SIZE, BORDER_SIZE, BORDER_SIZE * 2, height - BORDER_SIZE, BORDER_COLOR);
blitQuad(stack, BORDER_SIZE, height - BORDER_SIZE * 2, width - BORDER_SIZE, height - BORDER_SIZE, BORDER_COLOR);
blitQuad(stack, width - BORDER_SIZE * 2, BORDER_SIZE, width - BORDER_SIZE, height - BORDER_SIZE, BORDER_COLOR);
}
private void blitQuad(final PoseStack stack, final int x0, final int y0, final int x1, final int y1, final int color) {
RenderSystem.setShader(GameRenderer::getPositionColorShader);
final Tesselator tesselator = Tesselator.getInstance();
final BufferBuilder builder = tesselator.getBuilder();
builder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR);
builder.vertex(stack.last().pose(), x0, y1, getBlitOffset()).color(color).endVertex();
builder.vertex(stack.last().pose(), x1, y1, getBlitOffset()).color(color).endVertex();
builder.vertex(stack.last().pose(), x1, y0, getBlitOffset()).color(color).endVertex();
builder.vertex(stack.last().pose(), x0, y0, getBlitOffset()).color(color).endVertex();
tesselator.end();
}
private void grabMouse() {
final Minecraft minecraft = getMinecraft();
final MouseHandler mouseHandler = minecraft.mouseHandler;
@@ -78,8 +160,31 @@ public final class KeyboardScreen extends Screen {
private void sendInputMessage(final int keycode, final boolean isDown) {
if (KeyCodeMapping.MAPPING.containsKey(keycode)) {
swingArm();
final int evdevCode = KeyCodeMapping.MAPPING.get(keycode);
Network.sendToServer(new KeyboardInputMessage(keyboard, evdevCode, isDown));
}
}
private void swingArm() {
final Minecraft minecraft = getMinecraft();
final LocalPlayer player = minecraft.player;
if (player == null) {
return;
}
final Random random = player.getRandom();
if (random.nextFloat() < ARM_SWING_RATE) {
return;
}
final InteractionHand handToSwing;
if (minecraft.options.getCameraType().isFirstPerson()) {
handToSwing = InteractionHand.MAIN_HAND;
} else {
handToSwing = random.nextBoolean() ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND;
}
player.swing(handToSwing);
}
}

View File

@@ -20,6 +20,8 @@
"block.oc2.creative_energy.desc": "Provides unlimited energy to adjacent blocks. Intended for testing.",
"block.oc2.projector": "Projector",
"block.oc2.projector.desc": "Projects images onto surfaces in front of it.",
"block.oc2.keyboard": "Keyboard",
"block.oc2.keyboard.desc": "Allows keyboard input when using a projector.",
"item.oc2.wrench": "Scrench",
"item.oc2.wrench.desc": "Configures devices and dismantles them (while sneaking).",
@@ -98,6 +100,8 @@
"gui.oc2.network_interface_card.connectivity.disabled": "Disabled",
"gui.oc2.network_interface_card.info": "Drag to rotate. Click faces to toggle connectivity.",
"gui.oc2.keyboard.close_info": "Right click or press [Escape] twice to close.",
"gui.oc2.network_tunnel.link": "Link",
"manual.oc2.home": "Home",