Skip to content
Open
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 @@ -37,7 +37,7 @@ public class GlowcaseClient implements ClientModInitializer {
public void onInitializeClient() {
Glowcase.proxy = new GlowcaseClientProxy();

BlockEntityRenderers.register(Glowcase.TEXT_BLOCK_ENTITY.get(), (ctx) -> new TextBlockEntityRenderer());
BlockEntityRenderers.register(Glowcase.TEXT_BLOCK_ENTITY.get(), (ctx) -> new TextBlockEntityRenderer(ctx));
BlockEntityRenderers.register(Glowcase.HYPERLINK_BLOCK_ENTITY.get(), HyperlinkBlockEntityRenderer::new);
BlockEntityRenderers.register(Glowcase.CONFIG_LINK_BLOCK_ENTITY.get(), ConfigLinkBlockEntityRenderer::new);
BlockEntityRenderers.register(Glowcase.ITEM_DISPLAY_BLOCK_ENTITY.get(), ItemDisplayBlockEntityRenderer::new);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,36 +7,49 @@
import dev.hephaestus.glowcase.client.util.BlockEntityRenderUtil;
import net.minecraft.client.gui.Font;
import net.minecraft.client.renderer.SubmitNodeCollector;
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer;
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider;
import net.minecraft.client.renderer.blockentity.state.BlockEntityRenderState;
import net.minecraft.client.renderer.feature.ModelFeatureRenderer;
import net.minecraft.client.renderer.state.level.CameraRenderState;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.Identifier;
import net.minecraft.util.FormattedCharSequence;
import net.minecraft.util.LightCoordsUtil;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.phys.Vec3;
import org.joml.Matrix4f;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;

import java.util.List;

@NullMarked
public class TextBlockEntityRenderer implements BakedBlockEntityRenderer<TextBlockEntity, TextBlockEntityRenderer.TextRenderState, TextBlockEntityRenderer.TextRenderState> {
public static Identifier ITEM_TEXTURE = Glowcase.id("textures/item/text_block.png");
private boolean wasOutOfRange = false;

private final Font font;

public TextBlockEntityRenderer(BlockEntityRendererProvider.Context ctx) {
this.font = ctx.font();
}

public static class TextRenderState extends BlockEntityRenderState {
public boolean shouldRenderPlaceholder;
public TextBlockEntity.ZOffset zOffset;
public int rotation16;
public List<FormattedCharSequence> lines = List.of();
public TextBlockEntity.TextAlignment textAlignment;
public TextBlockEntity.ZOffset zOffset;
public boolean shadow;
public float scale = 1;
public int color;
public int backgroundColor;
}

@Override
public TextRenderState createRenderState() {
return new TextRenderState();
}


@Override
public TextRenderState createBakedRenderState() {
return new TextRenderState();
Expand All @@ -46,8 +59,16 @@ public TextRenderState createBakedRenderState() {
public void extractRenderState(TextBlockEntity blockEntity, TextRenderState state, float partialTicks, Vec3 cameraPosition, ModelFeatureRenderer.@Nullable CrumblingOverlay breakProgress) {
BakedBlockEntityRenderer.super.extractRenderState(blockEntity, state, partialTicks, cameraPosition, breakProgress);
state.shouldRenderPlaceholder = blockEntity.lines.stream().allMatch(t -> t.getString().isBlank()) || BlockEntityRenderUtil.shouldRenderPlaceholder(blockEntity.getBlockPos());
state.zOffset = blockEntity.zOffset;

state.rotation16 = blockEntity.getBlockState().getValue(BlockStateProperties.ROTATION_16);

state.lines = blockEntity.lines.stream().map(Component::getVisualOrderText).toList();
state.textAlignment = blockEntity.textAlignment;
state.zOffset = blockEntity.zOffset;
state.shadow = blockEntity.shadow;
state.scale = blockEntity.scale;
state.color = blockEntity.color;
state.backgroundColor = blockEntity.backgroundColor;
}

@Override
Expand All @@ -57,30 +78,86 @@ public void extractBakingRenderState(TextBlockEntity blockEntity, TextRenderStat
state.shouldRenderPlaceholder = blockEntity.lines.stream().allMatch(t -> t.getString().isBlank()) || BlockEntityRenderUtil.shouldRenderPlaceholder(blockEntity.getBlockPos());
state.zOffset = blockEntity.zOffset;
state.rotation16 = blockEntity.getBlockState().getValue(BlockStateProperties.ROTATION_16);

state.lines = blockEntity.lines.stream().map(Component::getVisualOrderText).toList();
state.scale = blockEntity.scale;
}

@Override
public boolean shouldBake(TextBlockEntity entity) {
// return !entity.lines.isEmpty();
return false;
}

@Override
public void submitForRendering(TextRenderState state, PoseStack poseStack, SubmitNodeCollector submitNodeCollector, CameraRenderState camera) {
if (state.shouldRenderPlaceholder) {
BlockEntityRenderUtil.renderPlaceholderWithBlockRotation(state, state.rotation16, ITEM_TEXTURE, 1.0F, poseStack, submitNodeCollector, state.zOffset == TextBlockEntity.ZOffset.CENTER ? 0.01F : state.zOffset == TextBlockEntity.ZOffset.FRONT ? 0.4F : -0.4F);
}
}

@Override
public void submitForBaking(TextRenderState state, PoseStack poseStack, SubmitNodeCollector submitNodeCollector) {
// TODO: Port to 26.1
// TODO: move this to a baked rendering method
// currently it errors "Rendersystem called from wrong thread" on `this.font.width(text)`
int maxWidth = 0;
for (var line : state.lines) {
maxWidth = Math.max(maxWidth, this.font.width(line));
}

poseStack.pushPose();
poseStack.mulPose(Axis.YP.rotationDegrees(-(state.rotation16 * 360) / 16.0F));
float a = 1 / 9f;
poseStack.translate(-.5, 1.5, -.5);
poseStack.scale(a, -a, a);
submitNodeCollector.submitText(poseStack, 0, 0, Component.literal("waff :3").getVisualOrderText(), true, Font.DisplayMode.NORMAL, LightCoordsUtil.FULL_BRIGHT, 0xFFFFFFFF, 0, 0);
poseStack.translate(0.5D, 0.5D, 0.5D);
// 2D rendering of the font has Y axis going down, not up
poseStack.scale(1, -1, 1);

switch (state.zOffset) {
case FRONT -> poseStack.translate(0D, 0D, 0.4D);
case BACK -> poseStack.translate(0D, 0D, -0.4D);
}

float rotation = -(state.rotation16 * 360) / 16.0F;
poseStack.mulPose(Axis.YP.rotationDegrees(rotation));

poseStack.scale(0.1F * state.scale, 0.1F * state.scale, 0.1F * state.scale);
poseStack.translate(0, -(state.lines.size() * this.font.lineHeight) / 2D, 0D);

for (int i = 0; i < state.lines.size(); ++i) {
var line = state.lines.get(i);

int width = this.font.width(line);
if (width == 0) {
continue;
}

float x = switch (state.textAlignment) {
case LEFT -> -maxWidth / 2F;
case CENTER -> (maxWidth - width) / 2F - maxWidth / 2F;
case CENTER_LEFT -> -(50F / state.scale) - (width / 2F);
case CENTER_RIGHT -> (50F / state.scale) - (width / 2F);
case RIGHT -> maxWidth - width - maxWidth / 2F;
};

submitNodeCollector.submitText(poseStack,
x,
i * this.font.lineHeight,
line, state.shadow,
Font.DisplayMode.NORMAL,
LightCoordsUtil.FULL_BRIGHT,
state.color,
state.backgroundColor,
0);
}

poseStack.popPose();
}

@Override
public boolean shouldBake(TextBlockEntity entity) {
return !entity.lines.isEmpty();
public void submitForBaking(TextRenderState state, PoseStack poseStack, SubmitNodeCollector submitNodeCollector) {
// TODO: Port to 26.1
// poseStack.pushPose();
// poseStack.mulPose(Axis.YP.rotationDegrees(-(state.rotation16 * 360) / 16.0F));
// float a = 1 / 9f;
// poseStack.translate(-.5, 1.5, -.5);
// poseStack.scale(a, -a, a);
// submitNodeCollector.submitText(poseStack, 0, 0, Component.literal("waff :3").getVisualOrderText(), true, Font.DisplayMode.NORMAL, LightCoordsUtil.FULL_BRIGHT, 0xFFFFFFFF, 0, 0);
// poseStack.popPose();
}

// FIXME 26.1
Expand Down
Loading