Bugfixes and new features.
-Improved: DynamicTexture is now a Interface so STB support can be added. -Added: UTF-8 Support for font rendering. SingleTexture requirement is still a thing. But that may change later. Most of the requirements are already added. -Added: ModelLoader/ModelCache into the Engine that handles old and new formats of the Game Engine but can now be used for other stuff too. -Added: HigherQuality/UTF Supporting font of Roboto-Medium into the engine so it looks a lot better. -Fixed: A bug within AssetPackages breaking paths.
This commit is contained in:
parent
b155fb5d92
commit
6577428b1f
|
@ -73,7 +73,7 @@ public class FolderAssetPackage implements IAssetPackage
|
||||||
{
|
{
|
||||||
for(Path path : IterableWrapper.wrap(stream.iterator()))
|
for(Path path : IterableWrapper.wrap(stream.iterator()))
|
||||||
{
|
{
|
||||||
result.add(folder.subAsset(start.relativize(path).toString()));
|
result.add(folder.subAsset(start.relativize(path).toString().replace("\\", "/")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(IOException e)
|
catch(IOException e)
|
||||||
|
|
|
@ -106,7 +106,7 @@ public class ZipAssetPackage implements IAssetPackage
|
||||||
{
|
{
|
||||||
for(Path path : IterableWrapper.wrap(stream.iterator()))
|
for(Path path : IterableWrapper.wrap(stream.iterator()))
|
||||||
{
|
{
|
||||||
result.add(folder.subAsset(start.relativize(path).toString()));
|
result.add(folder.subAsset(start.relativize(path).toString().replace("\\", "/")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(IOException e) { e.printStackTrace(); }
|
catch(IOException e) { e.printStackTrace(); }
|
||||||
|
|
|
@ -155,7 +155,7 @@ public abstract class GuiBase
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean onKeyTyped(char letter, int keyCode)
|
public boolean onKeyTyped(char letter, int codepoint)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -259,11 +259,11 @@ public class GuiScreenBase extends GuiBase
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onKeyTyped(char letter, int keyCode)
|
public boolean onKeyTyped(char letter, int codepoint)
|
||||||
{
|
{
|
||||||
for(IKeyComponent comp : findKeyPopups())
|
for(IKeyComponent comp : findKeyPopups())
|
||||||
{
|
{
|
||||||
if(comp.isAcceptingInput() && comp.onKeyTyped(letter, keyCode))
|
if(comp.isAcceptingInput() && comp.onKeyTyped(letter, codepoint))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,5 +8,5 @@ public interface IKeyComponent extends IInputComponent
|
||||||
|
|
||||||
public boolean onKeyPressed(int key);
|
public boolean onKeyPressed(int key);
|
||||||
|
|
||||||
public default boolean onKeyTyped(char letter, int keyCode) {return false;}
|
public default boolean onKeyTyped(char letter, int codepoint) {return false;}
|
||||||
}
|
}
|
||||||
|
|
|
@ -505,9 +505,9 @@ public class TextFieldComponent extends GuiComponent
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onKeyTyped(char letter, int keyCode)
|
public boolean onKeyTyped(char letter, int codepoint)
|
||||||
{
|
{
|
||||||
return isFlagSet(FLAG_FOCUS) && text.getFont().isCharValid(letter) && writeText(Character.toString(letter));
|
return isFlagSet(FLAG_FOCUS) && text.getFont().isCharValid(codepoint) && writeText(new String(Character.toChars(codepoint)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean deleteAtCurser(int amount)
|
public boolean deleteAtCurser(int amount)
|
||||||
|
|
|
@ -497,9 +497,9 @@ public class TextPanelComponent extends GuiComponent implements IButtonComponent
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onKeyTyped(char letter, int keyCode)
|
public boolean onKeyTyped(char letter, int codepoint)
|
||||||
{
|
{
|
||||||
return isFlagSet(FLAG_FOCUS) && text.getFont().isCharValid(letter) && writeText(Character.toString(letter));
|
return isFlagSet(FLAG_FOCUS) && text.getFont().isCharValid(codepoint) && writeText(new String(Character.toChars(codepoint)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean deleteAtCurser(int amount)
|
public boolean deleteAtCurser(int amount)
|
||||||
|
|
|
@ -17,6 +17,8 @@ import java.util.function.Consumer;
|
||||||
import com.google.gson.JsonArray;
|
import com.google.gson.JsonArray;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
|
|
||||||
|
import speiger.src.collections.ints.collections.IntIterator;
|
||||||
|
import speiger.src.collections.ints.utils.IntIterators;
|
||||||
import speiger.src.collections.objects.lists.ObjectArrayList;
|
import speiger.src.collections.objects.lists.ObjectArrayList;
|
||||||
import speiger.src.collections.objects.maps.impl.hash.Object2ObjectLinkedOpenHashMap;
|
import speiger.src.collections.objects.maps.impl.hash.Object2ObjectLinkedOpenHashMap;
|
||||||
import speiger.src.collections.objects.misc.pairs.ObjectObjectPair;
|
import speiger.src.collections.objects.misc.pairs.ObjectObjectPair;
|
||||||
|
@ -35,7 +37,12 @@ public class FontBuilder
|
||||||
|
|
||||||
public static ObjectObjectPair<BufferedImage, JsonObject> createBitmapFont(InputStream stream, float size)
|
public static ObjectObjectPair<BufferedImage, JsonObject> createBitmapFont(InputStream stream, float size)
|
||||||
{
|
{
|
||||||
ObjectObjectPair<ObjectObjectPair<Vec2i, BufferedImage>, List<WrittenChar>> result = createBitmapFont(stream, "ISO-8859-1", PLAIN | BOLD, size);
|
return createBitmapFont(stream, size, "ISO-8859-1");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ObjectObjectPair<BufferedImage, JsonObject> createBitmapFont(InputStream stream, float size, String charset)
|
||||||
|
{
|
||||||
|
ObjectObjectPair<ObjectObjectPair<Vec2i, BufferedImage>, List<WrittenChar>> result = createBitmapFont(stream, charset, PLAIN | BOLD, size);
|
||||||
if(result == null) return null;
|
if(result == null) return null;
|
||||||
JsonArray array = new JsonArray();
|
JsonArray array = new JsonArray();
|
||||||
result.getValue().forEach(T -> array.add(T.seralize()));
|
result.getValue().forEach(T -> array.add(T.seralize()));
|
||||||
|
@ -70,7 +77,6 @@ public class FontBuilder
|
||||||
|
|
||||||
Font font = Font.createFont(Font.TRUETYPE_FONT, ttf).deriveFont(size);
|
Font font = Font.createFont(Font.TRUETYPE_FONT, ttf).deriveFont(size);
|
||||||
String validChars = (flags & LITERAL) != 0 ? characters : getChars(characters, font);
|
String validChars = (flags & LITERAL) != 0 ? characters : getChars(characters, font);
|
||||||
|
|
||||||
if((flags & PLAIN) != 0) loadFontData(font, validChars, data);
|
if((flags & PLAIN) != 0) loadFontData(font, validChars, data);
|
||||||
if((flags & BOLD) != 0) loadFontData(font.deriveFont(Font.BOLD), validChars, data);
|
if((flags & BOLD) != 0) loadFontData(font.deriveFont(Font.BOLD), validChars, data);
|
||||||
|
|
||||||
|
@ -79,7 +85,6 @@ public class FontBuilder
|
||||||
builder.buildHollow((K, V) -> {
|
builder.buildHollow((K, V) -> {
|
||||||
BufferedImage image = new BufferedImage(K.getX(), K.getY(), BufferedImage.TYPE_INT_ARGB);
|
BufferedImage image = new BufferedImage(K.getX(), K.getY(), BufferedImage.TYPE_INT_ARGB);
|
||||||
Graphics2D graphics = image.createGraphics();
|
Graphics2D graphics = image.createGraphics();
|
||||||
|
|
||||||
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||||
graphics.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
|
graphics.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
|
||||||
graphics.setFont(font);
|
graphics.setFont(font);
|
||||||
|
@ -93,7 +98,7 @@ public class FontBuilder
|
||||||
extra = pair.extraY;
|
extra = pair.extraY;
|
||||||
graphics.setFont(pair.getFont());
|
graphics.setFont(pair.getFont());
|
||||||
graphics.setColor(Color.WHITE);
|
graphics.setColor(Color.WHITE);
|
||||||
graphics.drawString(Character.toString(pair.getLetter()), entry.getX()-pair.xOffset, pair.getExtraY(entry.getY()+metric.getAscent()));
|
graphics.drawString(new String(Character.toChars(pair.getLetter())), entry.getX()-pair.xOffset, pair.getExtraY(entry.getY()+metric.getAscent()));
|
||||||
result.getValue().add(new WrittenChar(pair.getLetter(), entry.getX(), entry.getY(), entry.getWidth(), entry.getHeight(), pair.isBold()));
|
result.getValue().add(new WrittenChar(pair.getLetter(), entry.getX(), entry.getY(), entry.getWidth(), entry.getHeight(), pair.isBold()));
|
||||||
}
|
}
|
||||||
toDraw.values().forEach(T -> result.getValue().add(new WrittenChar(T.getLetter(), 0, 0, 0, 0, T.isBold())));
|
toDraw.values().forEach(T -> result.getValue().add(new WrittenChar(T.getLetter(), 0, 0, 0, 0, T.isBold())));
|
||||||
|
@ -118,9 +123,11 @@ public class FontBuilder
|
||||||
{
|
{
|
||||||
CharsetEncoder encoder = Charset.forName(s).newEncoder();
|
CharsetEncoder encoder = Charset.forName(s).newEncoder();
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
for(char c = 0;c < Character.MAX_VALUE;c++)
|
for(int c = 0;c < 0x110000;c++)
|
||||||
{
|
{
|
||||||
if(encoder.canEncode(c) && font.canDisplay(c)) builder.append(c);
|
if(!Character.isDefined(c)) continue;
|
||||||
|
char[] chars = Character.toChars(c);
|
||||||
|
if(encoder.canEncode(new String(chars)) && font.canDisplay(c)) builder.append(chars);
|
||||||
}
|
}
|
||||||
return builder.toString();
|
return builder.toString();
|
||||||
}
|
}
|
||||||
|
@ -135,11 +142,14 @@ public class FontBuilder
|
||||||
FontMetrics metric = graphics.getFontMetrics();
|
FontMetrics metric = graphics.getFontMetrics();
|
||||||
int extraHeight = 0;
|
int extraHeight = 0;
|
||||||
List<CharData> data = new ObjectArrayList<>();
|
List<CharData> data = new ObjectArrayList<>();
|
||||||
for(char letter : chars.toCharArray())
|
int c = 0;
|
||||||
|
for(IntIterator iter = IntIterators.wrap(chars.codePoints().iterator());iter.hasNext();c++)
|
||||||
{
|
{
|
||||||
Rectangle rect = font.layoutGlyphVector(graphics.getFontRenderContext(), new char[] {letter }, 0, 1, 0).getGlyphPixelBounds(0, graphics.getFontRenderContext(), 0.0F, 0.0F);
|
int next = iter.nextInt();
|
||||||
|
Rectangle rect = font.layoutGlyphVector(graphics.getFontRenderContext(), Character.toChars(next), 0, Character.charCount(next), 0).getGlyphPixelBounds(0, graphics.getFontRenderContext(), 0.0F, 0.0F);
|
||||||
extraHeight = Math.min(extraHeight, rect.y);
|
extraHeight = Math.min(extraHeight, rect.y);
|
||||||
data.add(new CharData(font, letter, rect, metric.charWidth(letter), metric.getHeight(), font.isBold()));
|
data.add(new CharData(font, next, rect, metric.charWidth(next), metric.getHeight(), font.isBold()));
|
||||||
|
if(c % 1000 == 0) System.out.println("Rendered: "+c+" / "+chars.length()+" Chars");
|
||||||
}
|
}
|
||||||
extraHeight = -(extraHeight+metric.getAscent());
|
extraHeight = -(extraHeight+metric.getAscent());
|
||||||
for(int i = 0,m=data.size();i<m;listener.accept(data.get(i++).offset(extraHeight)));
|
for(int i = 0,m=data.size();i<m;listener.accept(data.get(i++).offset(extraHeight)));
|
||||||
|
@ -148,14 +158,14 @@ public class FontBuilder
|
||||||
|
|
||||||
public static class WrittenChar
|
public static class WrittenChar
|
||||||
{
|
{
|
||||||
char letter;
|
int letter;
|
||||||
int x;
|
int x;
|
||||||
int y;
|
int y;
|
||||||
int width;
|
int width;
|
||||||
int height;
|
int height;
|
||||||
boolean bold;
|
boolean bold;
|
||||||
|
|
||||||
public WrittenChar(char letter, int x, int y, int width, int height, boolean bold)
|
public WrittenChar(int letter, int x, int y, int width, int height, boolean bold)
|
||||||
{
|
{
|
||||||
this.letter = letter;
|
this.letter = letter;
|
||||||
this.x = x;
|
this.x = x;
|
||||||
|
@ -168,7 +178,7 @@ public class FontBuilder
|
||||||
public JsonObject seralize()
|
public JsonObject seralize()
|
||||||
{
|
{
|
||||||
JsonObject obj = new JsonObject();
|
JsonObject obj = new JsonObject();
|
||||||
obj.addProperty("char", (int)letter);
|
obj.addProperty("char", letter);
|
||||||
obj.addProperty("minX", x);
|
obj.addProperty("minX", x);
|
||||||
obj.addProperty("minY", y);
|
obj.addProperty("minY", y);
|
||||||
obj.addProperty("maxX", x+width);
|
obj.addProperty("maxX", x+width);
|
||||||
|
@ -186,14 +196,14 @@ public class FontBuilder
|
||||||
private static class CharData
|
private static class CharData
|
||||||
{
|
{
|
||||||
Font font;
|
Font font;
|
||||||
char letter;
|
int letter;
|
||||||
int xOffset;
|
int xOffset;
|
||||||
int width;
|
int width;
|
||||||
int height;
|
int height;
|
||||||
boolean bold;
|
boolean bold;
|
||||||
int extraY = 0;
|
int extraY = 0;
|
||||||
|
|
||||||
public CharData(Font font, char letter, Rectangle bounds, int width, int height, boolean bold)
|
public CharData(Font font, int letter, Rectangle bounds, int width, int height, boolean bold)
|
||||||
{
|
{
|
||||||
this.font = font;
|
this.font = font;
|
||||||
this.letter = letter;
|
this.letter = letter;
|
||||||
|
@ -228,14 +238,14 @@ public class FontBuilder
|
||||||
return extraY + asent;
|
return extraY + asent;
|
||||||
}
|
}
|
||||||
|
|
||||||
public char getLetter()
|
public int getLetter()
|
||||||
{
|
{
|
||||||
return letter;
|
return letter;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AssetLocation asLocation()
|
public AssetLocation asLocation()
|
||||||
{
|
{
|
||||||
return AssetLocation.of("base", font.getFontName().replaceAll(" ", "_") + (bold ? "_Bold" : "") + "_" + ((int)letter));
|
return AssetLocation.of("base", font.getFontName().replaceAll(" ", "_") + (bold ? "_Bold" : "") + "_" + (letter));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,10 +30,10 @@ import speiger.src.coreengine.utils.helpers.TextUtil;
|
||||||
public class FontRenderer implements IFontRenderer
|
public class FontRenderer implements IFontRenderer
|
||||||
{
|
{
|
||||||
public static final String INVALID_SEARCH = new String(" §<");
|
public static final String INVALID_SEARCH = new String(" §<");
|
||||||
public static final char EMPTY = (char)0;
|
public static final int EMPTY = (char)0;
|
||||||
public static final char SPACE = ' ';
|
public static final int SPACE = ' ';
|
||||||
public static final char TAB = '\t';
|
public static final int TAB = '\t';
|
||||||
public static final char LINE_SEPERATOR = '\n';
|
public static final int LINE_SEPERATOR = '\n';
|
||||||
Tesselator bufferBuilder = new Tesselator(655340);
|
Tesselator bufferBuilder = new Tesselator(655340);
|
||||||
|
|
||||||
IFontProvider provider;
|
IFontProvider provider;
|
||||||
|
@ -46,9 +46,9 @@ public class FontRenderer implements IFontRenderer
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CharInstance getInstance(char letter, boolean isBold)
|
public CharInstance getInstance(int codepoint, boolean isBold)
|
||||||
{
|
{
|
||||||
return provider.getCharacter(letter, isBold);
|
return provider.getCharacter(codepoint, isBold);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -302,16 +302,16 @@ public class FontRenderer implements IFontRenderer
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float getCharLength(char letter, boolean bold)
|
public float getCharLength(int codepoint, boolean bold)
|
||||||
{
|
{
|
||||||
switch(letter)
|
switch(codepoint)
|
||||||
{
|
{
|
||||||
case SPACE:
|
case SPACE:
|
||||||
return provider.getSpaceWidth();
|
return provider.getSpaceWidth();
|
||||||
case TAB:
|
case TAB:
|
||||||
return provider.getTabWidth();
|
return provider.getTabWidth();
|
||||||
default:
|
default:
|
||||||
CharInstance instance = getInstance(letter, bold);
|
CharInstance instance = getInstance(codepoint, bold);
|
||||||
return instance == null ? 0F : instance.getXAdvance();
|
return instance == null ? 0F : instance.getXAdvance();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -401,9 +401,9 @@ public class FontRenderer implements IFontRenderer
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isCharValid(char letter)
|
public boolean isCharValid(int codepoint)
|
||||||
{
|
{
|
||||||
return provider.isCharacterValid(letter);
|
return provider.isCharacterValid(codepoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -11,15 +11,15 @@ public interface IFontRenderer
|
||||||
public float getFontHeight();
|
public float getFontHeight();
|
||||||
public float getBaseLine();
|
public float getBaseLine();
|
||||||
public ITexture getTexture();
|
public ITexture getTexture();
|
||||||
public CharInstance getInstance(char letter, boolean bold);
|
public CharInstance getInstance(int codepoint, boolean bold);
|
||||||
|
|
||||||
public void updateText(TextComponent component);
|
public void updateText(TextComponent component);
|
||||||
|
|
||||||
public default String trimStringToWidth(String text, float limit){return trimStringToWidth(text, limit, false);}
|
public default String trimStringToWidth(String text, float limit){return trimStringToWidth(text, limit, false);}
|
||||||
public String trimStringToWidth(String text, float limit, boolean reverse);
|
public String trimStringToWidth(String text, float limit, boolean reverse);
|
||||||
|
|
||||||
public default float getCharLength(char letter){return getCharLength(letter, false);};
|
public default float getCharLength(int codepoint){return getCharLength(codepoint, false);};
|
||||||
public float getCharLength(char letter, boolean bold);
|
public float getCharLength(int codepoint, boolean bold);
|
||||||
|
|
||||||
public default float getTextLength(String text){return getTextLength(text, 0);};
|
public default float getTextLength(String text){return getTextLength(text, 0);};
|
||||||
public float getTextLength(String text, int flags);
|
public float getTextLength(String text, int flags);
|
||||||
|
@ -30,7 +30,7 @@ public interface IFontRenderer
|
||||||
|
|
||||||
public String[] splitLines(String text, float maxWidth, int flags);
|
public String[] splitLines(String text, float maxWidth, int flags);
|
||||||
|
|
||||||
public boolean isCharValid(char letter);
|
public boolean isCharValid(int codepoint);
|
||||||
public default String clearInvalidLetters(String text)
|
public default String clearInvalidLetters(String text)
|
||||||
{
|
{
|
||||||
if(text == null || text.isEmpty())
|
if(text == null || text.isEmpty())
|
||||||
|
@ -38,13 +38,11 @@ public interface IFontRenderer
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
StringBuilder builder = new StringBuilder(text.length());
|
StringBuilder builder = new StringBuilder(text.length());
|
||||||
for(int i = 0,m=text.length();i<m;i++)
|
for(int i = 0,m=text.length();i<m;)
|
||||||
{
|
{
|
||||||
char letter = text.charAt(i);
|
int codePoint = text.codePointAt(i);
|
||||||
if(isCharValid(letter))
|
if(isCharValid(codePoint)) builder.append(Character.toChars(codePoint));
|
||||||
{
|
i += Character.charCount(codePoint);
|
||||||
builder.append(letter);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return builder.toString();
|
return builder.toString();
|
||||||
}
|
}
|
||||||
|
@ -52,7 +50,7 @@ public interface IFontRenderer
|
||||||
|
|
||||||
public static final class CharInstance
|
public static final class CharInstance
|
||||||
{
|
{
|
||||||
char character;
|
int character;
|
||||||
float width;
|
float width;
|
||||||
float height;
|
float height;
|
||||||
float minU;
|
float minU;
|
||||||
|
@ -62,13 +60,13 @@ public interface IFontRenderer
|
||||||
float xAdvance;
|
float xAdvance;
|
||||||
boolean bold;
|
boolean bold;
|
||||||
|
|
||||||
public CharInstance(char character, boolean bold)
|
public CharInstance(int character, boolean bold)
|
||||||
{
|
{
|
||||||
this.character = character;
|
this.character = character;
|
||||||
this.bold = bold;
|
this.bold = bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CharInstance(char character, int width, int height, float minU, float minV, float maxU, float maxV, int xAdvance, boolean bold)
|
public CharInstance(int character, int width, int height, float minU, float minV, float maxU, float maxV, int xAdvance, boolean bold)
|
||||||
{
|
{
|
||||||
this.character = character;
|
this.character = character;
|
||||||
this.width = width;
|
this.width = width;
|
||||||
|
@ -88,7 +86,7 @@ public interface IFontRenderer
|
||||||
xAdvance *= scale;
|
xAdvance *= scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
public char getCharacter()
|
public int getCharacter()
|
||||||
{
|
{
|
||||||
return character;
|
return character;
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,16 @@ public class TextLexer
|
||||||
}
|
}
|
||||||
current.setSpecail(type);
|
current.setSpecail(type);
|
||||||
}
|
}
|
||||||
|
if(Character.isHighSurrogate(letter) && i + 1 < m)
|
||||||
|
{
|
||||||
|
char extra = text.charAt(i + 1);
|
||||||
|
if(Character.isLowSurrogate(extra))
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
current.addLetter(render.getInstance(Character.toCodePoint(letter, extra), context.isBold()));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
current.addLetter(render.getInstance(letter, context.isBold()));
|
current.addLetter(render.getInstance(letter, context.isBold()));
|
||||||
}
|
}
|
||||||
if(!current.isEmpty())
|
if(!current.isEmpty())
|
||||||
|
@ -60,7 +70,7 @@ public class TextLexer
|
||||||
{
|
{
|
||||||
return ObjectLists.empty();
|
return ObjectLists.empty();
|
||||||
}
|
}
|
||||||
List<Line> lines = new ObjectArrayList<Line>();
|
List<Line> lines = new ObjectArrayList<>();
|
||||||
getWords(text, context, helper);
|
getWords(text, context, helper);
|
||||||
Line line = new Line(maxWidth);
|
Line line = new Line(maxWidth);
|
||||||
for(int i = 0;i<helper.size();i++)
|
for(int i = 0;i<helper.size();i++)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package speiger.src.coreengine.rendering.gui.renderer.lexer;
|
package speiger.src.coreengine.rendering.gui.renderer.lexer;
|
||||||
|
|
||||||
import speiger.src.collections.chars.collections.CharIterable;
|
import speiger.src.collections.ints.collections.IntIterable;
|
||||||
import speiger.src.collections.chars.collections.CharIterator;
|
import speiger.src.collections.ints.collections.IntIterator;
|
||||||
import speiger.src.collections.objects.collections.ObjectIterator;
|
import speiger.src.collections.objects.collections.ObjectIterator;
|
||||||
import speiger.src.collections.objects.lists.ObjectArrayList;
|
import speiger.src.collections.objects.lists.ObjectArrayList;
|
||||||
import speiger.src.collections.objects.lists.ObjectList;
|
import speiger.src.collections.objects.lists.ObjectList;
|
||||||
|
@ -9,7 +9,7 @@ import speiger.src.coreengine.rendering.gui.renderer.IFontRenderer.CharInstance;
|
||||||
import speiger.src.coreengine.rendering.gui.renderer.lexer.TextContext.WordContext;
|
import speiger.src.coreengine.rendering.gui.renderer.lexer.TextContext.WordContext;
|
||||||
import speiger.src.coreengine.utils.collections.iterators.IterableWrapper;
|
import speiger.src.coreengine.utils.collections.iterators.IterableWrapper;
|
||||||
|
|
||||||
public class Word implements CharIterable
|
public class Word implements IntIterable
|
||||||
{
|
{
|
||||||
final float scale;
|
final float scale;
|
||||||
ObjectList<CharInstance> letters = new ObjectArrayList<CharInstance>();
|
ObjectList<CharInstance> letters = new ObjectArrayList<CharInstance>();
|
||||||
|
@ -90,7 +90,7 @@ public class Word implements CharIterable
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
for(int i = 0,m=letters.size();i<m;i++)
|
for(int i = 0,m=letters.size();i<m;i++)
|
||||||
{
|
{
|
||||||
builder.append(letters.get(i).getCharacter());
|
builder.append(Character.toChars(letters.get(i).getCharacter()));
|
||||||
}
|
}
|
||||||
return builder.toString();
|
return builder.toString();
|
||||||
}
|
}
|
||||||
|
@ -143,9 +143,9 @@ public class Word implements CharIterable
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CharIterator iterator()
|
public IntIterator iterator()
|
||||||
{
|
{
|
||||||
return new CharIterator(){
|
return new IntIterator(){
|
||||||
int index = 0;
|
int index = 0;
|
||||||
@Override
|
@Override
|
||||||
public boolean hasNext()
|
public boolean hasNext()
|
||||||
|
@ -154,7 +154,7 @@ public class Word implements CharIterable
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public char nextChar()
|
public int nextInt()
|
||||||
{
|
{
|
||||||
return letters.get(index++).getCharacter();
|
return letters.get(index++).getCharacter();
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,9 +5,9 @@ import java.util.List;
|
||||||
|
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
|
|
||||||
import speiger.src.collections.chars.maps.impl.hash.Char2ObjectOpenHashMap;
|
import speiger.src.collections.ints.maps.impl.hash.Int2ObjectOpenHashMap;
|
||||||
import speiger.src.collections.chars.maps.interfaces.Char2ObjectMap;
|
import speiger.src.collections.ints.maps.interfaces.Int2ObjectMap;
|
||||||
import speiger.src.collections.chars.utils.maps.Char2ObjectMaps;
|
import speiger.src.collections.ints.utils.maps.Int2ObjectMaps;
|
||||||
import speiger.src.collections.objects.misc.pairs.ObjectObjectPair;
|
import speiger.src.collections.objects.misc.pairs.ObjectObjectPair;
|
||||||
import speiger.src.coreengine.assets.AssetLocation;
|
import speiger.src.coreengine.assets.AssetLocation;
|
||||||
import speiger.src.coreengine.assets.AssetManager;
|
import speiger.src.coreengine.assets.AssetManager;
|
||||||
|
@ -24,10 +24,10 @@ public class BitmapFontProvider implements IFontProvider
|
||||||
{
|
{
|
||||||
FontInfo info;
|
FontInfo info;
|
||||||
ITexture texture;
|
ITexture texture;
|
||||||
Char2ObjectMap<CharInstance>[] instances;
|
Int2ObjectMap<CharInstance>[] instances;
|
||||||
float space;
|
float space;
|
||||||
|
|
||||||
public BitmapFontProvider(FontInfo info, ITexture texture, Char2ObjectMap<CharInstance>[] instances)
|
public BitmapFontProvider(FontInfo info, ITexture texture, Int2ObjectMap<CharInstance>[] instances)
|
||||||
{
|
{
|
||||||
this.info = info;
|
this.info = info;
|
||||||
this.texture = texture;
|
this.texture = texture;
|
||||||
|
@ -53,16 +53,16 @@ public class BitmapFontProvider implements IFontProvider
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isCharacterValid(char value)
|
public boolean isCharacterValid(int codepoint)
|
||||||
{
|
{
|
||||||
return instances[0].containsKey(value) || instances[1].containsKey(value);
|
return instances[0].containsKey(codepoint) || instances[1].containsKey(codepoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CharInstance getCharacter(char value, boolean bold)
|
public CharInstance getCharacter(int codepoint, boolean bold)
|
||||||
{
|
{
|
||||||
Char2ObjectMap<CharInstance> map = instances[bold ? 1 : 0];
|
Int2ObjectMap<CharInstance> map = instances[bold ? 1 : 0];
|
||||||
return (map.isEmpty() ? instances[bold ? 0 : 1] : map).get(value);
|
return (map.isEmpty() ? instances[bold ? 0 : 1] : map).get(codepoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -93,14 +93,14 @@ public class BitmapFontProvider implements IFontProvider
|
||||||
{
|
{
|
||||||
FontInfo info = new FontInfo(object.getAsJsonObject("info"));
|
FontInfo info = new FontInfo(object.getAsJsonObject("info"));
|
||||||
float multiplier = info.setDesiredHeight(desiredSize);
|
float multiplier = info.setDesiredHeight(desiredSize);
|
||||||
Char2ObjectMap<CharInstance>[] maps = new Char2ObjectMap[]{new Char2ObjectOpenHashMap<CharInstance>(), new Char2ObjectOpenHashMap<CharInstance>()};
|
Int2ObjectMap<CharInstance>[] maps = new Int2ObjectMap[]{new Int2ObjectOpenHashMap<CharInstance>(), new Int2ObjectOpenHashMap<CharInstance>()};
|
||||||
JsonUtil.iterate(object.get("chars"), T -> {
|
JsonUtil.iterate(object.get("chars"), T -> {
|
||||||
CharInstance instance = info.create(T);
|
CharInstance instance = info.create(T);
|
||||||
instance.scale(multiplier);
|
instance.scale(multiplier);
|
||||||
maps[instance.isBold() ? 1 : 0].put(instance.getCharacter(), instance);
|
maps[instance.isBold() ? 1 : 0].put(instance.getCharacter(), instance);
|
||||||
});
|
});
|
||||||
if(maps[0].isEmpty()) maps[0] = Char2ObjectMaps.empty();
|
if(maps[0].isEmpty()) maps[0] = Int2ObjectMaps.empty();
|
||||||
if(maps[1].isEmpty()) maps[1] = Char2ObjectMaps.empty();
|
if(maps[1].isEmpty()) maps[1] = Int2ObjectMaps.empty();
|
||||||
return new BitmapFontProvider(info, ITexture.simple(AssetLocation.of(object.get("file").getAsString())), maps);
|
return new BitmapFontProvider(info, ITexture.simple(AssetLocation.of(object.get("file").getAsString())), maps);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,15 +121,15 @@ public class BitmapFontProvider implements IFontProvider
|
||||||
Vec2i size = written.getKey().getKey();
|
Vec2i size = written.getKey().getKey();
|
||||||
FontInfo fontInfo = new FontInfo(image.getWidth(), image.getHeight(), size.getY(), size.getX(), tabs);
|
FontInfo fontInfo = new FontInfo(image.getWidth(), image.getHeight(), size.getY(), size.getX(), tabs);
|
||||||
float mulitplier = fontInfo.setDesiredHeight(desiredSize);
|
float mulitplier = fontInfo.setDesiredHeight(desiredSize);
|
||||||
Char2ObjectMap<CharInstance>[] maps = new Char2ObjectMap[]{new Char2ObjectOpenHashMap<CharInstance>(), new Char2ObjectOpenHashMap<CharInstance>()};
|
Int2ObjectMap<CharInstance>[] maps = new Int2ObjectMap[]{new Int2ObjectOpenHashMap<CharInstance>(), new Int2ObjectOpenHashMap<CharInstance>()};
|
||||||
for(WrittenChar entry : written.getValue())
|
for(WrittenChar entry : written.getValue())
|
||||||
{
|
{
|
||||||
CharInstance instance = entry.create(fontInfo.textureWidth, fontInfo.textureHeight);
|
CharInstance instance = entry.create(fontInfo.textureWidth, fontInfo.textureHeight);
|
||||||
instance.scale(mulitplier);
|
instance.scale(mulitplier);
|
||||||
maps[instance.isBold() ? 1 : 0].put(instance.getCharacter(), instance);
|
maps[instance.isBold() ? 1 : 0].put(instance.getCharacter(), instance);
|
||||||
}
|
}
|
||||||
if(maps[0].isEmpty()) maps[0] = Char2ObjectMaps.empty();
|
if(maps[0].isEmpty()) maps[0] = Int2ObjectMaps.empty();
|
||||||
if(maps[1].isEmpty()) maps[1] = Char2ObjectMaps.empty();
|
if(maps[1].isEmpty()) maps[1] = Int2ObjectMaps.empty();
|
||||||
return new BitmapFontProvider(fontInfo, ITexture.direct(image), maps);
|
return new BitmapFontProvider(fontInfo, ITexture.direct(image), maps);
|
||||||
}
|
}
|
||||||
catch(Exception e)
|
catch(Exception e)
|
||||||
|
|
|
@ -9,8 +9,8 @@ import speiger.src.coreengine.utils.helpers.JsonUtil;
|
||||||
public interface IFontProvider
|
public interface IFontProvider
|
||||||
{
|
{
|
||||||
public ITexture getTexture();
|
public ITexture getTexture();
|
||||||
public boolean isCharacterValid(char value);
|
public boolean isCharacterValid(int codePoint);
|
||||||
public CharInstance getCharacter(char value, boolean bold);
|
public CharInstance getCharacter(int codePoint, boolean bold);
|
||||||
public float getFontHeight();
|
public float getFontHeight();
|
||||||
public float getBaseLine();
|
public float getBaseLine();
|
||||||
|
|
||||||
|
@ -51,10 +51,10 @@ public interface IFontProvider
|
||||||
|
|
||||||
public CharInstance create(JsonObject obj)
|
public CharInstance create(JsonObject obj)
|
||||||
{
|
{
|
||||||
return create((char)obj.get("char").getAsInt(), obj.get("minX").getAsInt(), obj.get("minY").getAsInt(), obj.get("maxX").getAsInt(), obj.get("maxY").getAsInt(), JsonUtil.getOrDefault(obj, "bold", false));
|
return create(obj.get("char").getAsInt(), obj.get("minX").getAsInt(), obj.get("minY").getAsInt(), obj.get("maxX").getAsInt(), obj.get("maxY").getAsInt(), JsonUtil.getOrDefault(obj, "bold", false));
|
||||||
}
|
}
|
||||||
|
|
||||||
public CharInstance create(char character, int minX, int minY, int maxX, int maxY, boolean bold)
|
public CharInstance create(int character, int minX, int minY, int maxX, int maxY, boolean bold)
|
||||||
{
|
{
|
||||||
return new CharInstance(character, maxX - minX, maxY - minY, getTextureU(minX), getTextureV(minY), getTextureU(maxX), getTextureV(maxY), maxX - minX, bold);
|
return new CharInstance(character, maxX - minX, maxY - minY, getTextureU(minX), getTextureV(minY), getTextureU(maxX), getTextureV(maxY), maxX - minX, bold);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,82 @@
|
||||||
|
package speiger.src.coreengine.rendering.models;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import speiger.src.collections.objects.maps.impl.hash.Object2ObjectLinkedOpenHashMap;
|
||||||
|
import speiger.src.coreengine.assets.AssetLocation;
|
||||||
|
import speiger.src.coreengine.assets.AssetManager;
|
||||||
|
import speiger.src.coreengine.assets.reloader.IReloadableResource;
|
||||||
|
import speiger.src.coreengine.rendering.models.loader.MergedModelData;
|
||||||
|
import speiger.src.coreengine.rendering.models.loader.ModelLoader;
|
||||||
|
import speiger.src.coreengine.rendering.models.loader.SimpleModelData;
|
||||||
|
|
||||||
|
public class ModelCache implements IReloadableResource
|
||||||
|
{
|
||||||
|
AssetManager manager;
|
||||||
|
Map<AssetLocation, List<SimpleModelData>> models = new Object2ObjectLinkedOpenHashMap<>();
|
||||||
|
|
||||||
|
public void setManager(AssetManager manager)
|
||||||
|
{
|
||||||
|
this.manager = manager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reload()
|
||||||
|
{
|
||||||
|
models.clear();
|
||||||
|
load();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void destroy()
|
||||||
|
{
|
||||||
|
models.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void load()
|
||||||
|
{
|
||||||
|
for(AssetLocation model : manager.gatherAssets("models", 512, this::isValidModel))
|
||||||
|
{
|
||||||
|
if(model.getLocation().endsWith(".json")) addModel(model, ModelLoader.readModelData(model, manager));
|
||||||
|
else if(model.getLocation().endsWith(".spm")) addModel(model, ModelLoader.readLegacyModelData(model, manager));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void addModel(AssetLocation location, List<SimpleModelData> data)
|
||||||
|
{
|
||||||
|
if(data.isEmpty())
|
||||||
|
{
|
||||||
|
System.out.println("["+location+"]Found Empty Model Data");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
models.put(location, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean isValidModel(String fileName)
|
||||||
|
{
|
||||||
|
return fileName.endsWith(".json") || fileName.endsWith(".spm");
|
||||||
|
}
|
||||||
|
|
||||||
|
public SimpleModelData getModel(AssetLocation location)
|
||||||
|
{
|
||||||
|
List<SimpleModelData> data = models.get(location);
|
||||||
|
return data == null ? null : data.get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<SimpleModelData> getModels(AssetLocation location)
|
||||||
|
{
|
||||||
|
return models.get(location);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MergedModelData getMergedModel(AssetLocation location)
|
||||||
|
{
|
||||||
|
return getMergedModel(location, "MergedModel");
|
||||||
|
}
|
||||||
|
|
||||||
|
public MergedModelData getMergedModel(AssetLocation location, String newName)
|
||||||
|
{
|
||||||
|
List<SimpleModelData> data = models.get(location);
|
||||||
|
return data == null ? null : MergedModelData.merge(newName, data);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
package speiger.src.coreengine.rendering.models.loader;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import speiger.src.collections.bytes.lists.ByteArrayList;
|
||||||
|
import speiger.src.collections.bytes.lists.ByteList;
|
||||||
|
import speiger.src.collections.ints.lists.IntArrayList;
|
||||||
|
import speiger.src.collections.ints.lists.IntList;
|
||||||
|
|
||||||
|
public class MergedModelData extends SimpleModelData
|
||||||
|
{
|
||||||
|
int[] indexes;
|
||||||
|
|
||||||
|
protected MergedModelData(String name, byte[] data, int[] indecies, int[] indexes)
|
||||||
|
{
|
||||||
|
super(name, null, data, indecies);
|
||||||
|
this.indexes = indexes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int[] getVertexOffsets()
|
||||||
|
{
|
||||||
|
return indexes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getVertexCount(int index)
|
||||||
|
{
|
||||||
|
return indexes[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MergedModelData merge(String newName, List<SimpleModelData> data)
|
||||||
|
{
|
||||||
|
return merge(newName, 28, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MergedModelData merge(String newName, int vertexBytes, List<SimpleModelData> data)
|
||||||
|
{
|
||||||
|
System.out.println("Test: "+data.size()+", Name="+newName);
|
||||||
|
ByteList byteData = new ByteArrayList();
|
||||||
|
IntList indeciesData = new IntArrayList();
|
||||||
|
int[] offsets = new int[data.size() * 2];
|
||||||
|
int offset = 0;
|
||||||
|
int indeciesOffset = 0;
|
||||||
|
for(int i = 0,m=data.size();i<m;i++)
|
||||||
|
{
|
||||||
|
offset = byteData.size() / vertexBytes;
|
||||||
|
byteData.addAll(data.get(i).getModelData());
|
||||||
|
int[] indexes = data.get(i).getIndecies();
|
||||||
|
offsets[(i * 2) + 1] = indeciesOffset * 4;
|
||||||
|
offsets[i * 2] = indexes.length;
|
||||||
|
indeciesOffset += indexes.length;
|
||||||
|
for(int x = 0,n=indexes.length;x<n;x++)
|
||||||
|
{
|
||||||
|
indeciesData.add(indexes[x] + offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new MergedModelData(newName, byteData.toByteArray(), indeciesData.toIntArray(), offsets);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,103 @@
|
||||||
|
package speiger.src.coreengine.rendering.models.loader;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
|
||||||
|
import speiger.src.collections.objects.lists.ObjectArrayList;
|
||||||
|
import speiger.src.collections.objects.utils.ObjectLists;
|
||||||
|
import speiger.src.coreengine.assets.AssetLocation;
|
||||||
|
import speiger.src.coreengine.assets.AssetManager;
|
||||||
|
import speiger.src.coreengine.assets.IAsset;
|
||||||
|
import speiger.src.coreengine.math.misc.ColorObject;
|
||||||
|
import speiger.src.coreengine.utils.collections.iterators.IterableWrapper;
|
||||||
|
import speiger.src.coreengine.utils.helpers.JsonUtil;
|
||||||
|
|
||||||
|
public class ModelLoader
|
||||||
|
{
|
||||||
|
|
||||||
|
public static List<SimpleModelData> readModelData(AssetLocation location, AssetManager manager)
|
||||||
|
{
|
||||||
|
try(IAsset asset = manager.getAsset(location))
|
||||||
|
{
|
||||||
|
List<SimpleModelData> result = new ObjectArrayList<>();
|
||||||
|
JsonObject obj = asset.getJsonObject();
|
||||||
|
JsonUtil.iterate(obj.get("models"), T -> {
|
||||||
|
JsonObject info = T.getAsJsonObject("info");
|
||||||
|
JsonObject format = T.getAsJsonObject("format");
|
||||||
|
JsonObject data = T.getAsJsonObject("data");
|
||||||
|
List<VertexEntry> entries = VertexLoader.loadVertexFormat(format);
|
||||||
|
ByteBuffer buffer = VertexLoader.parseVertexData(data, info.get("vertecies").getAsInt(), entries, true);
|
||||||
|
result.add(new SimpleModelData(info.get("name").getAsString(), UUID.fromString(info.get("id").getAsString()), buffer.array(), JsonUtil.parseIntArray(data.getAsJsonArray("indecies"))));
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return ObjectLists.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<SimpleModelData> readLegacyModelData(AssetLocation location, AssetManager manager)
|
||||||
|
{
|
||||||
|
List<SimpleModelData> resultModels = new ObjectArrayList<SimpleModelData>();
|
||||||
|
ByteBuffer buffer = null;
|
||||||
|
int[] indexes = null;
|
||||||
|
String currentName = null;
|
||||||
|
try(IAsset asset = manager.getAsset(location))
|
||||||
|
{
|
||||||
|
boolean flag = false;
|
||||||
|
for(String line : IterableWrapper.wrap(asset.getStringReader()))
|
||||||
|
{
|
||||||
|
if(line.startsWith("{"))
|
||||||
|
{
|
||||||
|
if(currentName != null)
|
||||||
|
{
|
||||||
|
resultModels.add(new SimpleModelData(currentName, null, buffer.array(), indexes));
|
||||||
|
currentName = null;
|
||||||
|
}
|
||||||
|
currentName = line.substring(1, line.length() - 1);
|
||||||
|
flag = true;
|
||||||
|
}
|
||||||
|
else if(flag)
|
||||||
|
{
|
||||||
|
flag = false;
|
||||||
|
String[] bounds = line.split(";");
|
||||||
|
buffer = ByteBuffer.allocate(Integer.parseInt(bounds[0]) * 28).order(ByteOrder.nativeOrder());
|
||||||
|
indexes = new int[Integer.parseInt(bounds[1])];
|
||||||
|
}
|
||||||
|
else if(line.startsWith("<"))
|
||||||
|
{
|
||||||
|
String[] data = line.substring(1, line.length() - 1).split(" ");
|
||||||
|
String[] position = data[0].split(";");
|
||||||
|
String[] normal = data[2].split(";");
|
||||||
|
buffer.putFloat(Float.parseFloat(position[0])).putFloat(Float.parseFloat(position[1])).putFloat(Float.parseFloat(position[2]));
|
||||||
|
ColorObject.pack(Integer.parseInt(data[1]), true, buffer);
|
||||||
|
buffer.putFloat(Float.parseFloat(normal[0])).putFloat(Float.parseFloat(normal[1])).putFloat(Float.parseFloat(normal[2]));
|
||||||
|
}
|
||||||
|
else if(line.startsWith("["))
|
||||||
|
{
|
||||||
|
String[] data = line.substring(1, line.length() - 1).split(";");
|
||||||
|
for(int j = 0;j<data.length;j++)
|
||||||
|
{
|
||||||
|
indexes[j] = Integer.parseInt(data[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(currentName != null)
|
||||||
|
{
|
||||||
|
resultModels.add(new SimpleModelData(currentName, null, buffer.array(), indexes));
|
||||||
|
currentName = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return resultModels;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
package speiger.src.coreengine.rendering.models.loader;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class SimpleModelData
|
||||||
|
{
|
||||||
|
String name;
|
||||||
|
UUID id;
|
||||||
|
byte[] data;
|
||||||
|
int[] indecies;
|
||||||
|
|
||||||
|
public SimpleModelData(String name, UUID id, byte[] data, int[] indecies)
|
||||||
|
{
|
||||||
|
this.name = name;
|
||||||
|
this.data = data;
|
||||||
|
this.indecies = indecies;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UUID getId()
|
||||||
|
{
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName()
|
||||||
|
{
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getModelData()
|
||||||
|
{
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int[] getIndecies()
|
||||||
|
{
|
||||||
|
return indecies;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getVertexCount()
|
||||||
|
{
|
||||||
|
return indecies.length;
|
||||||
|
}
|
||||||
|
}
|
|
@ -52,6 +52,18 @@ public class VertexEntry
|
||||||
return optional;
|
return optional;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int caculateByteSize(List<VertexEntry> array, boolean excludeOptional)
|
||||||
|
{
|
||||||
|
int result = 0;
|
||||||
|
for(int i = 0,m=array.size();i<m;i++)
|
||||||
|
{
|
||||||
|
VertexEntry entry = array.get(i);
|
||||||
|
if(entry.isOptional() && excludeOptional) continue;
|
||||||
|
result += entry.getSize() * entry.getType().getByteSize();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
public static int calculateStride(List<VertexEntry> array, boolean excludeOptional)
|
public static int calculateStride(List<VertexEntry> array, boolean excludeOptional)
|
||||||
{
|
{
|
||||||
return excludeOptional ? calculateNonOptionalStride(array) : caclulateStride(array);
|
return excludeOptional ? calculateNonOptionalStride(array) : caclulateStride(array);
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package speiger.src.coreengine.rendering.models.loader;
|
package speiger.src.coreengine.rendering.models.loader;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
|
@ -21,7 +22,7 @@ public class VertexLoader
|
||||||
public static ByteBuffer parseVertexData(JsonObject obj, int vertexCount, List<VertexEntry> entries, boolean excludeOptional)
|
public static ByteBuffer parseVertexData(JsonObject obj, int vertexCount, List<VertexEntry> entries, boolean excludeOptional)
|
||||||
{
|
{
|
||||||
List<Number> numbers = parseVertexData(obj, entries, excludeOptional);
|
List<Number> numbers = parseVertexData(obj, entries, excludeOptional);
|
||||||
ByteBuffer buffer = ByteBuffer.allocate(vertexCount * VertexEntry.calculateStride(entries, excludeOptional));
|
ByteBuffer buffer = ByteBuffer.allocate(vertexCount * VertexEntry.caculateByteSize(entries, excludeOptional)).order(ByteOrder.nativeOrder());
|
||||||
for(int i = 0,offset=0,m=vertexCount*entries.size();i<m;i++)
|
for(int i = 0,offset=0,m=vertexCount*entries.size();i<m;i++)
|
||||||
{
|
{
|
||||||
VertexEntry entry = entries.get(i % entries.size());
|
VertexEntry entry = entries.get(i % entries.size());
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
package speiger.src.coreengine.rendering.textures.custom;
|
||||||
|
|
||||||
|
import speiger.src.coreengine.rendering.textures.base.ITexture;
|
||||||
|
|
||||||
|
public interface IDynamicTexture extends ITexture
|
||||||
|
{
|
||||||
|
public void markDirty(int x, int z);
|
||||||
|
public default void markDirty(int index) { markDirty(index % getWidth(), index / getWidth()); }
|
||||||
|
|
||||||
|
public default void setData(int x, int z, int value) { setData((z * getWidth()) + x, value); }
|
||||||
|
public void setData(int index, int value);
|
||||||
|
|
||||||
|
public default void setRGB(int x, int z, int red, int green, int blue, int alpha) { setRGB((z * getWidth()) + x, red, green, blue, alpha); }
|
||||||
|
public default void setRGB(int index, int red, int green, int blue, int alpha) { setData(index, ((alpha & 0xFF) << 24) | ((red & 0xFF) << 16) | ((green & 0xFF) << 8) | (blue & 0xFF)); }
|
||||||
|
|
||||||
|
public default void setRed(int x, int z, int red) { setRed((z * getWidth()) + x, red); }
|
||||||
|
public void setRed(int index, int red);
|
||||||
|
public default void setGreen(int x, int z, int green) { setGreen((z * getWidth()) + x, green); }
|
||||||
|
public void setGreen(int index, int green);
|
||||||
|
public default void setBlue(int x, int z, int blue) { setBlue((z * getWidth()) + x, blue); }
|
||||||
|
public void setBlue(int index, int blue);
|
||||||
|
public default void setAlpha(int x, int z, int alpha) { setAlpha((z * getWidth()) + x, alpha); }
|
||||||
|
public void setAlpha(int index, int alpha);
|
||||||
|
|
||||||
|
public default int getRGB(int x, int z) { return getRGB((z * getWidth()) + x); }
|
||||||
|
public int getRGB(int index);
|
||||||
|
|
||||||
|
public default int getRed(int x, int z) { return getRed((z * getWidth()) + x); }
|
||||||
|
public int getRed(int index);
|
||||||
|
public default int getGreen(int x, int z) { return getGreen((z * getWidth()) + x); }
|
||||||
|
public int getGreen(int index);
|
||||||
|
public default int getBlue(int x, int z) { return getBlue((z * getWidth()) + x); }
|
||||||
|
public int getBlue(int index);
|
||||||
|
public default int getAlpha(int x, int z) { return getAlpha((z * getWidth()) + x); }
|
||||||
|
public int getAlpha(int index);
|
||||||
|
|
||||||
|
public boolean isDirty();
|
||||||
|
public void processChanges(boolean full);
|
||||||
|
}
|
|
@ -13,7 +13,6 @@ import speiger.src.collections.objects.sets.ObjectOpenHashSet;
|
||||||
import speiger.src.collections.objects.utils.ObjectIterators;
|
import speiger.src.collections.objects.utils.ObjectIterators;
|
||||||
import speiger.src.coreengine.assets.AssetLocation;
|
import speiger.src.coreengine.assets.AssetLocation;
|
||||||
import speiger.src.coreengine.math.vector.ints.Vec2i;
|
import speiger.src.coreengine.math.vector.ints.Vec2i;
|
||||||
import speiger.src.coreengine.rendering.textures.custom.TextureAtlas;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inspired by: <a href=https://github.com/lukaszdk/texture-atlas-generator/blob/master/AtlasGenerator.java>AtlasGenerator</a>
|
* Inspired by: <a href=https://github.com/lukaszdk/texture-atlas-generator/blob/master/AtlasGenerator.java>AtlasGenerator</a>
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package speiger.src.coreengine.rendering.textures.custom;
|
package speiger.src.coreengine.rendering.textures.normal;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
|
||||||
import org.lwjgl.opengl.GL11;
|
import org.lwjgl.opengl.GL11;
|
||||||
|
@ -8,7 +9,7 @@ import org.lwjgl.system.MemoryStack;
|
||||||
import org.lwjgl.system.MemoryUtil;
|
import org.lwjgl.system.MemoryUtil;
|
||||||
|
|
||||||
import speiger.src.collections.ints.collections.IntIterator;
|
import speiger.src.collections.ints.collections.IntIterator;
|
||||||
import speiger.src.collections.ints.maps.impl.hash.Int2ObjectOpenHashMap;
|
import speiger.src.collections.ints.maps.impl.hash.Int2ObjectLinkedOpenHashMap;
|
||||||
import speiger.src.collections.ints.maps.interfaces.Int2ObjectMap;
|
import speiger.src.collections.ints.maps.interfaces.Int2ObjectMap;
|
||||||
import speiger.src.collections.ints.maps.interfaces.Int2ObjectMap.Entry;
|
import speiger.src.collections.ints.maps.interfaces.Int2ObjectMap.Entry;
|
||||||
import speiger.src.collections.ints.sets.IntOpenHashSet;
|
import speiger.src.collections.ints.sets.IntOpenHashSet;
|
||||||
|
@ -18,15 +19,19 @@ import speiger.src.collections.utils.ITrimmable;
|
||||||
import speiger.src.coreengine.math.BitUtil;
|
import speiger.src.coreengine.math.BitUtil;
|
||||||
import speiger.src.coreengine.rendering.textures.base.AbstractTexture;
|
import speiger.src.coreengine.rendering.textures.base.AbstractTexture;
|
||||||
import speiger.src.coreengine.rendering.textures.base.TextureManager;
|
import speiger.src.coreengine.rendering.textures.base.TextureManager;
|
||||||
|
import speiger.src.coreengine.rendering.textures.custom.IDynamicTexture;
|
||||||
import speiger.src.coreengine.rendering.utils.AllocationTracker;
|
import speiger.src.coreengine.rendering.utils.AllocationTracker;
|
||||||
|
|
||||||
public class DynamicTexture extends AbstractTexture
|
public class DynamicTexture extends AbstractTexture implements IDynamicTexture
|
||||||
{
|
{
|
||||||
Int2ObjectMap<IntSet> dirtyChunks = new Int2ObjectOpenHashMap<IntSet>();
|
public static final int R = 0xFF << 16;
|
||||||
|
public static final int G = 0xFF << 8;
|
||||||
|
public static final int B = 0xFF;
|
||||||
|
public static final int A = 0xFF << 24;
|
||||||
|
Int2ObjectMap<IntSet> dirtyChunks = new Int2ObjectLinkedOpenHashMap<IntSet>();
|
||||||
int[] data;
|
int[] data;
|
||||||
int width;
|
int width;
|
||||||
int height;
|
int height;
|
||||||
boolean first = true;
|
|
||||||
|
|
||||||
public DynamicTexture(int width, int height)
|
public DynamicTexture(int width, int height)
|
||||||
{
|
{
|
||||||
|
@ -36,11 +41,19 @@ public class DynamicTexture extends AbstractTexture
|
||||||
data = new int[width * height];
|
data = new int[width * height];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DynamicTexture(int width, int height, int defaultValue)
|
||||||
|
{
|
||||||
|
this(width, height);
|
||||||
|
Arrays.fill(data, defaultValue);
|
||||||
|
processChanges(true);
|
||||||
|
}
|
||||||
|
|
||||||
public int[] getTextureData()
|
public int[] getTextureData()
|
||||||
{
|
{
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void markDirty(int x, int z)
|
public void markDirty(int x, int z)
|
||||||
{
|
{
|
||||||
int chunkIndex = BitUtil.toInt(x >> 4, z >> 4);
|
int chunkIndex = BitUtil.toInt(x >> 4, z >> 4);
|
||||||
|
@ -50,23 +63,88 @@ public class DynamicTexture extends AbstractTexture
|
||||||
set = new IntOpenHashSet();
|
set = new IntOpenHashSet();
|
||||||
dirtyChunks.put(chunkIndex, set);
|
dirtyChunks.put(chunkIndex, set);
|
||||||
}
|
}
|
||||||
set.add(BitUtil.toInt(x, z));
|
set.add((x & 15) << 4 | (z & 15));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setData(int x, int z, int value)
|
@Override
|
||||||
|
public void setData(int index, int value)
|
||||||
{
|
{
|
||||||
data[(z * width) + x] = value;
|
data[index] = value;
|
||||||
markDirty(x, z);
|
markDirty(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setRed(int index, int red)
|
||||||
|
{
|
||||||
|
if(getRed(index) == red) return;
|
||||||
|
data[index] = (data[index] & ~R) | (red & 0xFF) << 16;
|
||||||
|
markDirty(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasTasks()
|
@Override
|
||||||
|
public void setGreen(int index, int green)
|
||||||
{
|
{
|
||||||
return dirtyChunks.size() > 0 || first;
|
if(getGreen(index) == green) return;
|
||||||
|
data[index] = (data[index] & ~G) | (green & 0xFF) << 8;
|
||||||
|
markDirty(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setBlue(int index, int blue)
|
||||||
|
{
|
||||||
|
if(getBlue(index) == blue) return;
|
||||||
|
data[index] = (data[index] & ~B) | (blue & 0xFF);
|
||||||
|
markDirty(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAlpha(int index, int alpha)
|
||||||
|
{
|
||||||
|
if(getAlpha(index) == alpha) return;
|
||||||
|
data[index] = (data[index] & ~A) | (alpha & 0xFF) << 24;
|
||||||
|
markDirty(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateData()
|
@Override
|
||||||
|
public int getRGB(int index)
|
||||||
{
|
{
|
||||||
if(first)
|
return data[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getRed(int index)
|
||||||
|
{
|
||||||
|
return (data[index] >> 16) & 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getGreen(int index)
|
||||||
|
{
|
||||||
|
return (data[index] >> 8) & 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getBlue(int index)
|
||||||
|
{
|
||||||
|
return data[index] & 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getAlpha(int index)
|
||||||
|
{
|
||||||
|
return (data[index] >> 24) & 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDirty()
|
||||||
|
{
|
||||||
|
return dirtyChunks.size() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void processChanges(boolean full)
|
||||||
|
{
|
||||||
|
if(full)
|
||||||
{
|
{
|
||||||
ByteBuffer buffer = MemoryUtil.memAlloc(data.length * 4);
|
ByteBuffer buffer = MemoryUtil.memAlloc(data.length * 4);
|
||||||
for(int i = 0;i<data.length;i++)
|
for(int i = 0;i<data.length;i++)
|
||||||
|
@ -83,7 +161,6 @@ public class DynamicTexture extends AbstractTexture
|
||||||
GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);
|
GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);
|
||||||
AllocationTracker.INSTANCE.addGPUBytes(buffer.remaining());
|
AllocationTracker.INSTANCE.addGPUBytes(buffer.remaining());
|
||||||
GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, width, height, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, buffer);
|
GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, width, height, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, buffer);
|
||||||
first = false;
|
|
||||||
MemoryUtil.memFree(buffer);
|
MemoryUtil.memFree(buffer);
|
||||||
dirtyChunks.clear();
|
dirtyChunks.clear();
|
||||||
}
|
}
|
||||||
|
@ -102,8 +179,8 @@ public class DynamicTexture extends AbstractTexture
|
||||||
for(IntIterator subIt = values.getValue().iterator();subIt.hasNext();)
|
for(IntIterator subIt = values.getValue().iterator();subIt.hasNext();)
|
||||||
{
|
{
|
||||||
int index = subIt.nextInt();
|
int index = subIt.nextInt();
|
||||||
width = Math.max(width, BitUtil.toFirstShort(index) - chunkX + 1);
|
width = Math.max(width, ((index >> 4) & 0xF) + 1);
|
||||||
height = Math.max(height, BitUtil.toSecondShort(index) - chunkZ + 1);
|
height = Math.max(height, (index & 0xF) + 1);
|
||||||
}
|
}
|
||||||
try(MemoryStack stack = MemoryStack.stackPush())
|
try(MemoryStack stack = MemoryStack.stackPush())
|
||||||
{
|
{
|
||||||
|
@ -137,9 +214,7 @@ public class DynamicTexture extends AbstractTexture
|
||||||
int old = getTextureID();
|
int old = getTextureID();
|
||||||
setTextureID(GL11.glGenTextures());
|
setTextureID(GL11.glGenTextures());
|
||||||
TextureManager.INSTANCE.removeTexture(old);
|
TextureManager.INSTANCE.removeTexture(old);
|
||||||
dirtyChunks.clear();
|
processChanges(true);
|
||||||
first = true;
|
|
||||||
updateData();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Before Width: | Height: | Size: 186 KiB After Width: | Height: | Size: 1.0 MiB |
Loading…
Reference in New Issue