168 lines
7.2 KiB
Java
168 lines
7.2 KiB
Java
// Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
|
|
//
|
|
// SPDX-License-Identifier: LicenseRef-CCPL
|
|
|
|
package dan200.computercraft.client.render;
|
|
|
|
import com.mojang.blaze3d.vertex.PoseStack;
|
|
import com.mojang.blaze3d.vertex.VertexConsumer;
|
|
import dan200.computercraft.client.render.text.FixedWidthFontRenderer;
|
|
import dan200.computercraft.core.terminal.Palette;
|
|
import dan200.computercraft.core.terminal.TextBuffer;
|
|
import dan200.computercraft.shared.media.items.PrintoutData;
|
|
import net.minecraft.client.renderer.MultiBufferSource;
|
|
import org.joml.Matrix4f;
|
|
|
|
import java.util.List;
|
|
|
|
import static dan200.computercraft.client.render.text.FixedWidthFontRenderer.FONT_HEIGHT;
|
|
import static dan200.computercraft.shared.media.items.PrintoutData.LINES_PER_PAGE;
|
|
|
|
/**
|
|
* Renders printed pages or books, either for a GUI ({@link dan200.computercraft.client.gui.PrintoutScreen}) or
|
|
* {@linkplain PrintoutItemRenderer in-hand/item frame printouts}.
|
|
*/
|
|
public final class PrintoutRenderer {
|
|
private static final float BG_SIZE = 256.0f;
|
|
|
|
/**
|
|
* Width of a page.
|
|
*/
|
|
public static final int X_SIZE = 172;
|
|
|
|
/**
|
|
* Height of a page.
|
|
*/
|
|
public static final int Y_SIZE = 209;
|
|
|
|
/**
|
|
* Padding between the left and right of a page and the text.
|
|
*/
|
|
public static final int X_TEXT_MARGIN = 13;
|
|
|
|
/**
|
|
* Padding between the top and bottom of a page and the text.
|
|
*/
|
|
public static final int Y_TEXT_MARGIN = 11;
|
|
|
|
/**
|
|
* Width of the extra page texture.
|
|
*/
|
|
private static final int X_FOLD_SIZE = 12;
|
|
|
|
/**
|
|
* Size of the leather cover.
|
|
*/
|
|
public static final int COVER_SIZE = 12;
|
|
|
|
private static final int COVER_Y = Y_SIZE;
|
|
private static final int COVER_X = X_SIZE + 4 * X_FOLD_SIZE;
|
|
|
|
private PrintoutRenderer() {
|
|
}
|
|
|
|
public static void drawText(PoseStack transform, MultiBufferSource bufferSource, int x, int y, int start, int light, TextBuffer[] text, TextBuffer[] colours) {
|
|
var buffer = bufferSource.getBuffer(RenderTypes.PRINTOUT_TEXT);
|
|
var emitter = FixedWidthFontRenderer.toVertexConsumer(transform, buffer);
|
|
for (var line = 0; line < LINES_PER_PAGE && line < text.length; line++) {
|
|
FixedWidthFontRenderer.drawString(emitter,
|
|
x, y + line * FONT_HEIGHT, text[start + line], colours[start + line],
|
|
Palette.DEFAULT, light
|
|
);
|
|
}
|
|
}
|
|
|
|
public static void drawText(PoseStack transform, MultiBufferSource bufferSource, int x, int y, int start, int light, List<PrintoutData.Line> lines) {
|
|
var buffer = bufferSource.getBuffer(RenderTypes.PRINTOUT_TEXT);
|
|
var emitter = FixedWidthFontRenderer.toVertexConsumer(transform, buffer);
|
|
for (var line = 0; line < LINES_PER_PAGE && line < lines.size(); line++) {
|
|
var lineContents = lines.get(start + line);
|
|
FixedWidthFontRenderer.drawString(emitter,
|
|
x, y + line * FONT_HEIGHT,
|
|
new TextBuffer(lineContents.text()), new TextBuffer(lineContents.foreground()),
|
|
Palette.DEFAULT, light
|
|
);
|
|
}
|
|
}
|
|
|
|
public static void drawBorder(PoseStack transform, MultiBufferSource bufferSource, float x, float y, float z, int page, int pages, boolean isBook, int light) {
|
|
var matrix = transform.last().pose();
|
|
var leftPages = page;
|
|
var rightPages = pages - page - 1;
|
|
|
|
var buffer = bufferSource.getBuffer(RenderTypes.PRINTOUT_BACKGROUND);
|
|
|
|
if (isBook) {
|
|
// Border
|
|
var offset = offsetAt(pages);
|
|
var left = x - 4 - offset;
|
|
var right = x + X_SIZE + offset - 4;
|
|
|
|
// Left and right border
|
|
drawTexture(matrix, buffer, left - 4, y - 8, z - 0.02f, COVER_X, 0, COVER_SIZE, Y_SIZE + COVER_SIZE * 2, light);
|
|
drawTexture(matrix, buffer, right, y - 8, z - 0.02f, COVER_X + COVER_SIZE, 0, COVER_SIZE, Y_SIZE + COVER_SIZE * 2, light);
|
|
|
|
// Draw centre panel (just stretched texture, sorry).
|
|
drawTexture(matrix, buffer,
|
|
x - offset, y, z - 0.02f, X_SIZE + offset * 2, Y_SIZE,
|
|
COVER_X + COVER_SIZE / 2.0f, COVER_SIZE, COVER_SIZE, Y_SIZE,
|
|
light
|
|
);
|
|
|
|
var borderX = left;
|
|
while (borderX < right) {
|
|
double thisWidth = Math.min(right - borderX, X_SIZE);
|
|
drawTexture(matrix, buffer, borderX, y - 8, z - 0.02f, 0, COVER_Y, (float) thisWidth, COVER_SIZE, light);
|
|
drawTexture(matrix, buffer, borderX, y + Y_SIZE - 4, z - 0.02f, 0, COVER_Y + COVER_SIZE, (float) thisWidth, COVER_SIZE, light);
|
|
borderX = (float) (borderX + thisWidth);
|
|
}
|
|
}
|
|
|
|
// Current page background: Z-offset is interleaved between the "zeroth" left/right page and the first
|
|
// left/right page, so that the "bold" border can be drawn over the edge where appropriate.
|
|
drawTexture(matrix, buffer, x, y, z - 1e-3f * 0.5f, X_FOLD_SIZE * 2, 0, X_SIZE, Y_SIZE, light);
|
|
|
|
// Left pages
|
|
for (var n = 0; n <= leftPages; n++) {
|
|
drawTexture(matrix, buffer,
|
|
x - offsetAt(n), y, z - 1e-3f * n,
|
|
// Use the left "bold" fold for the outermost page
|
|
n == leftPages ? 0 : X_FOLD_SIZE, 0,
|
|
X_FOLD_SIZE, Y_SIZE, light
|
|
);
|
|
}
|
|
|
|
// Right pages
|
|
for (var n = 0; n <= rightPages; n++) {
|
|
drawTexture(matrix, buffer,
|
|
x + (X_SIZE - X_FOLD_SIZE) + offsetAt(n), y, z - 1e-3f * n,
|
|
// Two folds, then the main page. Use the right "bold" fold for the outermost page.
|
|
X_FOLD_SIZE * 2 + X_SIZE + (n == rightPages ? X_FOLD_SIZE : 0), 0,
|
|
X_FOLD_SIZE, Y_SIZE, light
|
|
);
|
|
}
|
|
}
|
|
|
|
private static void drawTexture(Matrix4f matrix, VertexConsumer buffer, float x, float y, float z, float u, float v, float width, float height, int light) {
|
|
vertex(buffer, matrix, x, y + height, z, u / BG_SIZE, (v + height) / BG_SIZE, light);
|
|
vertex(buffer, matrix, x + width, y + height, z, (u + width) / BG_SIZE, (v + height) / BG_SIZE, light);
|
|
vertex(buffer, matrix, x + width, y, z, (u + width) / BG_SIZE, v / BG_SIZE, light);
|
|
vertex(buffer, matrix, x, y, z, u / BG_SIZE, v / BG_SIZE, light);
|
|
}
|
|
|
|
private static void drawTexture(Matrix4f matrix, VertexConsumer buffer, float x, float y, float z, float width, float height, float u, float v, float tWidth, float tHeight, int light) {
|
|
vertex(buffer, matrix, x, y + height, z, u / BG_SIZE, (v + tHeight) / BG_SIZE, light);
|
|
vertex(buffer, matrix, x + width, y + height, z, (u + tWidth) / BG_SIZE, (v + tHeight) / BG_SIZE, light);
|
|
vertex(buffer, matrix, x + width, y, z, (u + tWidth) / BG_SIZE, v / BG_SIZE, light);
|
|
vertex(buffer, matrix, x, y, z, u / BG_SIZE, v / BG_SIZE, light);
|
|
}
|
|
|
|
private static void vertex(VertexConsumer buffer, Matrix4f matrix, float x, float y, float z, float u, float v, int light) {
|
|
buffer.vertex(matrix, x, y, z).color(255, 255, 255, 255).uv(u, v).uv2(light).endVertex();
|
|
}
|
|
|
|
public static float offsetAt(int page) {
|
|
return (float) (32 * (1 - Math.pow(1.2, -page)));
|
|
}
|
|
}
|