Add Event for Picture in Picture renderers registration.

This commit is contained in:
Mysticdrew authored and LexManos committed 2025-06-20 14:21:27 -07:00
1 parent 219abfed22
commit 9e55363e2c
8 files changed
+227

No files matched your search

@@ -127,3 +127,18 @@
j1 += clienttooltipcomponent2.getHeight(p_283128_) + (j2 == 0 ? 2 : 0);
}
@@ -1217,6 +_,14 @@
public void submitProfilerChartRenderState(List<ResultField> p_408565_, int p_410147_, int p_406156_, int p_407365_, int p_408180_) {
this.guiRenderState.submitPicturesInPictureState(new GuiProfilerChartRenderState(p_408565_, p_410147_, p_406156_, p_407365_, p_408180_, this.scissorStack.peek()));
+ }
+
+ public GuiRenderState getRenderState() {
+ return this.guiRenderState;
+ }
+
+ public GuiGraphics.ScissorStack getScissorStack() {
+ return this.scissorStack;
}
@OnlyIn(Dist.CLIENT)
@@ -0,0 +1,10 @@
--- a/net/minecraft/client/gui/render/GuiRenderer.java
+++ b/net/minecraft/client/gui/render/GuiRenderer.java
@@ -134,6 +_,7 @@
builder.put((Class<? extends PictureInPictureRenderState>)pictureinpicturerenderer.getRenderStateClass(), pictureinpicturerenderer);
}
+ net.minecraftforge.client.ForgeHooksClient.onRegisterPictureInPictureRenderers(p_410565_, p_410441_, builder);
this.pictureInPictureRenderers = builder.buildOrThrow();
}
@@ -26,6 +26,8 @@ import net.minecraft.client.gui.Font;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.components.ChatComponent;
import net.minecraft.client.gui.components.LerpingBossEvent;
import net.minecraft.client.gui.render.pip.PictureInPictureRenderer;
import net.minecraft.client.gui.render.state.pip.PictureInPictureRenderState;
import net.minecraft.client.gui.screens.ConfirmScreen;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent;
@@ -96,6 +98,7 @@ import net.minecraftforge.client.event.ClientChatEvent;
import net.minecraftforge.client.event.ClientChatReceivedEvent;
import net.minecraftforge.client.event.ClientPauseChangeEvent;
import net.minecraftforge.client.event.ClientPlayerChangeGameTypeEvent;
import net.minecraftforge.client.event.RegisterPictureInPictureRendererEvent;
import net.minecraftforge.client.event.SystemMessageReceivedEvent;
import net.minecraftforge.client.event.CustomizeGuiOverlayEvent;
import net.minecraftforge.client.event.EntityRenderersEvent;
@@ -151,6 +154,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@@ -596,6 +600,12 @@ public class ForgeHooksClient {
ModLoader.get().postEvent(new RegisterKeyMappingsEvent(options));
}
public static void onRegisterPictureInPictureRenderers(List<PictureInPictureRenderer<?>> renderers,
MultiBufferSource.BufferSource bufferSource,
ImmutableMap.Builder<Class<? extends PictureInPictureRenderState>, PictureInPictureRenderer<?>> builder) {
RegisterPictureInPictureRendererEvent.BUS.post(new RegisterPictureInPictureRendererEvent(renderers, bufferSource, builder));
}
@Nullable
public static Component onClientChat(ChatType.Bound boundChatType, Component message, UUID sender) {
ClientChatReceivedEvent event = new ClientChatReceivedEvent(boundChatType, message, sender);
@@ -0,0 +1,54 @@
/*
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.client.event;
import com.google.common.collect.ImmutableMap;
import net.minecraft.client.gui.render.pip.PictureInPictureRenderer;
import net.minecraft.client.gui.render.state.pip.PictureInPictureRenderState;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraftforge.eventbus.api.bus.EventBus;
import net.minecraftforge.eventbus.api.event.MutableEvent;
import net.minecraftforge.eventbus.api.event.characteristic.SelfDestructing;
import net.minecraftforge.fml.LogicalSide;
import org.jetbrains.annotations.ApiStatus;
import java.util.HashSet;
import java.util.List;
/**
* Used for registering custom picture in picture renderers.
* <p>
* Fired at the beginning of the loading screen when starting minecraft.
* Cannot be used to replace vanilla picture in picture renderers.
* This event is fired only on the {@linkplain LogicalSide#CLIENT logical client}
*/
public final class RegisterPictureInPictureRendererEvent extends MutableEvent implements SelfDestructing {
public static final EventBus<RegisterPictureInPictureRendererEvent> BUS = EventBus.create(RegisterPictureInPictureRendererEvent.class);
private final List<PictureInPictureRenderer<?>> renderers;
private final MultiBufferSource.BufferSource bufferSource;
private final ImmutableMap.Builder<Class<? extends PictureInPictureRenderState>, PictureInPictureRenderer<?>> builder;
@ApiStatus.Internal
public RegisterPictureInPictureRendererEvent(List<PictureInPictureRenderer<?>> renderers, MultiBufferSource.BufferSource bufferSource, ImmutableMap.Builder<Class<? extends PictureInPictureRenderState>, PictureInPictureRenderer<?>> builder) {
this.renderers = renderers;
this.bufferSource = bufferSource;
this.builder = builder;
}
public MultiBufferSource.BufferSource getBufferSource() {
return bufferSource;
}
public void register(PictureInPictureRenderer<?> renderer) {
var seen = HashSet.newHashSet(renderers.size());
for (var r : renderers)
seen.add(r.getRenderStateClass());
var key = renderer.getRenderStateClass();
if (seen.add(key))
this.builder.put(key, renderer);
}
}
@@ -344,6 +344,8 @@ public net.minecraft.client.data.models.ModelProvider$ItemInfoCollector
public net.minecraft.client.data.models.ModelProvider$ItemInfoCollector <init>()V # constructor
public net.minecraft.client.data.models.ModelProvider$SimpleModelCollector
public net.minecraft.client.data.models.ModelProvider$SimpleModelCollector <init>()V # constructor
public net.minecraft.client.gui.GuiGraphics$ScissorStack
public net.minecraft.client.gui.GuiGraphics$ScissorStack <init>()V # constructor
protected net.minecraft.client.gui.components.AbstractButton f_290895_ # SPRITES
protected net.minecraft.client.gui.components.AbstractSelectionList$Entry f_93521_ # list
protected net.minecraft.client.gui.components.AbstractSliderButton m_293290_()Lnet/minecraft/resources/ResourceLocation; # getHandleSprite
@@ -0,0 +1,7 @@
{
"type": "minecraft:function",
"environment": "minecraft:default",
"function": "forge:pip_test/was_registered",
"max_ticks": 100,
"structure": "forge:empty3x3x3"
}
@@ -0,0 +1,128 @@
/*
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.debug.client;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.navigation.ScreenPosition;
import net.minecraft.client.gui.navigation.ScreenRectangle;
import net.minecraft.client.gui.render.pip.PictureInPictureRenderer;
import net.minecraft.client.gui.render.state.pip.PictureInPictureRenderState;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.gametest.framework.GameTestHelper;
import net.minecraftforge.client.event.RegisterPictureInPictureRendererEvent;
import net.minecraftforge.client.event.ScreenEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.gametest.GameTest;
import net.minecraftforge.gametest.GameTestNamespace;
import net.minecraftforge.test.BaseTestMod;
import java.awt.Color;
import java.util.Map;
@GameTestNamespace("forge")
@Mod(PictureInPictureTest.MODID)
public class PictureInPictureTest extends BaseTestMod {
public static final String MODID = "pip_test";
private static int RENDER_FRAMES = 0;
public PictureInPictureTest(FMLJavaModLoadingContext context) {
super(context, false, false);
RegisterPictureInPictureRendererEvent.BUS.addListener(this::registerTestPip);
ScreenEvent.BackgroundRendered.BUS.addListener(this::onScreenBackground);
}
@GameTest
public static void was_registered(GameTestHelper helper) throws IllegalAccessException, NoSuchFieldException {
// Get the GameRenderer instance
var gameRenderer = Minecraft.getInstance().gameRenderer;
// Get the guiRenderer field from GameRenderer class
var guiRendererField = gameRenderer.getClass().getDeclaredField("guiRenderer");
guiRendererField.setAccessible(true);
// Get the guiRenderer instance
var guiRenderer = guiRendererField.get(gameRenderer);
// Get the pictureInPictureRenderers field from GuiRenderer class
var pictureInPictureRenderersField = guiRenderer.getClass().getDeclaredField("pictureInPictureRenderers");
pictureInPictureRenderersField.setAccessible(true);
// Get the pictureInPictureRenderers map
Map<?,?> pictureInPictureRenderers = (Map<?, ?>) pictureInPictureRenderersField.get(guiRenderer);
helper.assertTrue(pictureInPictureRenderers != null, "PictureInPictureRenderer map was null");
helper.assertTrue(pictureInPictureRenderers.containsKey(TestPipRendererState.class), "PictureInPictureRenderer was not registered");
helper.succeed();
// This is just a example feedback, doesn't matter too much so just show it when the test is run.
RENDER_FRAMES = 100;
}
// this will draw a blue box outline in red in the top left corner of a screen.
private void onScreenBackground(ScreenEvent.BackgroundRendered event) {
if (RENDER_FRAMES <= 0)
return;
RENDER_FRAMES--;
var window = Minecraft.getInstance().getWindow();
event.getGuiGraphics().getRenderState().submitPicturesInPictureState(new TestPipRendererState(
event.getGuiGraphics(),
10,
10,
20,
20,
new ScreenRectangle(new ScreenPosition(0, 0), window.getGuiScaledWidth(), window.getGuiScaledHeight())));
}
private void registerTestPip(RegisterPictureInPictureRendererEvent event) {
event.register(new TestPipRenderer(event.getBufferSource()));
}
static class TestPipRenderer extends PictureInPictureRenderer<TestPipRendererState> {
protected TestPipRenderer(MultiBufferSource.BufferSource bufferSource) {
super(bufferSource);
}
@Override
public Class<TestPipRendererState> getRenderStateClass() {
return TestPipRendererState.class;
}
@Override
protected void renderToTexture(TestPipRendererState state, PoseStack poseStack) {
var graphics = state.graphics();
int red = Color.red.getRGB();
int x1 = state.x0 - 1;
int y1 = state.y0 - 1;
int x2 = x1 + state.x1() + 2;
int y2 = y1 + state.y1() + 2;
graphics.fill(x1 + 2, y1+ 2, x2, y2, Color.BLUE.getRGB());
graphics.fill(x1, y1, x2, y1 + 2, red);
graphics.fill(x1, y2, x2, y2 + 2, red);
graphics.fill(x1, y1, x1 + 2, y2, red);
graphics.fill(x2, y1, x2 + 2, y2 + 2, red);
}
@Override
protected String getTextureLabel() {
return "test_pip_renderer";
}
}
record TestPipRendererState(GuiGraphics graphics, int x0, int y0, int x1, int y1, ScreenRectangle scissorArea, ScreenRectangle bounds) implements PictureInPictureRenderState {
public TestPipRendererState(GuiGraphics graphics, int x0, int y0, int x1, int y1, ScreenRectangle scissorArea) {
this(graphics, x0, y0, x1, y1, scissorArea, PictureInPictureRenderState.getBounds(x0, y0, x1, y1, scissorArea));
}
@Override
public float scale() {
return 32;
}
}
}
@@ -0,0 +1 @@
clientSideOnly=true