2 * Sixth 3D engine. Author: Svjatoslav Agejenko.
3 * This project is released under Creative Commons Zero (CC0) license.
5 package eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.textcanvas;
7 import eu.svjatoslav.sixth.e3d.geometry.Point3D;
8 import eu.svjatoslav.sixth.e3d.gui.RenderingContext;
9 import eu.svjatoslav.sixth.e3d.gui.TextPointer;
10 import eu.svjatoslav.sixth.e3d.math.Transform;
11 import eu.svjatoslav.sixth.e3d.math.TransformsStack;
12 import eu.svjatoslav.sixth.e3d.renderer.raster.Color;
13 import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.TexturedRectangle;
16 import java.io.BufferedReader;
17 import java.io.IOException;
18 import java.io.StringReader;
20 import static eu.svjatoslav.sixth.e3d.renderer.raster.Color.BLACK;
21 import static eu.svjatoslav.sixth.e3d.renderer.raster.Color.WHITE;
23 public class TextCanvas extends TexturedRectangle {
26 * Font character width in world coordinates.
28 public static final int FONT_CHAR_WIDTH = 8;
31 * Font character height in world coordinates.
33 public static final int FONT_CHAR_HEIGHT = 16;
36 * Font character width in texture pixels.
38 public static final int FONT_CHAR_WIDTH_TEXTURE_PIXELS = 16;
41 * Font character height in texture pixels.
43 public static final int FONT_CHAR_HEIGHT_TEXTURE_PIXELS = 32;
46 public static final Font FONT = CanvasCharacter.getFont((int) (FONT_CHAR_HEIGHT_TEXTURE_PIXELS / 1.066));
47 private static final String GROUP_TEXTURE = "texture";
48 private static final String GROUP_CHARACTERS = "characters";
49 private final TextPointer size;
50 private final TextPointer cursorLocation = new TextPointer();
51 CanvasCharacter[][] lines;
52 private RenderMode renderMode = null;
53 private Color backgroundColor = BLACK;
54 private Color foregroundColor = WHITE;
56 public TextCanvas(final Transform location, final String text,
57 final Color foregroundColor, final Color backgroundColor) {
58 this(location, getTextDimensions(text), foregroundColor,
63 public TextCanvas(final Transform location, final TextPointer dimensions,
64 final Color foregroundColor, final Color backgroundColor) {
66 getRelativityTracker().enableOrientationTracking();
69 final int columns = dimensions.column;
70 final int rows = dimensions.row;
72 this.backgroundColor = backgroundColor;
73 this.foregroundColor = foregroundColor;
75 // initialize underlying textured rectangle
77 columns * FONT_CHAR_WIDTH,
78 rows * FONT_CHAR_HEIGHT,
79 columns * FONT_CHAR_WIDTH_TEXTURE_PIXELS,
80 rows * FONT_CHAR_HEIGHT_TEXTURE_PIXELS,
83 getTexture().primaryBitmap.fillColor(backgroundColor);
84 getTexture().resetResampledBitmapCache();
86 setGroupForUngrouped(GROUP_TEXTURE);
88 lines = new CanvasCharacter[rows][];
89 for (int row = 0; row < rows; row++) {
90 lines[row] = new CanvasCharacter[columns];
92 for (int column = 0; column < columns; column++) {
93 final Point3D characterCoordinate = getCharLocation(row, column);
95 final CanvasCharacter character = new CanvasCharacter(
96 characterCoordinate, ' ', foregroundColor,
99 lines[row][column] = character;
104 setGroupForUngrouped(GROUP_CHARACTERS);
106 setRenderMode(RenderMode.TEXTURE);
109 public static TextPointer getTextDimensions(final String text) {
111 final BufferedReader reader = new BufferedReader(new StringReader(text));
119 line = reader.readLine();
120 } catch (IOException e) {
121 throw new RuntimeException(e);
125 return new TextPointer(rows, columns);
128 columns = Math.max(columns, line.length());
133 public void beforeTransformHook(final TransformsStack transformPipe,
134 final RenderingContext context) {
136 final double textRelativeSize = context.width
137 / getRelativityTracker().getDistanceToUser();
139 if (textRelativeSize < 2d) {
140 if (renderMode == RenderMode.CHARACTERS)
141 setRenderMode(RenderMode.TEXTURE);
145 final double piHalf = Math.PI / 2;
147 final double deviation = Math.abs(getRelativityTracker().getAngleXZ()
149 + Math.abs(getRelativityTracker().getAngleYZ() + piHalf);
151 final double maxDeviation = 0.5;
153 if (deviation > maxDeviation) {
154 if (renderMode == RenderMode.CHARACTERS)
155 setRenderMode(RenderMode.TEXTURE);
156 } else if (renderMode == RenderMode.TEXTURE)
157 setRenderMode(RenderMode.CHARACTERS);
160 public void clear() {
161 for (final CanvasCharacter[] line : lines)
162 for (final CanvasCharacter character : line) {
163 character.setValue(' ');
164 character.setBackgroundColor(backgroundColor);
165 character.setForegroundColor(foregroundColor);
168 // set background color
169 getTexture().primaryBitmap.fillColor(backgroundColor);
170 getTexture().resetResampledBitmapCache();
173 private void drawCharToTexture(final int row, final int column,
174 final char character, final Color foreground) {
175 final Graphics2D graphics = getTexture().graphics;
177 getTexture().primaryBitmap.drawRectangle(
178 column * FONT_CHAR_WIDTH_TEXTURE_PIXELS,
179 row * FONT_CHAR_HEIGHT_TEXTURE_PIXELS,
180 (column * FONT_CHAR_WIDTH_TEXTURE_PIXELS) + FONT_CHAR_WIDTH_TEXTURE_PIXELS,
181 (row * FONT_CHAR_HEIGHT_TEXTURE_PIXELS) + FONT_CHAR_HEIGHT_TEXTURE_PIXELS,
184 graphics.setFont(FONT);
185 graphics.setColor(foreground.toAwtColor());
187 new char[]{character,}, 0, 1,
188 (column * FONT_CHAR_WIDTH_TEXTURE_PIXELS),
189 (row * FONT_CHAR_HEIGHT_TEXTURE_PIXELS) + (int) (FONT_CHAR_HEIGHT_TEXTURE_PIXELS / 1.23f));
191 getTexture().resetResampledBitmapCache();
194 public Point3D getCharLocation(final int row, final int column) {
195 final Point3D coordinate = topLeft.clone();
197 coordinate.translateY((row * FONT_CHAR_HEIGHT)
198 + (FONT_CHAR_HEIGHT / 3.2));
200 coordinate.translateX((column * FONT_CHAR_WIDTH)
201 + (FONT_CHAR_WIDTH / 2));
206 public TextPointer getSize() {
210 public void locate(final int row, final int column) {
211 cursorLocation.row = row;
212 cursorLocation.column = column;
215 public void print(final String text) {
216 for (final char c : text.toCharArray())
220 public void putChar(final char character) {
221 putChar(cursorLocation, character);
223 cursorLocation.column++;
224 if (cursorLocation.column >= size.column) {
225 cursorLocation.column = 0;
226 cursorLocation.row++;
230 public void putChar(final int row, final int column, final char character) {
231 if ((row >= lines.length) || (row < 0))
234 final CanvasCharacter[] line = lines[row];
236 if ((column >= line.length) || (column < 0))
239 final CanvasCharacter canvasCharacter = line[column];
240 canvasCharacter.setValue(character);
241 canvasCharacter.setBackgroundColor(backgroundColor);
242 canvasCharacter.setForegroundColor(foregroundColor);
243 drawCharToTexture(row, column, character,
247 public void putChar(final TextPointer location, final char character) {
248 putChar(location.row, location.column, character);
251 public void setBackgroundColor(
252 final eu.svjatoslav.sixth.e3d.renderer.raster.Color backgroundColor) {
253 this.backgroundColor = backgroundColor;
256 public void setForegroundColor(
257 final eu.svjatoslav.sixth.e3d.renderer.raster.Color foregroundColor) {
258 this.foregroundColor = foregroundColor;
261 private void setRenderMode(final RenderMode mode) {
262 if (mode == renderMode)
267 hideGroup(GROUP_TEXTURE);
268 showGroup(GROUP_CHARACTERS);
271 hideGroup(GROUP_CHARACTERS);
272 showGroup(GROUP_TEXTURE);
279 public void setText(final String text) {
280 final BufferedReader reader = new BufferedReader(new StringReader(text));
287 line = reader.readLine();
288 } catch (IOException e) {
289 throw new RuntimeException(e);
296 for (final char c : line.toCharArray()) {
297 putChar(row, column, c);
304 public void setTextColor(final Color color) {
305 for (final CanvasCharacter[] line : lines)
306 for (final CanvasCharacter character : line)
307 character.setForegroundColor(color);