2018-09-22 10:29:40 +02:00
|
|
|
package it.cavallium.warppi.gui.graphicengine.impl.common;
|
2017-01-31 22:29:49 +01:00
|
|
|
|
|
|
|
import java.awt.image.BufferedImage;
|
|
|
|
import java.awt.image.DataBufferInt;
|
|
|
|
import java.io.File;
|
|
|
|
import java.io.IOException;
|
2018-06-11 22:41:11 +02:00
|
|
|
import java.io.InputStream;
|
|
|
|
import java.net.URISyntaxException;
|
2017-11-19 22:58:37 +01:00
|
|
|
import java.util.LinkedList;
|
2017-01-31 22:29:49 +01:00
|
|
|
import java.util.logging.Level;
|
|
|
|
import java.util.logging.Logger;
|
|
|
|
|
|
|
|
import javax.imageio.ImageIO;
|
|
|
|
|
2018-09-04 12:12:41 +02:00
|
|
|
import it.cavallium.warppi.Engine;
|
2018-09-12 22:16:33 +02:00
|
|
|
import it.cavallium.warppi.Platform.ConsoleUtils;
|
2018-09-02 13:36:49 +02:00
|
|
|
import it.cavallium.warppi.gui.graphicengine.BinaryFont;
|
|
|
|
import it.cavallium.warppi.gui.graphicengine.GraphicEngine;
|
2018-09-12 22:16:33 +02:00
|
|
|
import it.cavallium.warppi.util.Utils;
|
2017-01-31 22:29:49 +01:00
|
|
|
|
2018-09-04 12:12:41 +02:00
|
|
|
public abstract class RFTFont implements BinaryFont {
|
2017-01-31 22:29:49 +01:00
|
|
|
|
|
|
|
public boolean[][] rawchars;
|
|
|
|
public int[] chars32;
|
|
|
|
public int minBound = 10;
|
|
|
|
public int maxBound = 0;
|
|
|
|
public int charW;
|
|
|
|
public int charH;
|
|
|
|
public int charS;
|
|
|
|
public int charIntCount;
|
2018-03-29 19:20:28 +02:00
|
|
|
public int[] intervals;
|
2017-11-19 22:58:37 +01:00
|
|
|
public int intervalsTotalSize = 0;
|
2017-01-31 22:29:49 +01:00
|
|
|
public static final int intBits = 31;
|
2018-09-02 12:45:51 +02:00
|
|
|
@SuppressWarnings("unused")
|
2017-11-19 22:58:37 +01:00
|
|
|
private final boolean isResource;
|
2017-01-31 22:29:49 +01:00
|
|
|
|
2018-09-22 11:17:30 +02:00
|
|
|
public RFTFont(final String fontName) throws IOException {
|
2017-12-09 23:00:04 +01:00
|
|
|
this(fontName, false);
|
|
|
|
}
|
|
|
|
|
2018-09-22 11:17:30 +02:00
|
|
|
RFTFont(final String fontName, final boolean onlyRaw) throws IOException {
|
2017-11-19 22:58:37 +01:00
|
|
|
isResource = true;
|
2017-12-09 23:00:04 +01:00
|
|
|
load("/font_" + fontName + ".rft", onlyRaw);
|
2017-11-19 22:58:37 +01:00
|
|
|
}
|
2018-05-12 21:18:29 +02:00
|
|
|
|
2018-09-22 11:17:30 +02:00
|
|
|
public RFTFont(final String path, final String fontName) throws IOException {
|
2017-12-09 23:00:04 +01:00
|
|
|
this(path, fontName, false);
|
|
|
|
}
|
2018-05-12 21:18:29 +02:00
|
|
|
|
2018-09-22 11:17:30 +02:00
|
|
|
RFTFont(final String path, final String fontName, final boolean onlyRaw) throws IOException {
|
2017-11-19 22:58:37 +01:00
|
|
|
isResource = false;
|
2017-12-09 23:00:04 +01:00
|
|
|
load(path + "/font_" + fontName + ".rft", onlyRaw);
|
2017-01-31 22:29:49 +01:00
|
|
|
}
|
|
|
|
|
2018-09-22 11:17:30 +02:00
|
|
|
public static RFTFont loadTemporaryFont(final String name) throws IOException {
|
2018-09-04 12:12:41 +02:00
|
|
|
return new BlankRFTFont(name, true);
|
2017-01-31 22:29:49 +01:00
|
|
|
}
|
|
|
|
|
2018-09-22 11:17:30 +02:00
|
|
|
public static RFTFont loadTemporaryFont(final String path, final String name) throws IOException {
|
2018-09-04 12:12:41 +02:00
|
|
|
return new BlankRFTFont(path, name, true);
|
2017-11-19 22:58:37 +01:00
|
|
|
}
|
|
|
|
|
2017-01-31 22:29:49 +01:00
|
|
|
@Override
|
2018-09-22 11:17:30 +02:00
|
|
|
public void load(final String path) throws IOException {
|
2017-12-09 23:00:04 +01:00
|
|
|
load(path, false);
|
|
|
|
}
|
2018-05-12 21:18:29 +02:00
|
|
|
|
2018-09-22 11:17:30 +02:00
|
|
|
private void load(final String path, final boolean onlyRaw) throws IOException {
|
2018-09-11 01:12:54 +02:00
|
|
|
Engine.getPlatform().getConsoleUtils().out().println(ConsoleUtils.OUTPUTLEVEL_DEBUG_MIN + 1, "Loading font " + path);
|
2017-11-19 22:58:37 +01:00
|
|
|
loadFont(path);
|
2017-12-09 23:00:04 +01:00
|
|
|
if (!onlyRaw) {
|
2018-09-22 11:17:30 +02:00
|
|
|
chars32 = new int[intervalsTotalSize * charIntCount];
|
2017-12-09 23:00:04 +01:00
|
|
|
for (int charCompressedIndex = 0; charCompressedIndex < intervalsTotalSize; charCompressedIndex++) {
|
|
|
|
final boolean[] currentChar = rawchars[charCompressedIndex];
|
|
|
|
if (currentChar == null) {
|
|
|
|
int currentInt = 0;
|
|
|
|
int currentBit = 0;
|
|
|
|
for (int i = 0; i < charS; i++) {
|
2018-09-22 11:17:30 +02:00
|
|
|
if (currentInt * RFTFont.intBits + currentBit >= (currentInt + 1) * RFTFont.intBits) {
|
2017-12-09 23:00:04 +01:00
|
|
|
currentInt += 1;
|
|
|
|
currentBit = 0;
|
|
|
|
}
|
|
|
|
chars32[charCompressedIndex * charIntCount + currentInt] = (chars32[charCompressedIndex * charIntCount + currentInt] << 1) + 1;
|
|
|
|
currentBit += 1;
|
2017-01-31 22:29:49 +01:00
|
|
|
}
|
2017-12-09 23:00:04 +01:00
|
|
|
} else {
|
|
|
|
int currentInt = 0;
|
|
|
|
int currentBit = 0;
|
|
|
|
for (int i = 0; i < charS; i++) {
|
2018-09-22 11:17:30 +02:00
|
|
|
if (currentBit >= RFTFont.intBits) {
|
2017-12-09 23:00:04 +01:00
|
|
|
currentInt += 1;
|
|
|
|
currentBit = 0;
|
|
|
|
}
|
2018-09-22 11:17:30 +02:00
|
|
|
chars32[charCompressedIndex * charIntCount + currentInt] = chars32[charCompressedIndex * charIntCount + currentInt] | (currentChar[i] ? 1 : 0) << currentBit;
|
2017-12-09 23:00:04 +01:00
|
|
|
currentBit++;
|
2017-01-31 22:29:49 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-04 12:12:41 +02:00
|
|
|
Engine.getPlatform().gc();
|
2017-01-31 22:29:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
private void loadFont(String string) throws IOException {
|
2018-06-11 22:41:11 +02:00
|
|
|
InputStream res;
|
|
|
|
try {
|
2018-09-28 11:39:28 +02:00
|
|
|
if (!string.startsWith("/")) {
|
2018-08-28 02:39:41 +02:00
|
|
|
string = "/" + string;
|
2018-09-28 11:39:28 +02:00
|
|
|
}
|
2018-09-04 12:12:41 +02:00
|
|
|
res = Engine.getPlatform().getStorageUtils().getResourceStream(string);
|
2018-09-22 11:17:30 +02:00
|
|
|
} catch (final URISyntaxException e) {
|
|
|
|
final IOException ex = new IOException();
|
2018-06-11 22:41:11 +02:00
|
|
|
ex.initCause(e);
|
|
|
|
throw ex;
|
|
|
|
}
|
|
|
|
final int[] file = Utils.realBytes(Utils.convertStreamToByteArray(res, res.available()));
|
2017-01-31 22:29:49 +01:00
|
|
|
final int filelength = file.length;
|
|
|
|
if (filelength >= 16) {
|
|
|
|
if (file[0x0] == 114 && file[0x1] == 97 && file[0x2] == 119 && file[0x3] == 0xFF && file[0x8] == 0xFF && file[0xD] == 0xFF) {
|
|
|
|
charW = file[0x4] << 8 | file[0x5];
|
|
|
|
charH = file[0x6] << 8 | file[0x7];
|
|
|
|
charS = charW * charH;
|
2018-09-22 11:17:30 +02:00
|
|
|
charIntCount = (int) Math.ceil((double) charS / (double) RFTFont.intBits);
|
2017-01-31 22:29:49 +01:00
|
|
|
minBound = file[0x9] << 24 | file[0xA] << 16 | file[0xB] << 8 | file[0xC];
|
|
|
|
maxBound = file[0xE] << 24 | file[0xF] << 16 | file[0x10] << 8 | file[0x11];
|
2018-09-28 11:39:28 +02:00
|
|
|
if (maxBound <= minBound) {
|
2018-05-06 16:37:25 +02:00
|
|
|
maxBound = 66000; //TODO remove it: temp fix
|
2018-09-28 11:39:28 +02:00
|
|
|
}
|
2017-01-31 22:29:49 +01:00
|
|
|
rawchars = new boolean[maxBound - minBound][];
|
|
|
|
int index = 0x12;
|
2018-09-28 11:39:28 +02:00
|
|
|
while (index < filelength) {
|
2017-01-31 22:29:49 +01:00
|
|
|
try {
|
|
|
|
final int charIndex = file[index] << 8 | file[index + 1];
|
|
|
|
final boolean[] rawchar = new boolean[charS];
|
|
|
|
int charbytescount = 0;
|
2018-09-28 11:39:28 +02:00
|
|
|
while (charbytescount * 8 < charS) {
|
2017-01-31 22:29:49 +01:00
|
|
|
charbytescount += 1;
|
2018-09-28 11:39:28 +02:00
|
|
|
}
|
2017-01-31 22:29:49 +01:00
|
|
|
int currentBit = 0;
|
2018-09-28 11:39:28 +02:00
|
|
|
for (int i = 0; i <= charbytescount; i++) {
|
2017-01-31 22:29:49 +01:00
|
|
|
for (int bit = 0; bit < 8; bit++) {
|
2018-09-28 11:39:28 +02:00
|
|
|
if (currentBit >= charS) {
|
2017-01-31 22:29:49 +01:00
|
|
|
break;
|
2018-09-28 11:39:28 +02:00
|
|
|
}
|
2018-09-22 11:17:30 +02:00
|
|
|
rawchar[currentBit] = (file[index + 2 + i] >> 8 - 1 - bit & 0x1) == 1 ? true : false;
|
2017-01-31 22:29:49 +01:00
|
|
|
currentBit++;
|
|
|
|
}
|
2018-09-28 11:39:28 +02:00
|
|
|
}
|
2017-01-31 22:29:49 +01:00
|
|
|
rawchars[charIndex - minBound] = rawchar;
|
|
|
|
index += 2 + charbytescount;
|
|
|
|
} catch (final Exception ex) {
|
|
|
|
ex.printStackTrace();
|
|
|
|
System.out.println(string);
|
2018-09-04 12:12:41 +02:00
|
|
|
Engine.getPlatform().exit(-1);
|
2017-01-31 22:29:49 +01:00
|
|
|
}
|
2018-09-28 11:39:28 +02:00
|
|
|
}
|
|
|
|
} else {
|
2017-01-31 22:29:49 +01:00
|
|
|
throw new IOException();
|
2018-09-28 11:39:28 +02:00
|
|
|
}
|
|
|
|
} else {
|
2017-01-31 22:29:49 +01:00
|
|
|
throw new IOException();
|
2018-09-28 11:39:28 +02:00
|
|
|
}
|
2017-11-19 22:58:37 +01:00
|
|
|
findIntervals();
|
|
|
|
/*int[] screen = new int[rawchars.length * charW * charH];
|
|
|
|
for (int i = 0; i < rawchars.length; i++) {
|
|
|
|
if (rawchars[i] != null)
|
|
|
|
for (int charX = 0; charX < charW; charX++) {
|
|
|
|
for (int charY = 0; charY < charH; charY++) {
|
|
|
|
int x = i * charW + charX;
|
|
|
|
int y = charY;
|
|
|
|
screen[x + y * rawchars.length * charW] = rawchars[i][charX + charY * charW] ? 0xFF000000 : 0xFFFFFFFF;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
System.out.println();
|
|
|
|
System.out.println((('1' & 0xFFFF) - minBound) + "=>"+ (getCharIndexes("1")[0]));
|
|
|
|
this.saveArray(screen, rawchars.length * charW, charH, "N:\\TimedTemp"+string+".png");
|
|
|
|
System.out.println();
|
|
|
|
System.out.println();
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
|
|
|
private void findIntervals() {
|
2018-05-12 21:18:29 +02:00
|
|
|
final LinkedList<int[]> intervals = new LinkedList<>();
|
2017-11-19 22:58:37 +01:00
|
|
|
int beginIndex = -1;
|
|
|
|
int endIndex = 0;
|
|
|
|
int intervalSize = 0;
|
2018-09-02 12:45:51 +02:00
|
|
|
@SuppressWarnings("unused")
|
2018-05-12 21:18:29 +02:00
|
|
|
final int holeSize = 0;
|
2018-09-28 11:39:28 +02:00
|
|
|
for (int i = 0; i < rawchars.length; i++) {
|
2017-11-19 22:58:37 +01:00
|
|
|
if (rawchars[i] != null) {
|
|
|
|
beginIndex = i;
|
|
|
|
int firstNull = 0;
|
2018-09-28 11:39:28 +02:00
|
|
|
while (i + firstNull < rawchars.length && rawchars[i + firstNull] != null) {
|
2017-11-19 22:58:37 +01:00
|
|
|
firstNull++;
|
2018-09-28 11:39:28 +02:00
|
|
|
}
|
2017-11-19 22:58:37 +01:00
|
|
|
endIndex = beginIndex + firstNull - 1;
|
|
|
|
i = endIndex;
|
|
|
|
if (endIndex >= 0) {
|
|
|
|
intervalSize = endIndex - beginIndex + 1;
|
2018-05-12 21:18:29 +02:00
|
|
|
intervals.add(new int[] { beginIndex, endIndex, intervalSize });
|
2017-11-19 22:58:37 +01:00
|
|
|
intervalsTotalSize += intervalSize;
|
|
|
|
}
|
|
|
|
beginIndex = -1;
|
|
|
|
}
|
2018-09-28 11:39:28 +02:00
|
|
|
}
|
2017-11-19 22:58:37 +01:00
|
|
|
int lastIndex = 0;
|
2018-05-12 21:18:29 +02:00
|
|
|
final boolean[][] newrawchars = new boolean[intervalsTotalSize][];
|
|
|
|
for (final int[] interval : intervals) {
|
2018-09-22 11:17:30 +02:00
|
|
|
if (rawchars.length - interval[0] - interval[2] < 0) {
|
2017-11-19 22:58:37 +01:00
|
|
|
System.err.println(interval[0] + "-" + interval[1] + "(" + interval[2] + ")");
|
2018-09-22 11:17:30 +02:00
|
|
|
System.err.println(rawchars.length - interval[0] - interval[2]);
|
2017-11-19 22:58:37 +01:00
|
|
|
throw new ArrayIndexOutOfBoundsException();
|
|
|
|
}
|
2018-05-12 21:18:29 +02:00
|
|
|
if (newrawchars.length - (lastIndex - 1) - interval[2] < 0) {
|
|
|
|
System.err.println(newrawchars.length - (lastIndex - 1) - interval[2]);
|
2017-11-19 22:58:37 +01:00
|
|
|
throw new ArrayIndexOutOfBoundsException();
|
|
|
|
}
|
|
|
|
System.arraycopy(rawchars, interval[0], newrawchars, lastIndex, interval[2]);
|
|
|
|
lastIndex += interval[2];
|
|
|
|
}
|
|
|
|
rawchars = newrawchars;
|
2018-03-29 19:20:28 +02:00
|
|
|
final int intervalsSize = intervals.size();
|
|
|
|
this.intervals = new int[intervalsSize * 3];
|
|
|
|
for (int i = 0; i < intervalsSize; i++) {
|
2018-05-12 21:18:29 +02:00
|
|
|
final int[] interval = intervals.get(i);
|
2018-03-29 19:20:28 +02:00
|
|
|
this.intervals[i * 3 + 0] = interval[0];
|
|
|
|
this.intervals[i * 3 + 1] = interval[1];
|
|
|
|
this.intervals[i * 3 + 2] = interval[2];
|
|
|
|
}
|
2017-01-31 22:29:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@SuppressWarnings("unused")
|
2018-09-22 11:17:30 +02:00
|
|
|
private void saveArray(final int[] screen, final int w, final int h, final String coutputpng) {
|
2017-11-19 22:58:37 +01:00
|
|
|
final BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
|
2017-01-31 22:29:49 +01:00
|
|
|
final int[] a = ((DataBufferInt) bi.getRaster().getDataBuffer()).getData();
|
|
|
|
System.arraycopy(screen, 0, a, 0, screen.length);
|
|
|
|
try {
|
|
|
|
ImageIO.write(bi, "PNG", new File(coutputpng));
|
|
|
|
} catch (final IOException ex) {
|
2017-02-02 10:30:45 +01:00
|
|
|
Logger.getLogger(BinaryFont.class.getName()).log(Level.SEVERE, null, ex);
|
2017-01-31 22:29:49 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-22 11:17:30 +02:00
|
|
|
public int[] getCharIndexes(final String txt) {
|
2017-01-31 22:29:49 +01:00
|
|
|
final int l = txt.length();
|
|
|
|
final int[] indexes = new int[l];
|
|
|
|
final char[] chars = txt.toCharArray();
|
|
|
|
for (int i = 0; i < l; i++) {
|
2018-05-12 21:18:29 +02:00
|
|
|
final int originalIndex = (chars[i] & 0xFFFF) - minBound;
|
2017-12-09 23:00:04 +01:00
|
|
|
indexes[i] = compressIndex(originalIndex);
|
2017-01-31 22:29:49 +01:00
|
|
|
}
|
|
|
|
return indexes;
|
|
|
|
}
|
2018-05-12 21:18:29 +02:00
|
|
|
|
2018-09-22 11:17:30 +02:00
|
|
|
public int getCharIndex(final char c) {
|
2018-05-12 21:18:29 +02:00
|
|
|
final int originalIndex = c & 0xFFFF;
|
2017-12-09 23:00:04 +01:00
|
|
|
return compressIndex(originalIndex);
|
|
|
|
}
|
2018-05-12 21:18:29 +02:00
|
|
|
|
2018-09-22 11:17:30 +02:00
|
|
|
protected int compressIndex(final int originalIndex) {
|
2017-12-09 23:00:04 +01:00
|
|
|
int compressedIndex = 0;
|
2018-09-28 11:39:28 +02:00
|
|
|
for (int i = 0; i < intervals.length; i += 3) {
|
|
|
|
if (intervals[i] > originalIndex) {
|
2017-12-09 23:00:04 +01:00
|
|
|
break;
|
2018-09-28 11:39:28 +02:00
|
|
|
} else if (originalIndex <= intervals[i + 1]) {
|
2018-09-22 11:17:30 +02:00
|
|
|
compressedIndex += originalIndex - intervals[i];
|
2017-12-09 23:00:04 +01:00
|
|
|
break;
|
2018-09-28 11:39:28 +02:00
|
|
|
} else {
|
2018-05-12 21:18:29 +02:00
|
|
|
compressedIndex += intervals[i + 2];
|
2018-09-28 11:39:28 +02:00
|
|
|
}
|
|
|
|
}
|
2017-12-09 23:00:04 +01:00
|
|
|
return compressedIndex;
|
|
|
|
}
|
2018-05-12 21:18:29 +02:00
|
|
|
|
2018-09-02 12:45:51 +02:00
|
|
|
@SuppressWarnings("unused")
|
2018-09-22 11:17:30 +02:00
|
|
|
private int decompressIndex(final int compressedIndex) {
|
2018-05-12 21:18:29 +02:00
|
|
|
final int originalIndex = 0;
|
2017-12-09 23:00:04 +01:00
|
|
|
int i = 0;
|
2018-05-12 21:18:29 +02:00
|
|
|
for (int intvl = 0; intvl < intervals.length; intvl += 3) {
|
|
|
|
i += intervals[intvl + 2];
|
2018-09-28 11:39:28 +02:00
|
|
|
if (i == compressedIndex) {
|
2018-05-12 21:18:29 +02:00
|
|
|
return intervals[intvl + 1];
|
2018-09-28 11:39:28 +02:00
|
|
|
} else if (i > compressedIndex) {
|
2018-05-12 21:18:29 +02:00
|
|
|
return intervals[intvl + 1] - (i - compressedIndex);
|
2018-09-28 11:39:28 +02:00
|
|
|
}
|
2017-12-09 23:00:04 +01:00
|
|
|
}
|
|
|
|
return originalIndex;
|
|
|
|
}
|
2017-01-31 22:29:49 +01:00
|
|
|
|
|
|
|
@Override
|
2018-09-22 11:17:30 +02:00
|
|
|
public void initialize(final GraphicEngine d) {}
|
2017-01-31 22:29:49 +01:00
|
|
|
|
|
|
|
@Override
|
2018-09-22 11:17:30 +02:00
|
|
|
public int getStringWidth(final String text) {
|
2017-09-24 13:09:30 +02:00
|
|
|
final int w = charW * text.length();
|
2018-09-28 11:39:28 +02:00
|
|
|
if (text.length() > 0 && w > 0) {
|
2017-09-24 13:09:30 +02:00
|
|
|
return w;
|
2018-09-28 11:39:28 +02:00
|
|
|
} else {
|
2017-01-31 22:29:49 +01:00
|
|
|
return 0;
|
2018-09-28 11:39:28 +02:00
|
|
|
}
|
2017-01-31 22:29:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public int getCharacterWidth() {
|
|
|
|
return charW;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public int getCharacterHeight() {
|
|
|
|
return charH;
|
|
|
|
}
|
|
|
|
|
2017-09-15 23:24:12 +02:00
|
|
|
@Override
|
|
|
|
public boolean isInitialized() {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-04-02 00:47:33 +02:00
|
|
|
@Override
|
|
|
|
public int getSkinWidth() {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public int getSkinHeight() {
|
|
|
|
return -1;
|
|
|
|
}
|
2018-09-22 11:17:30 +02:00
|
|
|
|
2018-09-04 12:12:41 +02:00
|
|
|
private static class BlankRFTFont extends RFTFont {
|
|
|
|
|
2018-09-22 11:17:30 +02:00
|
|
|
BlankRFTFont(final String fontName, final boolean onlyRaw) throws IOException {
|
2018-09-04 12:12:41 +02:00
|
|
|
super(fontName, onlyRaw);
|
|
|
|
}
|
|
|
|
|
2018-09-22 11:17:30 +02:00
|
|
|
public BlankRFTFont(final String path, final String name, final boolean b) throws IOException {
|
2018-09-04 12:12:41 +02:00
|
|
|
super(path, name, b);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2018-09-22 11:17:30 +02:00
|
|
|
public void use(final GraphicEngine d) {
|
|
|
|
|
2018-09-04 12:12:41 +02:00
|
|
|
}
|
2018-09-22 11:17:30 +02:00
|
|
|
|
2018-09-04 12:12:41 +02:00
|
|
|
}
|
2018-04-02 00:47:33 +02:00
|
|
|
|
2017-01-31 22:29:49 +01:00
|
|
|
}
|