fd78bf99892d7a187357ec78e95796a349fe4d2e
[sixth-3d.git] / src / main / java / eu / svjatoslav / sixth / e3d / renderer / raster / shapes / composite / textcanvas / TextCanvas.java
1 /*
2  * Sixth 3D engine. Author: Svjatoslav Agejenko. 
3  * This project is released under Creative Commons Zero (CC0) license.
4  */
5 package eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.textcanvas;
6
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.TransformsPipeline;
12 import eu.svjatoslav.sixth.e3d.renderer.raster.Color;
13 import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.TexturedRectangle;
14
15 import java.awt.*;
16 import java.io.BufferedReader;
17 import java.io.IOException;
18 import java.io.StringReader;
19
20 import static eu.svjatoslav.sixth.e3d.renderer.raster.Color.BLACK;
21 import static eu.svjatoslav.sixth.e3d.renderer.raster.Color.WHITE;
22
23 public class TextCanvas extends TexturedRectangle {
24
25     // character size in world coordiates
26     public static final int FONT_CHAR_WIDTH = 8;
27     public static final int FONT_CHAR_HEIGHT = 16;
28
29     // character size on texture
30     public static final int FONT_CHAR_WIDTH_TEXTURE_PIXELS = 16;
31     public static final int FONT_CHAR_HEIGHT_TEXTURE_PIXELS = 32;
32
33
34     public static final Font FONT = CanvasCharacter.getFont((int)(FONT_CHAR_HEIGHT_TEXTURE_PIXELS / 1.066));
35     private static final String GROUP_TEXTURE = "texture";
36     private static final String GROUP_CHARACTERS = "characters";
37     private final TextPointer size;
38     private final TextPointer cursorLocation = new TextPointer();
39     CanvasCharacter lines[][];
40     private RenderMode renderMode = null;
41     private Color backgroundColor = BLACK;
42     private Color foregroundColor = WHITE;
43
44     public TextCanvas(final Transform location, final String text,
45                       final Color foregroundColor, final Color backgroundColor) {
46         this(location, getTextDimensions(text), foregroundColor,
47                 backgroundColor);
48         setText(text);
49     }
50
51     public TextCanvas(final Transform location, final TextPointer dimensions,
52                       final Color foregroundColor, final Color backgroundColor) {
53         super(location);
54         getRelativityTracker().enableOrientationTracking();
55
56         size = dimensions;
57         final int columns = dimensions.column;
58         final int rows = dimensions.row;
59
60         this.backgroundColor = backgroundColor;
61         this.foregroundColor = foregroundColor;
62
63         // initialize underlying textured rectangle
64         initialize(
65                 columns * FONT_CHAR_WIDTH,
66                 rows * FONT_CHAR_HEIGHT,
67                 columns * FONT_CHAR_WIDTH_TEXTURE_PIXELS,
68                 rows * FONT_CHAR_HEIGHT_TEXTURE_PIXELS,
69                 0);
70
71         getTexture().primaryBitmap.fillColor(backgroundColor);
72         getTexture().resetResampledBitmapCache();
73
74         setGroupForUngrouped(GROUP_TEXTURE);
75
76         lines = new CanvasCharacter[rows][];
77         for (int row = 0; row < rows; row++) {
78             lines[row] = new CanvasCharacter[columns];
79
80             for (int column = 0; column < columns; column++) {
81                 final Point3D characterCoordinate = getCharLocation(row, column);
82
83                 final CanvasCharacter character = new CanvasCharacter(
84                         characterCoordinate, ' ', foregroundColor,
85                         backgroundColor);
86                 addShape(character);
87                 lines[row][column] = character;
88             }
89
90         }
91
92         setGroupForUngrouped(GROUP_CHARACTERS);
93
94         setRenderMode(RenderMode.TEXTURE);
95     }
96
97     public static TextPointer getTextDimensions(final String text) {
98
99         final BufferedReader reader = new BufferedReader(new StringReader(text));
100
101         int rows = 0;
102         int columns = 0;
103
104         while (true) {
105             final String line;
106             try {
107                 line = reader.readLine();
108             } catch (IOException e) {
109                 throw new RuntimeException(e);
110             }
111
112             if (line == null)
113                 return new TextPointer(rows, columns);
114
115             rows++;
116             columns = Math.max(columns, line.length());
117         }
118     }
119
120     @Override
121     public void beforeTransformHook(final TransformsPipeline transformPipe,
122                                     final RenderingContext context) {
123
124         final double textRelativeSize = context.width
125                 / getRelativityTracker().getDistanceToUser();
126
127         if (textRelativeSize < 2d) {
128             if (renderMode == RenderMode.CHARACTERS)
129                 setRenderMode(RenderMode.TEXTURE);
130             return;
131         }
132
133         final double piHalf = Math.PI / 2;
134
135         final double deviation = Math.abs(getRelativityTracker().getAngleXZ()
136                 + piHalf)
137                 + Math.abs(getRelativityTracker().getAngleYZ() + piHalf);
138
139         final double maxDeviation = 0.5;
140
141         if (deviation > maxDeviation) {
142             if (renderMode == RenderMode.CHARACTERS)
143                 setRenderMode(RenderMode.TEXTURE);
144         } else if (renderMode == RenderMode.TEXTURE)
145             setRenderMode(RenderMode.CHARACTERS);
146     }
147
148     public void cls() {
149         for (final CanvasCharacter[] line : lines)
150             for (final CanvasCharacter character : line) {
151                 character.setValue(' ');
152                 character.setBackgroundColor(backgroundColor);
153                 character.setForegroundColor(foregroundColor);
154             }
155
156         // set background color
157         getTexture().primaryBitmap.fillColor(backgroundColor);
158         getTexture().resetResampledBitmapCache();
159     }
160
161     private void drawCharToTexture(final int row, final int column,
162                                    final char character, final Color foreground) {
163         final Graphics2D graphics = getTexture().graphics;
164
165         getTexture().primaryBitmap.drawRectangle(
166                 column * FONT_CHAR_WIDTH_TEXTURE_PIXELS,
167                 row * FONT_CHAR_HEIGHT_TEXTURE_PIXELS,
168                 (column * FONT_CHAR_WIDTH_TEXTURE_PIXELS) + FONT_CHAR_WIDTH_TEXTURE_PIXELS,
169                 (row * FONT_CHAR_HEIGHT_TEXTURE_PIXELS) + FONT_CHAR_HEIGHT_TEXTURE_PIXELS,
170                 backgroundColor);
171
172         graphics.setFont(FONT);
173         graphics.setColor(foreground.toAwtColor());
174         graphics.drawChars(
175                 new char[]{character,}, 0, 1,
176                 (column * FONT_CHAR_WIDTH_TEXTURE_PIXELS) - 0,
177                 (row * FONT_CHAR_HEIGHT_TEXTURE_PIXELS) + (int)(FONT_CHAR_HEIGHT_TEXTURE_PIXELS / 1.23f));
178
179         getTexture().resetResampledBitmapCache();
180     }
181
182     public Point3D getCharLocation(final int row, final int column) {
183         final Point3D coordinate = topLeft.clone();
184
185         coordinate.translateY((row * FONT_CHAR_HEIGHT)
186                 + (FONT_CHAR_HEIGHT / 3.2));
187
188         coordinate.translateX((column * FONT_CHAR_WIDTH)
189                 + (FONT_CHAR_WIDTH / 2));
190
191         return coordinate;
192     }
193
194     public TextPointer getSize() {
195         return size;
196     }
197
198     public void locate(final int row, final int column) {
199         cursorLocation.row = row;
200         cursorLocation.column = column;
201     }
202
203     public void print(final String text) {
204         for (final char c : text.toCharArray())
205             putChar(c);
206     }
207
208     public void putChar(final char character) {
209         putChar(cursorLocation, character);
210
211         cursorLocation.column++;
212         if (cursorLocation.column >= size.column) {
213             cursorLocation.column = 0;
214             cursorLocation.row++;
215         }
216     }
217
218     public void putChar(final int row, final int column, final char character) {
219         if ((row >= lines.length) || (row < 0))
220             return;
221
222         final CanvasCharacter[] line = lines[row];
223
224         if ((column >= line.length) || (column < 0))
225             return;
226
227         final CanvasCharacter canvasCharacter = line[column];
228         canvasCharacter.setValue(character);
229         canvasCharacter.setBackgroundColor(backgroundColor);
230         canvasCharacter.setForegroundColor(foregroundColor);
231         drawCharToTexture(row, column, character,
232                 foregroundColor);
233     }
234
235     public void putChar(final TextPointer location, final char character) {
236         putChar(location.row, location.column, character);
237     }
238
239     public void setBackgroundColor(
240             final eu.svjatoslav.sixth.e3d.renderer.raster.Color backgroundColor) {
241         this.backgroundColor = backgroundColor;
242     }
243
244     public void setForegroundColor(
245             final eu.svjatoslav.sixth.e3d.renderer.raster.Color foregroundColor) {
246         this.foregroundColor = foregroundColor;
247     }
248
249     private void setRenderMode(final RenderMode mode) {
250         if (mode == renderMode)
251             return;
252
253         switch (mode) {
254             case CHARACTERS:
255                 hideGroup(GROUP_TEXTURE);
256                 showGroup(GROUP_CHARACTERS);
257                 break;
258             case TEXTURE:
259                 hideGroup(GROUP_CHARACTERS);
260                 showGroup(GROUP_TEXTURE);
261                 break;
262         }
263
264         renderMode = mode;
265     }
266
267     public void setText(final String text) {
268         final BufferedReader reader = new BufferedReader(new StringReader(text));
269
270         int row = 0;
271
272         while (true) {
273             final String line;
274             try {
275                 line = reader.readLine();
276             } catch (IOException e) {
277                 throw new RuntimeException(e);
278             }
279
280             if (line == null)
281                 return;
282
283             int column = 0;
284             for (final char c : line.toCharArray()) {
285                 putChar(row, column, c);
286                 column++;
287             }
288             row++;
289         }
290     }
291
292     public void setTextColor(final Color color) {
293         for (final CanvasCharacter[] line : lines)
294             for (final CanvasCharacter character : line)
295                 character.setForegroundColor(color);
296     }
297
298     // @Override
299     // public void transform(final TransformPipe transformPipe,
300     // final RenderAggregator aggregator, final RenderingContext buffer) {
301     //
302     // super.transform(transformPipe, aggregator, buffer);
303     //
304     // }
305 }