package gameEngine.views; import org.joml.Vector3f; import java.util.Map; import static java.awt.Font.PLAIN; import static java.awt.Font.SANS_SERIF; import static org.lwjgl.opengl.GL11.*; public class Text extends Renderer implements IUpdatable { private Texture fontTexture; private Map<Character, Glyph> fontGlyphs; private int fontHeight; public String text; public int textSize; public Text(float posX, float posY, String text, int textSize) { this.position = new Vector3f(posX,posY,0); this.rotation = new Vector3f(0,0,0); this.scale = new Vector3f(1,1,1); this.text = text; this.textSize = textSize; this.color = new Color(0,0,0,1); Font font = new Font(new java.awt.Font(SANS_SERIF, PLAIN, textSize), true); fontTexture = font.getTexture(); fontGlyphs = font.getGlyphs(); fontHeight = font.getFontHeight(); } public void update(){ Integer id = fontTexture.getId(); if(id == null) { fontTexture.init(); } render(); } public void setText(String newText) { this.text = newText; render(); } public void setTextSize(int newTextSize) { if (newTextSize < 3 || newTextSize > 127) return; this.textSize = newTextSize; Font font = new Font(new java.awt.Font(SANS_SERIF, PLAIN, textSize), true); this.fontTexture = font.getTexture(); this.fontGlyphs = font.getGlyphs(); this.fontHeight = font.getFontHeight(); render(); } public void setColor(Color color) { this.color = color; render(); } public boolean isMouseOver(float mouseX, float mouseY) { float width = getDisplayedWidth(); float height = getDisplayedHeight(); return mouseX >= position.x && mouseX <= position.x + width && mouseY >= position.y && mouseY <= position.y + height; } @Override public void render() { prepareRendering(); glBindTexture(GL_TEXTURE_2D, fontTexture.getId()); float drawX = 0; // Render relative to the transformed position float drawY = 0; for (int i = 0; i < text.length(); i++) { char ch = text.charAt(i); if (ch == '\n') { drawY += fontHeight; drawX = 0; continue; } Glyph g = fontGlyphs.get(ch); if (g != null) { glBegin(GL_QUADS); glTexCoord2f(g.x / (float) fontTexture.getWidth(), g.y / (float) fontTexture.getHeight()); glVertex3f(drawX, drawY, 0); glTexCoord2f((g.x + g.width) / (float) fontTexture.getWidth(), g.y / (float) fontTexture.getHeight()); glVertex3f(drawX + g.width, drawY, 0); glTexCoord2f((g.x + g.width) / (float) fontTexture.getWidth(), (g.y + g.height) / (float) fontTexture.getHeight()); glVertex3f(drawX + g.width, drawY + g.height, 0); glTexCoord2f(g.x / (float) fontTexture.getWidth(), (g.y + g.height) / (float) fontTexture.getHeight()); glVertex3f(drawX, drawY + g.height, 0); glEnd(); drawX += g.width; // Advance x position by character width } } endRendering(); } public int getHeight(CharSequence text) { int height = 0; int lineHeight = 0; for (int i = 0; i < text.length(); i++) { char c = text.charAt(i); if (c == '\n') { height += lineHeight; lineHeight = 0; continue; } if (c == '\r') { continue; } Glyph g = fontGlyphs.get(c); lineHeight = Math.max(lineHeight, g.height); } height += lineHeight; return height; } public float getDisplayedWidth() { float width = 0; float lineWidth = 0; for (int i = 0; i < text.length(); i++) { char ch = text.charAt(i); if (ch == '\n') { width = Math.max(width, lineWidth); lineWidth = 0; // 新しい行に移行するためにリセット } else { Glyph g = fontGlyphs.get(ch); if (g != null) { lineWidth += g.width; // 文字の幅を加算 } } } width = Math.max(width, lineWidth); // 最後の行の幅も確認 return width * scale.x; } public float getWidthAtIndex(int index) { float width = 0; float drawX = 0; for (int i = 0; i < index; i++) { char ch = text.charAt(i); if (ch == '\n') { drawX = 0; continue; } Glyph g = fontGlyphs.get(ch); if (g != null) { drawX += g.width; // 文字の幅を加算 } } return drawX * scale.x; } public float getDisplayedHeight() { int numLines = 1; // 初期行は1行 for (int i = 0; i < text.length(); i++) { if (text.charAt(i) == '\n') { numLines++; } } return numLines * fontHeight * scale.y; } }