Compare commits

..
4 Commits
Author SHA1 Message Date
selimaj-dev 30f65bd914 Merge pull request 'Bring in the UI redesign' (#35) from ui-redesign into master
Reviewed-on: #35
2026-09-27 16:32:20 +00:00
selimaj-devandclaude bedb45c8aa Point common at the UI redesign
Check / compile (pull_request) Successful in 2m39s
common#6 redesigns the mod menu, mod and client settings and cosmetics
screens, which the two commits before this one build on.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-27 18:28:20 +02:00
selimaj-devandclaude 1602520624 Blur behind Saturn's screens on 1.21.6+
From 1.21.6 vanilla's renderBackground drew its own panorama and blurred
at the vanilla setting, then Saturn's panorama was drawn unblurred on top.
SaturnScreenFabric now draws Saturn's panorama in renderBackground, blurs
it and keeps vanilla's darkening in a world, and GameRendererMixin gives
the blur shader Saturn's strength while a Saturn screen is open. Before
1.21.6 the existing blur reads the same setting.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-27 18:26:42 +02:00
selimaj-devandclaude f69c379ae1 Draw the player preview at a given yaw
EntityDrawerImpl follows common's new EntityDrawer contract: it draws the
player filling the preview box, turned by the yaw the cosmetics screen's
drag sets, and returns false when there's no player. The angle no longer
follows the cursor.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-27 17:33:25 +02:00
4 changed files with 82 additions and 43 deletions
+1 -1
Submodule common updated: 15fa973553...caf472da96
@@ -1,12 +1,20 @@
package org.saturnclient.impl.features.mixins.render;
//? if >=1.21.6
import net.minecraft.client.MinecraftClient;
//? if >=1.21.6
import net.minecraft.client.option.GameOptions;
import net.minecraft.client.render.GameRenderer;
//? if >=1.21.6
import org.saturnclient.impl.ui.SaturnScreenFabric;
import org.saturnclient.mod.mods.FreelookMod;
import org.saturnclient.mod.mods.ZoomMod;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
//? if >=1.21.6
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
/**
@@ -38,4 +46,18 @@ public class GameRendererMixin {
cir.setReturnValue(zoomedFov);
}
}
//? if >=1.21.6 {
// From 1.21.6 the menu blur's strength is the vanilla setting, read here every frame. While a
// Saturn screen is open, it's Saturn's background blur instead, faded in with the screen.
@Redirect(method = "render", at = @At(value = "INVOKE",
target = "Lnet/minecraft/client/option/GameOptions;getMenuBackgroundBlurrinessValue()I"))
private int useSaturnBlur(GameOptions options) {
if (MinecraftClient.getInstance().currentScreen instanceof SaturnScreenFabric saturnScreen) {
return saturnScreen.screen.getBackgroundBlur();
}
return options.getMenuBackgroundBlurrinessValue();
}
//?}
}
@@ -7,7 +7,6 @@ import org.jetbrains.annotations.Nullable;
import org.joml.Quaternionf;
import org.joml.Vector3f;
import org.saturnclient.saturnclient.SaturnClient;
import org.saturnclient.ui.ElementContext;
import org.saturnclient.ui.RenderScope;
import org.saturnclient.ui.components.SkinPreview.EntityDrawer;
@@ -21,33 +20,32 @@ import net.minecraft.entity.LivingEntity;
public class EntityDrawerImpl implements EntityDrawer {
@Override
public void render(RenderScope renderScope, boolean negativeAngle, float angle, float scale, ElementContext ctx) {
public boolean render(RenderScope renderScope, int width, int height, float yaw) {
LivingEntity entity = SaturnClient.client.player;
if (entity != null) {
drawEntity(renderScope, 0, 0, 75, 78, 30, 0.0625F, ctx.mouseX / scale, ctx.mouseY / scale,
SaturnClient.client.player);
if (entity == null) {
return false;
}
// The player is about 1.8 blocks tall; leave some room above and below.
drawEntity(renderScope, 0, 0, width, height, (int) (height / 2.2F), 0.0625F, yaw, entity);
return true;
}
// Draws the entity in the box, turned by yaw degrees (0 faces the viewer) with its head straight.
public static void drawEntity(RenderScope renderScope, int x1, int y1, int x2, int y2, int size, float scale,
float mouseX, float mouseY, LivingEntity entity) {
float f = (float) (x1 + x2) / 2.0F;
float g = (float) (y1 + y2) / 2.0F;
float yaw, LivingEntity entity) {
renderScope.enableScissor(x1, y1, x2, y2);
float h = (float) Math.atan((double) ((f - mouseX) / 40.0F));
float i = (float) Math.atan((double) ((g - mouseY) / 40.0F));
Quaternionf quaternionf = (new Quaternionf()).rotateZ((float) Math.PI);
Quaternionf quaternionf2 = (new Quaternionf()).rotateX(i * 20.0F * ((float) Math.PI / 180F));
quaternionf.mul(quaternionf2);
Quaternionf quaternionf2 = new Quaternionf();
float j = entity.bodyYaw;
float k = entity.getYaw();
float l = entity.getPitch();
float m = entity.lastHeadYaw;
float n = entity.headYaw;
entity.bodyYaw = 180.0F + h * 20.0F;
entity.setYaw(180.0F + h * 40.0F);
entity.setPitch(-i * 20.0F);
entity.bodyYaw = 180.0F + yaw;
entity.setYaw(180.0F + yaw);
entity.setPitch(0.0F);
entity.headYaw = entity.getYaw();
entity.lastHeadYaw = entity.getYaw();
float o = entity.getScale();
@@ -83,7 +81,6 @@ public class EntityDrawerImpl implements EntityDrawer {
import org.joml.Quaternionf;
import org.joml.Vector3f;
import org.saturnclient.saturnclient.SaturnClient;
import org.saturnclient.ui.ElementContext;
import org.saturnclient.ui.RenderScope;
import org.saturnclient.ui.components.SkinPreview.EntityDrawer;
@@ -92,14 +89,12 @@ import net.minecraft.client.render.entity.EntityRenderDispatcher;
import net.minecraft.entity.LivingEntity;
public class EntityDrawerImpl implements EntityDrawer {
// Draws the entity in the box, turned by yaw degrees (0 faces the viewer) with its head straight.
public static void drawEntity(RenderScope renderScope, int x1, int y1, int x2, int y2, int size, float f,
float mouseX,
float mouseY, LivingEntity entity, float angle, boolean negativeAngle) {
float yaw, LivingEntity entity) {
float g = (float) (x1 + x2) / 2.0F;
float h = (float) (y1 + y2) / 2.0F;
renderScope.enableScissor(0, 6, x2, y2);
float i = (float) Math.atan((double) ((g - mouseX) / 40.0F));
float j = (float) Math.atan((double) ((h - mouseY) / 40.0F));
renderScope.enableScissor(x1, y1, x2, y2);
Quaternionf quaternionf = (new Quaternionf()).rotateZ(3.1415927F);
float k = entity.bodyYaw;
float l = entity.getYaw();
@@ -109,10 +104,10 @@ public class EntityDrawerImpl implements EntityDrawer {
//? if <1.21.5
//float n = entity.prevHeadYaw;
float o = entity.headYaw;
entity.setYaw(angle);
entity.bodyYaw = angle;
entity.setPitch(-(j * 20.0F));
entity.headYaw = negativeAngle ? (i * 40.0F) + 180f : -(i * 40.0F);
entity.setYaw(180.0F + yaw);
entity.bodyYaw = 180.0F + yaw;
entity.setPitch(0.0F);
entity.headYaw = entity.getYaw();
//? if >=1.21.5
entity.lastHeadYaw = entity.getHeadYaw();
//? if <1.21.5
@@ -166,12 +161,15 @@ public class EntityDrawerImpl implements EntityDrawer {
}
@Override
public void render(RenderScope renderScope, boolean negativeAngle, float angle, float scale, ElementContext ctx) {
public boolean render(RenderScope renderScope, int width, int height, float yaw) {
LivingEntity entity = SaturnClient.client.player;
if (entity != null) {
drawEntity(renderScope, 0, 0, 75, 78, 30, 0.0625F, ctx.mouseX / scale, ctx.mouseY / scale, entity, angle,
negativeAngle);
if (entity == null) {
return false;
}
// The player is about 1.8 blocks tall; leave some room above and below.
drawEntity(renderScope, 0, 0, width, height, (int) (height / 2.2F), 0.0625F, yaw, entity);
return true;
}
}
*///?}
@@ -89,25 +89,18 @@ public class SaturnScreenFabric extends Screen implements ScreenProvider {
mouseX *= 2;
mouseY *= 2;
// From 1.21.6 the panorama renderer has no opacity (and takes no delta), so it's drawn fully
// opaque there.
if (panoramaReady && client.world == null && client.getCurrentServerEntry() == null) {
//? if >=1.21.6 {
ROTATING_PANORAMA_RENDERER.render(context, this.width, this.height, true);
//?} else
//ROTATING_PANORAMA_RENDERER.render(context, this.width, this.height, screen.backgroundOpacity, delta);
// From 1.21.6 the background, blur included, is drawn in renderBackground.
//? if <1.21.6 {
/*if (isShowingPanorama()) {
ROTATING_PANORAMA_RENDERER.render(context, this.width, this.height, screen.backgroundOpacity, delta);
}
// TODO: the background blur (screen.backgroundBlur) is only drawn before 1.21.6 so far. See
// also issue #23.
//? if <1.21.6 {
/*PostEffectProcessor postEffectProcessor = this.client.getShaderLoader().loadPostEffect(
PostEffectProcessor postEffectProcessor = this.client.getShaderLoader().loadPostEffect(
Identifier.ofVanilla("blur"),
DefaultFramebufferSet.MAIN_ONLY);
if (postEffectProcessor != null) {
float radius = screen.backgroundBlur * Math.min((float) elapsed / 700, 1.0f);
float radius = screen.getBackgroundBlur();
//? if >=1.21.5
postEffectProcessor.render(this.client.getFramebuffer(), this.pool, pass -> pass.setUniform("Radius", radius));
//? if <1.21.5
@@ -122,6 +115,32 @@ public class SaturnScreenFabric extends Screen implements ScreenProvider {
screen.render(renderScope, mouseX, mouseY, delta, elapsed);
}
//? if >=1.21.6 {
// Vanilla's background would cover Saturn's panorama, and blurs by the vanilla setting. The
// strength of this blur comes from GameRendererMixin, which gives Saturn's setting instead.
@Override
public void renderBackground(DrawContext context, int mouseX, int mouseY, float delta) {
// The panorama renderer has no opacity (and takes no delta) from 1.21.6, so it's drawn fully
// opaque.
if (isShowingPanorama()) {
ROTATING_PANORAMA_RENDERER.render(context, this.width, this.height, true);
}
if (screen.getBackgroundBlur() >= 1) {
context.applyBlur();
}
if (client.world != null) {
renderDarkening(context);
}
}
//?}
/** Whether Saturn's panorama is behind the screen: outside a world, once it's loaded. */
private boolean isShowingPanorama() {
return panoramaReady && client.world == null && client.getCurrentServerEntry() == null;
}
// 1.21.9 moved mouse and key events to Click and KeyInput.
//? if >=1.21.9 {
@Override