Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,10 @@ private void drawCircle(Entity entity, double rad, boolean shade) {
GL11.glEnd();
} finally {
if (shade) {
GL11.glShadeModel(GL11.GL_FLAT);
// 还原成 SMOOTH,不是 FLAT:原版 GUI/世界渲染从不碰 shade model,
// 基线一直是 GL 默认的 GL_SMOOTH。这里留 FLAT,之后所有逐顶点着色的
// 渐变(ClickGUI 调色板的 SV 方块、色相条、透明度条)都会被拍成一块纯色。
GL11.glShadeModel(GL11.GL_SMOOTH);
}
GlStateManager.depthMask(true);
GlStateManager.enableLighting();
Expand Down
13 changes: 12 additions & 1 deletion src/main/java/top/fpsmaster/ui/kit/EdgeUi.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@
public final class EdgeUi {
private static UiFrame current;
private static final FrameInput fallback = new FrameInput();
/**
* 这一帧是不是宿主屏幕开的。键鼠缓冲只有喂过 {@link #keyTyped} 的那一帧有权清:
* HUD 覆盖层每帧都 begin/end 一次、又排在 drawScreen 前面,无脑清会把玩家这一帧
* 敲的键冲掉——绑定按钮和文本框双双点不动,纯鼠标的开关滑条却照常。
*/
private static boolean screenFrame;

private EdgeUi() {
}
Expand All @@ -26,14 +32,19 @@ public static void begin(ScaledGuiScreen screen) {
float w = screen == null ? 0f : screen.guiWidth;
float h = screen == null ? 0f : screen.guiHeight;
current = new UiFrame(new EdgeHost(screen, fallback, w, h), theme());
screenFrame = true;
}

public static void beginOverlay(float guiWidth, float guiHeight) {
current = new UiFrame(new EdgeHost(null, fallback, guiWidth, guiHeight), theme());
screenFrame = false;
}

public static void end() {
fallback.endFrame();
if (screenFrame) {
fallback.endFrame();
}
screenFrame = false;
EdgeCanvas.clearPanelClip();
current = null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
import net.minecraft.client.renderer.entity.RenderManager;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.util.ResourceLocation;
import org.lwjgl.BufferUtils;
import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.GL11;
import top.fpsmaster.FPSMaster;
import top.fpsmaster.exception.FileException;
import top.fpsmaster.cosmetic.CosmeticManager;
Expand All @@ -28,6 +30,7 @@
import com.google.gson.JsonObject;

import java.io.IOException;
import java.nio.IntBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
Expand All @@ -40,6 +43,10 @@ public final class CosmeticsScreen extends ScaledGuiScreen {
private final EdgeCosmeticsBridge bridge = new EdgeCosmeticsBridge();
private final float[] preview = new float[5];
private final List<ItemPreview> itemPreviews = new ArrayList<>();
/** 商品列表的 GL 裁剪框,缩略图 2D 之后才画,得在回调那一刻抄下来照着裁。 */
private final IntBuffer previewScissor = BufferUtils.createIntBuffer(16);
private boolean previewScissorCaptured;
private boolean previewScissorEnabled;

public CosmeticsScreen(GuiScreen parent) {
this.parent = parent;
Expand All @@ -60,6 +67,8 @@ public void initGui() {
@Override
public void render(int mouseX, int mouseY, float partialTicks) {
itemPreviews.clear();
previewScissorCaptured = false;
previewScissorEnabled = false;
if (cosmetics.draw(EdgeUi.frame(), bridge)) {
mc.displayGuiScreen(parent);
return;
Expand All @@ -81,25 +90,53 @@ public void render(int mouseX, int mouseY, float partialTicks) {
}

private void renderItemPreviews() {
for (ItemPreview itemPreview : itemPreviews) {
ResourceLocation texture = bridge.cosmetics.textureFor(itemPreview.item.id());
if ("wings".equals(itemPreview.item.category())) {
if (!itemPreview.item.builtin() && texture == null) continue;
float size = Math.max(12f, itemPreview.h * 0.4f);
bridge.cosmetics.wingsRenderer().renderPreview(
itemPreview.x + itemPreview.w * 0.5f,
itemPreview.y + itemPreview.h - 1f,
size,
180f,
texture,
0.78f
);
} else if ("cape".equals(itemPreview.item.category()) && texture != null) {
renderCapeThumbnail(itemPreview, texture);
if (itemPreviews.isEmpty()) return;
// 缩略图是攒到 2D 通道结束之后才上屏的,那时 clip 栈已经弹空:不照着商品列表
// 当时那道裁剪框自己裁一刀,往下滚的时候缩略图会横穿列表边界糊到面板外面去。
boolean scissored = previewScissorEnabled;
if (scissored) {
GL11.glEnable(GL11.GL_SCISSOR_TEST);
GL11.glScissor(previewScissor.get(0), previewScissor.get(1),
previewScissor.get(2), previewScissor.get(3));
}
try {
for (ItemPreview itemPreview : itemPreviews) {
ResourceLocation texture = bridge.cosmetics.textureFor(itemPreview.item.id());
if ("wings".equals(itemPreview.item.category())) {
if (!itemPreview.item.builtin() && texture == null) continue;
float size = Math.max(12f, itemPreview.h * 0.4f);
bridge.cosmetics.wingsRenderer().renderPreview(
itemPreview.x + itemPreview.w * 0.5f,
itemPreview.y + itemPreview.h - 1f,
size,
180f,
texture,
0.78f
);
} else if ("cape".equals(itemPreview.item.category()) && texture != null) {
renderCapeThumbnail(itemPreview, texture);
}
}
} finally {
if (scissored) {
GL11.glDisable(GL11.GL_SCISSOR_TEST);
}
}
}

/**
* 抄一份当前 GL 裁剪框。商品列表是同一道裁剪,一帧抄一次就够。
*/
private void capturePreviewScissor() {
if (previewScissorCaptured) return;
previewScissorCaptured = true;
previewScissorEnabled = GL11.glIsEnabled(GL11.GL_SCISSOR_TEST);
if (previewScissorEnabled) {
previewScissor.clear();
GL11.glGetInteger(GL11.GL_SCISSOR_BOX, previewScissor);
}
}

private void renderCapeThumbnail(ItemPreview itemPreview, ResourceLocation texture) {
float size = Math.max(18f, itemPreview.h * 0.76f);
GlStateManager.enableColorMaterial();
Expand Down Expand Up @@ -323,6 +360,7 @@ public void purchaseItem(String id) {
public void paintItemPreview(UiFrame ui, CosmeticsBridge.Item item,
float x, float y, float w, float h) {
itemPreviews.add(new ItemPreview(item, x, y, w, h));
capturePreviewScissor();
}
@Override
public void paintPlayerPreview(UiFrame ui, float x, float y, float w, float h, float yaw) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,12 @@ public void onGuiClosed() {

@Override
protected void keyTyped(char typedChar, int keyCode) throws IOException {
// handleInput 里先跑鼠标后跑键盘:本屏在 handleMouseInput 里关掉后,同一批
// Keyboard.next() 的余下按键仍会派到这个死实例上。缓冲现在只由宿主屏幕帧清,
// 死屏喂进来的键会一直攒到下一个 ScaledGuiScreen 打开才冒出来,直接丢掉。
if (mc.currentScreen != this) {
return;
}
EdgeUi.keyTyped(typedChar, keyCode);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,9 @@ public static void drawGradientVertical(float x, float y, float width, float hei
GL11.glVertex2f(x + width, y + height);
GL11.glEnd();

GL11.glShadeModel(7424);
// 回到 GL 默认的 SMOOTH(原版 GUI 从不设置 shade model,基线就是它)。
// 留 FLAT 会把之后所有逐顶点着色的渐变——比如 ClickGUI 调色板——拍成一块纯色。
GL11.glShadeModel(7425);
GL11.glEnable(3553);
GL11.glDisable(3042);
GL11.glEnable(2929);
Expand Down
Loading