diff --git a/src/main/java/mcp/mobius/waila/WailaClient.java b/src/main/java/mcp/mobius/waila/WailaClient.java index 847117677..03281ae40 100644 --- a/src/main/java/mcp/mobius/waila/WailaClient.java +++ b/src/main/java/mcp/mobius/waila/WailaClient.java @@ -32,6 +32,7 @@ public abstract class WailaClient { public static KeyMapping keyShowRecipeOutput; public static boolean showComponentBounds = false; + public static boolean showFps = false; @Nullable private static IRecipeAction recipeAction; diff --git a/src/main/java/mcp/mobius/waila/command/ClientCommand.java b/src/main/java/mcp/mobius/waila/command/ClientCommand.java index 8c3db7799..bc5b92bb0 100644 --- a/src/main/java/mcp/mobius/waila/command/ClientCommand.java +++ b/src/main/java/mcp/mobius/waila/command/ClientCommand.java @@ -127,23 +127,34 @@ public final void register(CommandDispatcher dispatcher) { .pop("enabled", "overlay"); - if (Waila.ENABLE_DEBUG_COMMAND) { - command - .then(argument.literal("debug")) - - .then(argument.literal("showComponentBounds")) - .then(argument.required("enabled", BoolArgumentType.bool())) - .suggests((context, builder) -> suggest(new String[]{String.valueOf(!WailaClient.showComponentBounds)}, builder)) - .executes(context -> { - var feedback = feedback(context.getSource()); - var enabled = BoolArgumentType.getBool(context, "enabled"); - Minecraft.getInstance().execute(() -> WailaClient.showComponentBounds = enabled); - feedback.success(Component.literal((enabled ? "En" : "Dis") + "abled component bounds")); - return enabled ? 1 : 0; - }) - - .pop("enabled", "showComponentBounds", "debug"); - } + if (Waila.ENABLE_DEBUG_COMMAND) command + .then(argument.literal("debug")) + + .then(argument.literal("showComponentBounds")) + .then(argument.required("enabled", BoolArgumentType.bool())) + .suggests((context, builder) -> suggest(new String[]{String.valueOf(!WailaClient.showComponentBounds)}, builder)) + .executes(context -> { + var feedback = feedback(context.getSource()); + var enabled = BoolArgumentType.getBool(context, "enabled"); + Minecraft.getInstance().execute(() -> WailaClient.showComponentBounds = enabled); + feedback.success(Component.literal((enabled ? "En" : "Dis") + "abled component bounds")); + return enabled ? 1 : 0; + }) + .pop("enabled", "showComponentBounds") + + .then(argument.literal("showFps")) + .then(argument.required("enabled", BoolArgumentType.bool())) + .suggests((context, builder) -> suggest(new String[]{String.valueOf(!WailaClient.showFps)}, builder)) + .executes(context -> { + var feedback = feedback(context.getSource()); + var enabled = BoolArgumentType.getBool(context, "enabled"); + Minecraft.getInstance().execute(() -> WailaClient.showFps = enabled); + feedback.success(Component.literal((enabled ? "En" : "Dis") + "abled FPS display")); + return enabled ? 1 : 0; + }) + .pop("enabled", "showFps") + + .pop("debug"); command.register(dispatcher); } diff --git a/src/main/java/mcp/mobius/waila/config/WailaConfig.java b/src/main/java/mcp/mobius/waila/config/WailaConfig.java index 4c1085020..803061a97 100644 --- a/src/main/java/mcp/mobius/waila/config/WailaConfig.java +++ b/src/main/java/mcp/mobius/waila/config/WailaConfig.java @@ -139,6 +139,7 @@ public static class Overlay implements IWailaConfig.Overlay { private final Position position = new Position(); private final Color color = new Color(); private float scale = 1.0F; + private int fps = 30; @Override public Position getPosition() { @@ -159,6 +160,14 @@ public Color getColor() { return color; } + public int getFps() { + return fps; + } + + public void setFps(int fps) { + this.fps = fps; + } + public static class Position implements IWailaConfig.Overlay.Position { private final Align align = new Align(); diff --git a/src/main/java/mcp/mobius/waila/gui/hud/TooltipHandler.java b/src/main/java/mcp/mobius/waila/gui/hud/TooltipHandler.java index 66382f003..a1e3d65fd 100644 --- a/src/main/java/mcp/mobius/waila/gui/hud/TooltipHandler.java +++ b/src/main/java/mcp/mobius/waila/gui/hud/TooltipHandler.java @@ -207,6 +207,11 @@ private WailaConfig.Overlay getOverlay() { return Waila.CONFIG.get().getOverlay(); } + @Override + public int getFps() { + return getOverlay().getFps(); + } + @Override public float getScale() { return getOverlay().getScale(); diff --git a/src/main/java/mcp/mobius/waila/gui/hud/TooltipRenderer.java b/src/main/java/mcp/mobius/waila/gui/hud/TooltipRenderer.java index cf53ac8d9..4530cf207 100644 --- a/src/main/java/mcp/mobius/waila/gui/hud/TooltipRenderer.java +++ b/src/main/java/mcp/mobius/waila/gui/hud/TooltipRenderer.java @@ -6,8 +6,13 @@ import com.google.common.base.Preconditions; import com.google.common.base.Suppliers; +import com.mojang.blaze3d.pipeline.MainTarget; import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.DefaultVertexFormat; +import com.mojang.blaze3d.vertex.Tesselator; +import com.mojang.blaze3d.vertex.VertexFormat; import com.mojang.text2speech.Narrator; +import mcp.mobius.waila.WailaClient; import mcp.mobius.waila.access.DataAccessor; import mcp.mobius.waila.api.ITheme; import mcp.mobius.waila.api.ITooltipComponent; @@ -23,9 +28,10 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.screens.ChatScreen; +import net.minecraft.client.renderer.GameRenderer; import net.minecraft.util.Mth; +import org.jetbrains.annotations.Nullable; -import static mcp.mobius.waila.util.DisplayUtil.enable2DRender; import static mcp.mobius.waila.util.DisplayUtil.renderComponent; public class TooltipRenderer { @@ -46,6 +52,10 @@ public class TooltipRenderer { public static State state; + private static long lastFrame = System.nanoTime(); + private static @Nullable MainTarget framebuffer = null; + private static int fbWidth, fbHeight; + public static void beginBuild(State state) { started = true; TooltipRenderer.state = state; @@ -171,11 +181,76 @@ public static void resetState() { } public static void render(GuiGraphics ctx, float delta) { - if (state == null || !state.render()) { + var client = Minecraft.getInstance(); + + if (WailaClient.showFps) { + var fpsString = client.getFps() + " FPS"; + var x1 = client.font.width(fpsString) + 2; + var y0 = client.getWindow().getGuiScaledHeight() - client.font.lineHeight - 1; + var y1 = y0 + client.font.lineHeight + 2; + ctx.fill(0, y0, x1, y1, 0x90505050); + ctx.drawString(client.font, fpsString, 1, y0 + 1, 0xE0E0E0, false); + } + + if (state == null || !state.render()) return; + + var fps = state.getFps(); + + if (fps == 0) { + render0(client, ctx, delta); return; } - var client = Minecraft.getInstance(); + var nspf = 1_000_000_000f / fps; + var now = System.nanoTime(); + + if (framebuffer == null || (now - lastFrame) >= nspf) { + var window = client.getWindow(); + + if (framebuffer == null) { + framebuffer = new MainTarget(window.getWidth(), window.getHeight()); + framebuffer.setClearColor(0f, 0f, 0f, 0f); + } + + if (window.getWidth() != fbWidth || window.getHeight() != fbHeight) { + fbWidth = window.getWidth(); + fbHeight = window.getHeight(); + framebuffer.resize(fbWidth, fbHeight, Minecraft.ON_OSX); + } + + framebuffer.clear(Minecraft.ON_OSX); + framebuffer.bindWrite(true); + render0(client, ctx, delta); + framebuffer.unbindWrite(); + client.getMainRenderTarget().bindWrite(true); + lastFrame = now; + } + + RenderSystem.enableBlend(); + RenderSystem.defaultBlendFunc(); + RenderSystem.setShader(GameRenderer::getPositionTexShader); + RenderSystem.setShaderTexture(0, framebuffer.getColorTextureId()); + + var w = client.getWindow().getGuiScaledWidth(); + var h = client.getWindow().getGuiScaledHeight(); + + var tesselator = Tesselator.getInstance(); + var buffer = tesselator.getBuilder(); + + buffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX); + + var pose = ctx.pose().last().pose(); + buffer.vertex(pose, 0, h, 0).uv(0f, 0f).endVertex(); + buffer.vertex(pose, w, h, 0).uv(1f, 0f).endVertex(); + buffer.vertex(pose, w, 0, 0).uv(1f, 1f).endVertex(); + buffer.vertex(pose, 0, 0, 0).uv(0f, 1f).endVertex(); + + tesselator.end(); + + RenderSystem.disableBlend(); + } + + private static void render0(Minecraft client, GuiGraphics ctx, float delta) { var profiler = client.getProfiler(); profiler.push("Waila Overlay"); @@ -185,8 +260,6 @@ public static void render(GuiGraphics ctx, float delta) { ctx.pose().pushPose(); ctx.pose().scale(scale, scale, 1.0f); - enable2DRender(); - var rect = RENDER_RECT.get(); rect.setRect(TooltipRenderer.RECT.get()); @@ -305,6 +378,8 @@ public interface State { boolean fireEvent(); + int getFps(); + float getScale(); Align.X getXAnchor(); diff --git a/src/main/java/mcp/mobius/waila/gui/screen/ThemeEditorScreen.java b/src/main/java/mcp/mobius/waila/gui/screen/ThemeEditorScreen.java index f8aea5dd3..2b0812930 100644 --- a/src/main/java/mcp/mobius/waila/gui/screen/ThemeEditorScreen.java +++ b/src/main/java/mcp/mobius/waila/gui/screen/ThemeEditorScreen.java @@ -220,6 +220,11 @@ public boolean fireEvent() { return false; } + @Override + public int getFps() { + return 0; + } + @Override public float getScale() { return 2.0f; diff --git a/src/main/java/mcp/mobius/waila/gui/screen/WailaConfigScreen.java b/src/main/java/mcp/mobius/waila/gui/screen/WailaConfigScreen.java index b67049563..d48c0153b 100644 --- a/src/main/java/mcp/mobius/waila/gui/screen/WailaConfigScreen.java +++ b/src/main/java/mcp/mobius/waila/gui/screen/WailaConfigScreen.java @@ -56,6 +56,7 @@ public class WailaConfigScreen extends ConfigScreen { private ConfigValue modNameFormatVal; private ConfigValue blockNameFormatVal; + private ConfigValue fpsVal; private ConfigValue xPosValue; private ConfigValue xAnchorValue; private ConfigValue yAnchorValue; @@ -178,6 +179,11 @@ public ConfigListWidget getOptions() { Util.getPlatform().openFile(Waila.BLACKLIST_CONFIG.getPath().toFile()))); options.with(new CategoryEntry(Tl.Config.OVERLAY)) + .with(fpsVal = new InputValue<>(Tl.Config.OVERLAY_FPS, + get().getOverlay().getFps(), + defaultConfig.getOverlay().getFps(), + val -> get().getOverlay().setFps(val), + InputValue.POSITIVE_INTEGER)) .with(xAnchorValue = new EnumValue<>(Tl.Config.OVERLAY_ANCHOR_X, Align.X.values(), get().getOverlay().getPosition().getAnchor().getX(), @@ -384,6 +390,11 @@ public boolean fireEvent() { return false; } + @Override + public int getFps() { + return fpsVal.getValue(); + } + @Override public int getBackgroundAlpha() { return backgroundAlphaVal.getValue(); diff --git a/src/resources/resources/assets/waila/lang/en_us.json b/src/resources/resources/assets/waila/lang/en_us.json index 1af17244a..69a3afad0 100644 --- a/src/resources/resources/assets/waila/lang/en_us.json +++ b/src/resources/resources/assets/waila/lang/en_us.json @@ -124,6 +124,9 @@ "config.waila.overlay" : "Overlay", + "config.waila.overlay_fps" : "Overlay FPS", + "config.waila.overlay_fps_desc" : "Lowering the overlay FPS might improve the overall game FPS\nSet to 0 to unlock", + "config.waila.overlay_pos_x" : "X Offset", "config.waila.overlay_pos_x_desc" : "X position relative from screen anchor\nPosition is affected by scale", "config.waila.overlay_pos_y" : "Y Offset",