Progress on more rewrites

This commit is contained in:
Speiger 2026-06-13 03:55:20 +02:00
parent 340d8ff463
commit 396d4f2232
144 changed files with 5657 additions and 4997 deletions

View File

@ -24,6 +24,18 @@
<attribute name="gradle_used_by_scope" value="graphics"/> <attribute name="gradle_used_by_scope" value="graphics"/>
</attributes> </attributes>
</classpathentry> </classpathentry>
<classpathentry kind="src" output="bin/math" path="src/math/java">
<attributes>
<attribute name="gradle_scope" value="math"/>
<attribute name="gradle_used_by_scope" value="main,graphics,math"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="bin/assets" path="src/assets/java">
<attributes>
<attribute name="gradle_scope" value="assets"/>
<attribute name="gradle_used_by_scope" value="assets"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-25/"/> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-25/"/>
<classpathentry kind="con" path="org.eclipse.buildship.core.gradleclasspathcontainer"/> <classpathentry kind="con" path="org.eclipse.buildship.core.gradleclasspathcontainer"/>
<classpathentry kind="output" path="bin/default"/> <classpathentry kind="output" path="bin/default"/>

View File

@ -16,12 +16,31 @@ eclipse {
} }
sourceSets { sourceSets {
graphics {} math {
java {}
}
assets {
java {}
}
graphics {
java {}
}
main {
compileClasspath += sourceSets.math.output
runtimeClasspath += sourceSets.math.output
}
graphics {
compileClasspath += sourceSets.math.output
runtimeClasspath += sourceSets.math.output
java {}
}
} }
configurations { configurations {
graphics.extendsFrom implementation graphics.extendsFrom implementation
graphics.extendsFrom runtime graphics.extendsFrom runtime
graphics.extendsFrom mathRuntime
implementation.extendsFrom mathRuntime
} }
repositories { repositories {
@ -64,6 +83,7 @@ dependencies {
//Primitive Collections //Primitive Collections
implementation 'de.speiger:Primitive-Collections:1.0.0' implementation 'de.speiger:Primitive-Collections:1.0.0'
mathImplementation 'de.speiger:Primitive-Collections:1.0.0'
} }
jar { jar {

View File

@ -0,0 +1,14 @@
package speiger.src.coreengine.assets.api;
import java.io.IOException;
import java.io.InputStream;
public interface IAsset {
public IAssetPackage owner();
public ID location();
public String hash();
public InputStream stream() throws IOException;
public <T> T parse(IAssetParser<T> parser) throws IOException;
}

View File

@ -0,0 +1,5 @@
package speiger.src.coreengine.assets.api;
public interface IAssetPackage {
}

View File

@ -0,0 +1,8 @@
package speiger.src.coreengine.assets.api;
import java.io.IOException;
import java.nio.file.Path;
public interface IAssetParser<T> {
public T parse(Path path) throws IOException;
}

View File

@ -0,0 +1,6 @@
package speiger.src.coreengine.assets.api;
public interface IAssetProvider {
public IAsset get(ID id);
public String hash(ID id);
}

View File

@ -0,0 +1,79 @@
package speiger.src.coreengine.assets.api;
import java.util.Objects;
public record ID(String domain, String path) implements Comparable<ID> {
public ID {
Objects.requireNonNull(domain);
Objects.requireNonNull(path);
if(!isValidDomain(domain)) throw new IllegalArgumentException("Non [a-zA-Z0-9_.-] Character found in domain of location ["+domain+":"+path+"]");
if(!isValidPath(path)) throw new IllegalArgumentException("Non [a-zA-Z0-9/_.-] Character found in path of location ["+domain+":"+path+"]");
}
public ID prefix(String prefix) { return of(domain, prefix+"/"+path); }
public ID suffix(String suffix) { return of(domain, path+"/"+suffix); }
public ID alternate(String alterversion) { return of(domain, path+"."+alterversion); }
public String fileLocation() { return "assets/"+domain+"/"+path; }
public boolean isRoot() { return !path.contains("/"); }
public boolean isRootFolder(String folder) { return path.indexOf('/', folder.length()+1) < 0; }
public boolean endsWith(String suffix) { return path.endsWith(suffix); }
@Override
public final String toString() {
return domain+":"+path;
}
@Override
public int compareTo(ID o) {
int result = domain.compareToIgnoreCase(o.domain);
return result != 0 ? result : path.compareToIgnoreCase(path);
}
public boolean matches(ID id) {
return id.domain.equals(domain) && id.path.equals(path);
}
public static ID of(String domain, String path) {
return new ID((domain == null || domain.isBlank() ? "base" : domain), path);
}
public static ID of(String location) {
Objects.requireNonNull(location);
int index = location.indexOf(":");
String domain = location.substring(0, index);
String path = location.substring(index + 1);
if(!isValidDomain(domain)) throw new IllegalArgumentException("Non [a-zA-Z0-9_.-] Character found in domain of location ["+domain+":"+path+"]");
if(!isValidPath(path)) throw new IllegalArgumentException("Non [a-zA-Z0-9/_.-] Character found in path of location ["+domain+":"+path+"]");
return new ID(domain, path);
}
public static final ID tryOf(String location) {
try { return of(location); }
catch(Exception e) {}
return null;
}
private static boolean isValidDomain(String s) {
for(int i = 0,m=s.length();i<m;i++) {
if(!isValidDomainChar(s.charAt(i))) return false;
}
return true;
}
private static boolean isValidPath(String s) {
for(int i = 0,m=s.length();i<m;i++) {
if(!isValidPathChar(s.charAt(i))) return false;
}
return true;
}
private static boolean isValidPathChar(char c) {
return c == '/' || isValidDomainChar(c);
}
private static boolean isValidDomainChar(char c) {
return c == '_' || c == '-' || c == '.' || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9');
}
}

View File

@ -0,0 +1,54 @@
package speiger.src.coreengine.assets.api;
import java.io.IOException;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Supplier;
import speiger.src.collections.ints.functions.consumer.IntObjectConsumer;
import speiger.src.collections.objects.collections.ObjectIterable;
import speiger.src.collections.objects.collections.ObjectIterator;
import speiger.src.collections.objects.functions.consumer.ObjectObjectConsumer;
import speiger.src.collections.objects.lists.ObjectArrayList;
import speiger.src.collections.objects.lists.ObjectList;
public record MultiAsset(ObjectList<IAsset> assets) implements ObjectIterable<IAsset> {
public MultiAsset(ObjectList<IAsset> assets) {
this.assets = Objects.requireNonNull(assets).unmodifiable();
}
public MultiAsset(IAsset... assets) {
this(ObjectArrayList.wrap(assets));
}
public int size() { return assets.size(); }
public IAsset get(int index) { return assets.get(index); }
@Override
public ObjectIterator<IAsset> iterator() { return assets.iterator(); }
public <T> ObjectIterable<T> map(IAssetParser<T> mapper, Supplier<T> defaultValue) {
return assets.map(E -> {
try { return E.parse(mapper); }
catch(IOException e) {
e.printStackTrace();
return defaultValue.get();
}
});
}
@Override
public void forEach(Consumer<? super IAsset> action) {
assets.forEach(action);
}
@Override
public <E> void forEach(E input, ObjectObjectConsumer<E, IAsset> action) {
assets.forEach(input, action);
}
@Override
public void forEachIndexed(IntObjectConsumer<IAsset> action) {
assets.forEachIndexed(action);
}
}

View File

@ -0,0 +1,7 @@
package speiger.src.coreengine.graphics.api.buffer.states;
public enum IndeciesType {
BYTE,
SHORT,
INT;
}

View File

@ -1,5 +1,7 @@
package speiger.src.coreengine.graphics.api.core; package speiger.src.coreengine.graphics.api.core;
import speiger.src.coreengine.graphics.api.shader.RenderPass;
import speiger.src.coreengine.graphics.api.target.RenderTarget;
import speiger.src.coreengine.graphics.api.texture.Texture; import speiger.src.coreengine.graphics.api.texture.Texture;
import speiger.src.coreengine.graphics.api.utils.PushableResource; import speiger.src.coreengine.graphics.api.utils.PushableResource;
import speiger.src.coreengine.math.vector.floats.Vec4f; import speiger.src.coreengine.math.vector.floats.Vec4f;
@ -7,11 +9,26 @@ import speiger.src.coreengine.math.vector.floats.Vec4f;
public interface GraphicsCommandQueue { public interface GraphicsCommandQueue {
public static final int CLEAR_COLOR = 1; public static final int CLEAR_COLOR = 1;
public static final int CLEAR_DEPTH = 2; public static final int CLEAR_DEPTH = 2;
public PushableResource pushClearColor(Vec4f color); public PushableResource putClearColor(Vec4f color);
public PushableResource pushClearDepth(double value); public PushableResource putClearDepth(double value);
public PushableResource putRenderTarget(RenderTarget target);
public void clearTexture(int clearParam);
public void clearTexture(int x, int y, int width, int height, int clearParam);
public void clearTexture(Texture texture, int clearParam); public void clearTexture(Texture texture, int clearParam);
public void clearTexture(Texture texture, int x, int y, int width, int height, int clearParam); public void clearTexture(Texture texture, int x, int y, int width, int height, int clearParam);
public void writeToTexture(Texture target, int x, int y, int width, int height, long source);
public void readFromTexture(Texture source, int x, int y, int width, int height, long target);
public RenderPass createRenderPass(RenderTarget target, DrawArea area);
public record DrawArea(int x, int y, int width, int height) {
public boolean fits(int x, int y, int width, int height) {
return x >= x() && y >= y() && x + width < width() && y + height < height();
}
public boolean fills(int width, int height) {
return x == 0 && y == 0 && width == width() && height == height();
}
}
} }

View File

@ -7,8 +7,10 @@ import speiger.src.coreengine.graphics.api.sampler.Sampler;
import speiger.src.coreengine.graphics.api.sampler.SamplerSettings; import speiger.src.coreengine.graphics.api.sampler.SamplerSettings;
import speiger.src.coreengine.graphics.api.texture.Texture; import speiger.src.coreengine.graphics.api.texture.Texture;
import speiger.src.coreengine.graphics.api.texture.TextureSettings; import speiger.src.coreengine.graphics.api.texture.TextureSettings;
import speiger.src.coreengine.rendering.input.window.Window;
public interface GraphicsDevice { public interface GraphicsDevice {
public Window getWindow();
public GraphicsSurface createSurface(); public GraphicsSurface createSurface();
public GraphicsCommandQueue getQueue(); public GraphicsCommandQueue getQueue();
public VertexBuffer createBuffer(BufferType type, BufferState state); public VertexBuffer createBuffer(BufferType type, BufferState state);

View File

@ -0,0 +1,5 @@
package speiger.src.coreengine.graphics.api.shader;
public interface CompiledPipeline {
}

View File

@ -0,0 +1,51 @@
package speiger.src.coreengine.graphics.api.shader;
import speiger.src.coreengine.graphics.api.buffer.VertexBuffer;
import speiger.src.coreengine.graphics.api.buffer.states.IndeciesType;
import speiger.src.coreengine.graphics.api.core.GraphicsCommandQueue.DrawArea;
import speiger.src.coreengine.graphics.api.sampler.Sampler;
import speiger.src.coreengine.graphics.api.texture.Texture;
import speiger.src.coreengine.graphics.api.utils.ScissorsManager;
public abstract class RenderPass implements AutoCloseable {
protected final DrawArea area;
protected final boolean hasColor;
protected final boolean hasDepth;
protected final ScissorsManager scissors = new ScissorsManager(16);
public RenderPass(DrawArea area, boolean hasColor, boolean hasDepth) {
this.area = area;
this.hasColor = hasColor;
this.hasDepth = hasDepth;
}
public void pushScissors(int x, int y, int width, int height) {
if(area != null && area.fits(x, y, width, height)) {
//TODO implement logging
return;
}
scissors.push(x, y, width, height);
}
public void popScissors() {
scissors.pop();
}
public abstract void setShader(ShaderPipeline pipeline);
public abstract void setTexture(String name, Texture texture, Sampler sampler);
public abstract void clearTextures();
public abstract void removeTexture(String name);
public abstract void setUniform(String name, VertexBuffer buffer);
public abstract void setIndecies(VertexBuffer buffer, IndeciesType type);
public abstract void clearIndecies();
public abstract void setVertexBuffer(int index, VertexBuffer buffer);
public DrawArea area() { return area; }
public boolean hasDepth() { return hasDepth; }
public boolean hasColor() { return hasColor; }
@Override
public abstract void close();
}

View File

@ -0,0 +1,4 @@
package speiger.src.coreengine.graphics.api.target;
public sealed interface RenderTarget permits ScreenTarget, TextureTarget {
}

View File

@ -0,0 +1,6 @@
package speiger.src.coreengine.graphics.api.target;
public final class ScreenTarget implements RenderTarget {
public static final ScreenTarget INSTANCE = new ScreenTarget();
private ScreenTarget() {}
}

View File

@ -0,0 +1,17 @@
package speiger.src.coreengine.graphics.api.target;
import speiger.src.coreengine.assets.AssetLocation;
import speiger.src.coreengine.graphics.api.texture.Texture;
import speiger.src.coreengine.graphics.api.texture.states.TextureType;
public record TextureTarget(AssetLocation id, Texture color, Texture depth) implements RenderTarget {
public TextureTarget {
if(color == null && depth == null) throw new IllegalArgumentException("At least either texture has to be nonNull");
if(color != null && depth != null) {
if(color.width() != depth.width()) throw new IllegalArgumentException("Width is not matching");
if(color.height() != depth.height()) throw new IllegalArgumentException("Height is not matching");
}
if(color != null && color.settings().type() != TextureType.TEXTURE_2D) throw new IllegalArgumentException("Color Texture has to be 2D");
if(depth != null && depth.settings().type() != TextureType.TEXTURE_2D) throw new IllegalArgumentException("Depth Texture has to be 2D");
}
}

View File

@ -6,7 +6,7 @@ public abstract class Texture implements GraphicsResource {
final TextureSettings settings; final TextureSettings settings;
int width; int width;
int height; int height;
public Texture(TextureSettings settings, int width, int height) { public Texture(TextureSettings settings, int width, int height) {
this.settings = settings; this.settings = settings;
this.width = width; this.width = width;

View File

@ -0,0 +1,52 @@
package speiger.src.coreengine.graphics.api.utils;
import org.lwjgl.opengl.GL11;
import speiger.src.collections.objects.lists.ObjectArrayList;
import speiger.src.collections.utils.Stack;
import speiger.src.coreengine.math.vector.ints.Vec4i;
public class ScissorsManager {
Stack<Vec4i> stack = new ObjectArrayList<>();
int limit;
public ScissorsManager(int limit) {
if(limit <= 0) throw new IllegalStateException("Limit is negative");
this.limit = limit;
}
public void push(int x, int y, int width, int height) {
if(stack.size() >= limit) {
//TODO implement logging
return;
}
if(stack.isEmpty()) {
stack.push(Vec4i.of(x, y, x + width, y + height));
GL11.glEnable(GL11.GL_SCISSOR_TEST);
GL11.glScissor(x, y, width, height);
return;
}
Vec4i top = stack.top();
stack.push(Vec4i.of(Math.max(x, top.x()), Math.max(y, top.y()), Math.min(x + width, top.z()), Math.min(y + height, top.w())));
}
public boolean contains(int x, int y, int width, int height) {
return stack.isEmpty() || contains(stack.top(), x, y, width, height);
}
protected boolean contains(Vec4i top, int x, int y, int width, int height) {
return x >= top.x() && y >= top.y() && x + width < top.z() && y + height < top.w();
}
public void pop() {
if(stack.isEmpty()) {
//TODO implement logging
return;
}
stack.pop();
}
public void clear() {
stack.clear();
}
}

View File

@ -0,0 +1,167 @@
package speiger.src.coreengine.graphics.opengl.core;
import java.util.function.Consumer;
import java.util.function.Supplier;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL30;
import org.lwjgl.opengl.GL45;
import speiger.src.coreengine.assets.AssetLocation;
import speiger.src.coreengine.graphics.api.core.GraphicsCommandQueue;
import speiger.src.coreengine.graphics.api.shader.RenderPass;
import speiger.src.coreengine.graphics.api.target.RenderTarget;
import speiger.src.coreengine.graphics.api.target.ScreenTarget;
import speiger.src.coreengine.graphics.api.target.TextureTarget;
import speiger.src.coreengine.graphics.api.texture.Texture;
import speiger.src.coreengine.graphics.api.utils.PushableResource;
import speiger.src.coreengine.graphics.opengl.shader.GLRenderPass;
import speiger.src.coreengine.graphics.opengl.texture.FrameBufferCache;
import speiger.src.coreengine.graphics.opengl.texture.GLTexture;
import speiger.src.coreengine.math.vector.floats.Vec4f;
import speiger.src.coreengine.rendering.input.window.Window;
public class GLCommandQueue implements GraphicsCommandQueue {
private static final int HAS_COLOR = 1;
private static final int HAS_DEPTH = 2;
private static final int HAS_BOTH = 3;
GLGraphicsDevice device;
FrameBufferCache fboCache = new FrameBufferCache();
GLRenderPass activePass;
RenderTarget renderTarget = ScreenTarget.INSTANCE;
Vec4f clearColor = Vec4f.mutable(0F, 0F, 0F, 1F);
double clearDepth = 0D;
public GLCommandQueue(GLGraphicsDevice device) {
this.device = device;
}
@Override
public PushableResource putClearColor(Vec4f color) {
return new PushableObject<>(clearColor.copyAsImmutable(), setClearColor(color), () -> clearColor, this::setClearColor);
}
@Override
public PushableResource putClearDepth(double value) {
return new PushableObject<>(clearDepth, setClearDepth(value), () -> clearDepth, this::setClearDepth);
}
@Override
public PushableResource putRenderTarget(RenderTarget target) {
return new PushableObject<>(renderTarget, setRenderTarget(target), () -> renderTarget, this::setRenderTarget);
}
private Vec4f setClearColor(Vec4f value) {
if(clearColor.equals(value)) return value;
clearColor.set(value);
GL11.glClearColor(value.x(), value.y(), value.y(), value.w());
return value;
}
private double setClearDepth(double value) {
if(Double.compare(clearDepth, value) == 0) return value;
clearDepth = value;
GL11.glClearDepth(value);
return value;
}
private RenderTarget setRenderTarget(RenderTarget target) {
if(this.renderTarget.equals(target)) return target;
this.renderTarget = target;
switch(target) {
case ScreenTarget _ -> {
GL30.glBindFramebuffer(GL30.GL_DRAW_FRAMEBUFFER, 0);
Window window = device.getWindow();
GL11.glViewport(0, 0, window.width(), window.height());
break;
}
case TextureTarget(AssetLocation id, Texture color, Texture depth) -> {
int fbo = fboCache.getOrCreateFBO(id);
if(color != null) GL45.glNamedFramebufferTexture(fbo, GL30.GL_COLOR_ATTACHMENT0, ((GLTexture)color).id(), 0);
if(depth != null) GL45.glNamedFramebufferTexture(fbo, GL30.GL_DEPTH_ATTACHMENT, ((GLTexture)depth).id(), 0);
GL30.glBindFramebuffer(GL30.GL_DRAW_FRAMEBUFFER, fbo);
if(color != null) GL11.glViewport(0, 0, color.width(), color.height());
else if(depth != null) GL11.glViewport(0, 0, depth.width(), depth.height());
break;
}
}
return target;
}
@Override
public void clearTexture(int clearParam) {
}
@Override
public void clearTexture(int x, int y, int width, int height, int clearParam) {
}
@Override
public void clearTexture(Texture texture, int clearParam) {
}
@Override
public void clearTexture(Texture texture, int x, int y, int width, int height, int clearParam) {
}
@Override
public void writeToTexture(Texture target, int x, int y, int width, int height, long source) {
}
@Override
public void readFromTexture(Texture source, int x, int y, int width, int height, long target) {
}
@Override
public RenderPass createRenderPass(RenderTarget target, DrawArea area) {
int width = 0;
int height = 0;
int hasState = 0;
int frameBuffer = switch(target) {
case ScreenTarget _ -> {
Window window = device.getWindow();
width = window.width();
height = window.height();
hasState = HAS_BOTH;
yield 0;
}
case TextureTarget(AssetLocation id, Texture color, Texture depth) -> {
int fbo = fboCache.getOrCreateFBO(id);
if(color != null) {
hasState |= HAS_COLOR;
GL45.glNamedFramebufferTexture(fbo, GL30.GL_COLOR_ATTACHMENT0, ((GLTexture)color).id(), 0);
}
if(depth != null) {
hasState |= HAS_DEPTH;
GL45.glNamedFramebufferTexture(fbo, GL30.GL_DEPTH_ATTACHMENT, ((GLTexture)depth).id(), 0);
}
if(color != null) {
width = color.width();
height = color.height();
}
else if(depth != null) {
width = depth.width();
height = depth.height();
}
yield fbo;
}
};
GL30.glBindFramebuffer(GL30.GL_DRAW_FRAMEBUFFER, frameBuffer);
GL11.glViewport(0, 0, width, height);
boolean scissors = area != null && !area.fills(width, height);
if(scissors) {
GL11.glEnable(GL11.GL_SCISSOR_TEST);
GL11.glScissor(area.x(), area.y(), area.width(), area.height());
}
return (activePass = new GLRenderPass(this, area, scissors, (hasState & HAS_COLOR) != 0, (hasState & HAS_DEPTH) != 0, frameBuffer));
}
private record PushableObject<T>(T original, T applying, Supplier<T> current, Consumer<T> apply) implements PushableResource {
@Override
public void close() {
if(current.get().equals(applying)) {
apply.accept(original);
}
}
}
}

View File

@ -9,36 +9,44 @@ import org.lwjgl.opengl.GL33;
import org.lwjgl.opengl.GL43; import org.lwjgl.opengl.GL43;
import org.lwjgl.opengl.GL45; import org.lwjgl.opengl.GL45;
import speiger.src.coreengine.assets.base.IAssetProvider;
import speiger.src.coreengine.graphics.api.buffer.states.BufferState; import speiger.src.coreengine.graphics.api.buffer.states.BufferState;
import speiger.src.coreengine.graphics.api.buffer.states.BufferType; import speiger.src.coreengine.graphics.api.buffer.states.BufferType;
import speiger.src.coreengine.graphics.api.core.GraphicsCommandQueue;
import speiger.src.coreengine.graphics.api.core.GraphicsDevice; import speiger.src.coreengine.graphics.api.core.GraphicsDevice;
import speiger.src.coreengine.graphics.api.core.GraphicsSurface;
import speiger.src.coreengine.graphics.api.sampler.SamplerSettings; import speiger.src.coreengine.graphics.api.sampler.SamplerSettings;
import speiger.src.coreengine.graphics.api.shader.ShaderPipeline;
import speiger.src.coreengine.graphics.api.texture.TextureSettings; import speiger.src.coreengine.graphics.api.texture.TextureSettings;
import speiger.src.coreengine.graphics.api.texture.states.SwizzleMask; import speiger.src.coreengine.graphics.api.texture.states.SwizzleMask;
import speiger.src.coreengine.graphics.opengl.buffer.GLVertexBuffer; import speiger.src.coreengine.graphics.opengl.buffer.GLVertexBuffer;
import speiger.src.coreengine.graphics.opengl.sampler.GLSampler; import speiger.src.coreengine.graphics.opengl.sampler.GLSampler;
import speiger.src.coreengine.graphics.opengl.shader.ShaderInstance;
import speiger.src.coreengine.graphics.opengl.texture.GLTexture; import speiger.src.coreengine.graphics.opengl.texture.GLTexture;
import speiger.src.coreengine.graphics.opengl.utils.GLFunctions; import speiger.src.coreengine.graphics.opengl.utils.GLFunctions;
import speiger.src.coreengine.graphics.opengl.utils.GLUtils; import speiger.src.coreengine.graphics.opengl.utils.GLUtils;
import speiger.src.coreengine.rendering.input.window.Window; import speiger.src.coreengine.rendering.input.window.Window;
public class GLGraphicsDevice implements GraphicsDevice { public class GLGraphicsDevice implements GraphicsDevice {
GLCommandQueue queue;
Window owner; Window owner;
public GLGraphicsDevice(Window owner) { public GLGraphicsDevice(Window owner) {
this.owner = owner; this.owner = owner;
this.queue = new GLCommandQueue(this);
} }
@Override @Override
public GraphicsSurface createSurface() { public Window getWindow() {
return owner;
}
@Override
public GLSurface createSurface() {
return new GLSurface(owner); return new GLSurface(owner);
} }
@Override @Override
public GraphicsCommandQueue getQueue() { public GLCommandQueue getQueue() {
return null; return queue;
} }
@Override @Override
@ -76,4 +84,10 @@ public class GLGraphicsDevice implements GraphicsDevice {
public GLSampler createSampler(SamplerSettings settings) { public GLSampler createSampler(SamplerSettings settings) {
return new GLSampler(Objects.requireNonNull(settings)); return new GLSampler(Objects.requireNonNull(settings));
} }
public ShaderInstance createShader(ShaderPipeline line, IAssetProvider provider) {
return null;
}
} }

View File

@ -0,0 +1,100 @@
package speiger.src.coreengine.graphics.opengl.shader;
import java.util.Map;
import java.util.Objects;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL45;
import speiger.src.collections.objects.maps.interfaces.Object2ObjectMap;
import speiger.src.collections.objects.misc.pairs.ObjectObjectPair;
import speiger.src.coreengine.graphics.api.buffer.VertexBuffer;
import speiger.src.coreengine.graphics.api.buffer.states.IndeciesType;
import speiger.src.coreengine.graphics.api.core.GraphicsCommandQueue.DrawArea;
import speiger.src.coreengine.graphics.api.sampler.Sampler;
import speiger.src.coreengine.graphics.api.shader.CompiledPipeline;
import speiger.src.coreengine.graphics.api.shader.RenderPass;
import speiger.src.coreengine.graphics.api.shader.ShaderPipeline;
import speiger.src.coreengine.graphics.api.texture.Texture;
import speiger.src.coreengine.graphics.opengl.core.GLCommandQueue;
public class GLRenderPass extends RenderPass {
boolean scissors;
GLCommandQueue queue;
int fbo;
VertexBuffer[] buffers = new VertexBuffer[4];
Map<String, ObjectObjectPair<Texture, Sampler>> textures = Object2ObjectMap.builder().linkedMap();
Map<String, VertexBuffer> uniforms = Object2ObjectMap.builder().linkedMap();
VertexBuffer indecies;
IndeciesType indeciesType;
ShaderPipeline pipeline;
CompiledPipeline compiled;
public GLRenderPass(GLCommandQueue queue, DrawArea area, boolean scissors, boolean hasColor, boolean hasDepth, int fbo) {
super(area, hasColor, hasDepth);
this.scissors = scissors;
this.queue = queue;
this.fbo = fbo;
}
@Override
public void setShader(ShaderPipeline pipeline) {
this.pipeline = Objects.requireNonNull(pipeline);
}
@Override
public void setTexture(String name, Texture texture, Sampler sampler) {
Objects.requireNonNull(name, "Sampler Name is needed");
Objects.requireNonNull(texture, "Texture is required");
Objects.requireNonNull(sampler, "Sampler is required");
textures.put(name, ObjectObjectPair.of(texture, sampler));
}
@Override
public void clearTextures() {
textures.clear();
}
@Override
public void removeTexture(String name) {
Objects.requireNonNull(name, "Sampler Name is needed");
textures.remove(name);
}
@Override
public void setUniform(String name, VertexBuffer buffer) {
Objects.requireNonNull(name, "Uniform name is needed");
Objects.requireNonNull(buffer, "Vertex Buffer is required");
uniforms.put(name, buffer);
}
@Override
public void setIndecies(VertexBuffer buffer, IndeciesType type) {
indecies = Objects.requireNonNull(buffer, "Buffer is required");
indeciesType = Objects.requireNonNull(type, "Type is required");
}
@Override
public void clearIndecies() {
indecies = null;
indeciesType = null;
}
@Override
public void setVertexBuffer(int index, VertexBuffer buffer) {
if(index < 0 || index >= 4) throw new ArrayIndexOutOfBoundsException(index);
buffers[index] = buffer;
}
public void applyState() {
}
@Override
public void close() {
if(fbo == -1) return;
if(scissors) GL11.glDisable(GL11.GL_SCISSOR_TEST);
if(fbo != 0) GL45.glBindFramebuffer(GL45.GL_DRAW_FRAMEBUFFER, 0);
fbo = -1;
}
}

View File

@ -0,0 +1,101 @@
package speiger.src.coreengine.graphics.opengl.shader;
import java.io.BufferedReader;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Map;
import java.util.Objects;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.internal.Streams;
import com.google.gson.stream.JsonWriter;
import speiger.src.collections.objects.maps.impl.hash.Object2ObjectOpenHashMap;
import speiger.src.coreengine.assets.AssetLocation;
public class ShaderCache {
public static final ShaderCache INSTANCE = new ShaderCache();
Map<AssetLocation, String> hashCache;
Path cache;
public void init(Path cache) {
this.cache = cache;
if(Files.notExists(cache)) {
try { Files.createDirectories(cache); }
catch(IOException e) {
e.printStackTrace();
this.cache = null;
}
}
try(BufferedReader reader = Files.newBufferedReader(cache.resolve("cache.json"))) {
Map<AssetLocation, String> knownCache = new Object2ObjectOpenHashMap<>();
for(JsonElement element : JsonParser.parseReader(reader).getAsJsonObject().getAsJsonArray("shaders")) {
JsonObject shader = element.getAsJsonObject();
knownCache.put(AssetLocation.of(shader.get("id").getAsString()), shader.get("hash").getAsString());
}
hashCache = knownCache;
}
catch(Exception e) {
e.printStackTrace();
hashCache = new Object2ObjectOpenHashMap<>();
}
}
private void save() {
JsonArray array = new JsonArray();
hashCache.forEach((K, V) -> {
JsonObject obj = new JsonObject();
obj.addProperty("id", K.toString());
obj.addProperty("hash", V);
array.add(obj);
});
try(JsonWriter writer = new JsonWriter(Files.newBufferedWriter(cache.resolve("cache.json")))) {
JsonObject obj = new JsonObject();
obj.add("shaders", array);
writer.setIndent("\t");
Streams.write(obj, writer);
}
catch(Exception e) { e.printStackTrace(); }
}
public byte[] get(AssetLocation shaderLocation, String fileHash) {
String known = hashCache.get(shaderLocation);
if(!Objects.equals(known, fileHash)) return null;
Path path = toFile(shaderLocation);
if(Files.notExists(path)) return null;
try { return Files.readAllBytes(path); }
catch(Exception e) { e.printStackTrace(); }
return null;
}
public void store(AssetLocation shaderLocation, String fileHash, byte[] shader) {
Objects.requireNonNull(shaderLocation);
Objects.requireNonNull(fileHash);
Objects.requireNonNull(shader);
hashCache.put(shaderLocation, fileHash);
try {
Path file = toFile(shaderLocation);
if(Files.notExists(file.getParent())) Files.createDirectories(file.getParent());
Files.write(file, shader);
}
catch(Exception e) {
e.printStackTrace();
}
save();
}
public void delete(AssetLocation shaderLocation) {
if(hashCache.remove(shaderLocation) == null) return;
try { Files.deleteIfExists(toFile(shaderLocation)); }
catch(Exception e) { e.printStackTrace(); }
save();
}
private Path toFile(AssetLocation id) {
return cache.resolve(id.domain()).resolve(id.location()+".bin");
}
}

View File

@ -0,0 +1,9 @@
package speiger.src.coreengine.graphics.opengl.shader;
import java.util.Map;
public record ShaderInstance(int programId, Map<String, UniformObject> uniforms, Map<String, SamplerObject> samplers) {
public record UniformObject(int slot) {}
public record SamplerObject(int unit) {}
}

View File

@ -0,0 +1,26 @@
package speiger.src.coreengine.graphics.opengl.texture;
import org.lwjgl.opengl.GL45;
import speiger.src.collections.objects.maps.impl.hash.Object2IntOpenHashMap;
import speiger.src.collections.objects.maps.interfaces.Object2IntMap;
import speiger.src.coreengine.assets.AssetLocation;
public class FrameBufferCache {
Object2IntMap<AssetLocation> fboCache = new Object2IntOpenHashMap<>();
public int getOrCreateFBO(AssetLocation id) {
return fboCache.supplyIntIfAbsent(id, GL45::glCreateFramebuffers);
}
public void deleteFBO(AssetLocation id) {
int fbo = fboCache.rem(id);
if(fbo == -1) return;
GL45.glDeleteFramebuffers(fbo);
}
public void clear() {
GL45.glDeleteFramebuffers(fboCache.values().toIntArray());
fboCache.clear();
}
}

View File

@ -12,6 +12,10 @@ public class GLTexture extends Texture {
this.id = id; this.id = id;
} }
public int id() {
return id;
}
@Override @Override
public boolean isRemoved() { public boolean isRemoved() {
return id == 0; return id == 0;

View File

@ -10,7 +10,6 @@ import org.lwjgl.opengl.GL43;
import org.lwjgl.system.Configuration; import org.lwjgl.system.Configuration;
import org.lwjgl.util.freetype.FreeType; import org.lwjgl.util.freetype.FreeType;
import speiger.src.collections.objects.lists.ObjectArrayList; import speiger.src.collections.objects.lists.ObjectArrayList;
import speiger.src.coreengine.assets.AssetLocation; import speiger.src.coreengine.assets.AssetLocation;
import speiger.src.coreengine.assets.AssetManager; import speiger.src.coreengine.assets.AssetManager;
@ -19,7 +18,6 @@ import speiger.src.coreengine.assets.base.IAssetProvider;
import speiger.src.coreengine.math.vector.matrix.Matrix4f; import speiger.src.coreengine.math.vector.matrix.Matrix4f;
import speiger.src.coreengine.rendering.gui.font.Font; import speiger.src.coreengine.rendering.gui.font.Font;
import speiger.src.coreengine.rendering.gui.font.FontManager; import speiger.src.coreengine.rendering.gui.font.FontManager;
import speiger.src.coreengine.rendering.gui.font.TextStyle;
import speiger.src.coreengine.rendering.gui.font.glyth.Glyth; import speiger.src.coreengine.rendering.gui.font.glyth.Glyth;
import speiger.src.coreengine.rendering.gui.font.glyth.IGlythSheetInfo; import speiger.src.coreengine.rendering.gui.font.glyth.IGlythSheetInfo;
import speiger.src.coreengine.rendering.gui.font.glyth.MissingGlyth; import speiger.src.coreengine.rendering.gui.font.glyth.MissingGlyth;
@ -157,11 +155,11 @@ public class NewInputTest {
// }); // });
// String s = "The Quick brown fox Jumps over the Lazy dog"; // String s = "The Quick brown fox Jumps over the Lazy dog";
float x = 50; // float x = 50;
float y = 50; // float y = 50;
float scale = 1F; // float scale = 1F;
y /= scale; // y /= scale;
TextStyle style = TextStyle.DEFAULT.size(12).bold(false); // TextStyle style = TextStyle.DEFAULT.size(12).bold(false);
// font.drawText(style, "Testing My Theory", x, y, -1, buffer, scale, true); // font.drawText(style, "Testing My Theory", x, y, -1, buffer, scale, true);
// float offset = font.drawText(style, "The Quick ", 50, y, -1, buffer, scale, false); // float offset = font.drawText(style, "The Quick ", 50, y, -1, buffer, scale, false);
// offset += font.drawText(style, "Brown ", 50+offset, y, -1, buffer, scale, false); // offset += font.drawText(style, "Brown ", 50+offset, y, -1, buffer, scale, false);
@ -169,7 +167,7 @@ public class NewInputTest {
// offset += font.drawText(style, "Jumps ", 50+offset, y, -1, buffer, scale, false); // offset += font.drawText(style, "Jumps ", 50+offset, y, -1, buffer, scale, false);
// offset += font.drawText(style, "over the Lazy dog", 50+offset, y, -1, buffer, scale, true); // offset += font.drawText(style, "over the Lazy dog", 50+offset, y, -1, buffer, scale, true);
// font.drawText(s, 50, 50, -1, buffer, true); // font.drawText(s, 50, 50, -1, buffer, true);
GLStateTracker tracker = GLStateTracker.instance(); // GLStateTracker tracker = GLStateTracker.instance();
GL11.glClearColor(0.2F, 0.55F, 0.66F, 1F); GL11.glClearColor(0.2F, 0.55F, 0.66F, 1F);
while(!window.shouldClose()) { while(!window.shouldClose()) {
GLFW.glfwPollEvents(); GLFW.glfwPollEvents();
@ -215,7 +213,7 @@ public class NewInputTest {
GL11.glClearColor(0.4F, 0.55F, 0.36F, 1F); GL11.glClearColor(0.4F, 0.55F, 0.36F, 1F);
int size = 512; int size = 512;
int half = size >> 1; int half = size >> 1;
int base = size >> 3; // int base = size >> 3;
DynamicTexture texture = new DynamicTexture(size, size, DynamicTexture.DEFAULT_PARAMETERS); DynamicTexture texture = new DynamicTexture(size, size, DynamicTexture.DEFAULT_PARAMETERS);
texture.fill(0, 0, size, size, -1); texture.fill(0, 0, size, size, -1);

View File

@ -1,39 +1,39 @@
package speiger.src.coreengine.assets; package speiger.src.coreengine.assets;
import java.util.Map; import java.util.Map;
import speiger.src.coreengine.assets.base.IAsset; import speiger.src.coreengine.assets.base.IAsset;
import speiger.src.coreengine.assets.base.IAssetProvider; import speiger.src.coreengine.assets.base.IAssetProvider;
import speiger.src.coreengine.assets.base.MultiAsset; import speiger.src.coreengine.assets.base.MultiAsset;
public record AssetFilter(String prefix, String extension) { public record AssetFilter(String prefix, String extension) {
public static AssetFilter json(String prefix) { public static AssetFilter json(String prefix) {
return new AssetFilter(prefix, ".json"); return new AssetFilter(prefix, ".json");
} }
public AssetLocation id(AssetLocation file) { public AssetLocation id(AssetLocation file) {
String location = file.location(); String location = file.location();
return AssetLocation.of(file.domain(), location.substring(prefix().length()+1, location.length()-extension().length())); return AssetLocation.of(file.domain(), location.substring(prefix().length()+1, location.length()-extension().length()));
} }
public AssetLocation file(AssetLocation id) { public AssetLocation file(AssetLocation id) {
return AssetLocation.of(id.domain(), prefix()+"/"+id.location()+extension()); return AssetLocation.of(id.domain(), prefix()+"/"+id.location()+extension());
} }
public Map<AssetLocation, IAsset> list(IAssetProvider provider) { public Map<AssetLocation, IAsset> list(IAssetProvider provider) {
return provider.listAssets(prefix, T -> T.endsWith(extension)); return provider.listAssets(prefix, T -> T.endsWith(extension));
} }
public Map<AssetLocation, IAsset> listRoot(IAssetProvider provider) { public Map<AssetLocation, IAsset> listRoot(IAssetProvider provider) {
return provider.listAssets(prefix, T -> T.endsWith(extension) && !T.isInFolder(prefix)); return provider.listAssets(prefix, T -> T.endsWith(extension) && !T.isInFolder(prefix));
} }
public Map<AssetLocation, MultiAsset> multi(IAssetProvider provider) { public Map<AssetLocation, MultiAsset> multi(IAssetProvider provider) {
return provider.listAllAssets(prefix, T -> T.endsWith(extension)); return provider.listAllAssets(prefix, T -> T.endsWith(extension));
} }
public Map<AssetLocation, MultiAsset> multiRoot(IAssetProvider provider) { public Map<AssetLocation, MultiAsset> multiRoot(IAssetProvider provider) {
return provider.listAllAssets(prefix, T -> T.endsWith(extension) && !T.isInFolder(prefix)); return provider.listAllAssets(prefix, T -> T.endsWith(extension) && !T.isInFolder(prefix));
} }
} }

View File

@ -1,103 +1,103 @@
package speiger.src.coreengine.assets; package speiger.src.coreengine.assets;
import java.nio.file.attribute.FileTime; import java.nio.file.attribute.FileTime;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.function.Predicate; import java.util.function.Predicate;
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;
import speiger.src.collections.objects.utils.ObjectLists; import speiger.src.collections.objects.utils.ObjectLists;
import speiger.src.coreengine.assets.base.IAsset; import speiger.src.coreengine.assets.base.IAsset;
import speiger.src.coreengine.assets.base.IAssetPackage; import speiger.src.coreengine.assets.base.IAssetPackage;
import speiger.src.coreengine.assets.base.IAssetProvider.ICloseableAssetProvider; import speiger.src.coreengine.assets.base.IAssetProvider.ICloseableAssetProvider;
import speiger.src.coreengine.assets.base.IManagedAsset; import speiger.src.coreengine.assets.base.IManagedAsset;
import speiger.src.coreengine.assets.base.IReloadableAsset; import speiger.src.coreengine.assets.base.IReloadableAsset;
import speiger.src.coreengine.assets.base.MultiAsset; import speiger.src.coreengine.assets.base.MultiAsset;
import speiger.src.coreengine.assets.base.PackReloadingTask; import speiger.src.coreengine.assets.base.PackReloadingTask;
import speiger.src.coreengine.assets.impl.LayeredAssetProvider; import speiger.src.coreengine.assets.impl.LayeredAssetProvider;
public class AssetManager implements ICloseableAssetProvider public class AssetManager implements ICloseableAssetProvider
{ {
ObjectList<IReloadableAsset> listeners = new ObjectArrayList<>(); ObjectList<IReloadableAsset> listeners = new ObjectArrayList<>();
LayeredAssetProvider provider; LayeredAssetProvider provider;
public AssetManager(List<IAssetPackage> packages) { public AssetManager(List<IAssetPackage> packages) {
provider = new LayeredAssetProvider(packages); provider = new LayeredAssetProvider(packages);
} }
public void addListener(IReloadableAsset listener) { public void addListener(IReloadableAsset listener) {
listeners.add(listener); listeners.add(listener);
if(listener instanceof IManagedAsset managed) { if(listener instanceof IManagedAsset managed) {
managed.setProvider(this); managed.setProvider(this);
} }
} }
public ObjectList<IReloadableAsset> listeners() { public ObjectList<IReloadableAsset> listeners() {
return ObjectLists.unmodifiable(listeners); return ObjectLists.unmodifiable(listeners);
} }
public AssetManager reload(Executor offthread, Executor syncer, List<IAssetPackage> packages) { public AssetManager reload(Executor offthread, Executor syncer, List<IAssetPackage> packages) {
return reloadAssets(packages).reloadSelective(offthread, syncer, listeners); return reloadAssets(packages).reloadSelective(offthread, syncer, listeners);
} }
public AssetManager reload() { public AssetManager reload() {
return reload(Runnable::run, Runnable::run); return reload(Runnable::run, Runnable::run);
} }
public AssetManager reload(Executor offthread, Executor syncer) { public AssetManager reload(Executor offthread, Executor syncer) {
return reloadSelective(offthread, syncer, listeners); return reloadSelective(offthread, syncer, listeners);
} }
public AssetManager reloadSelective(List<IReloadableAsset> listeners) { public AssetManager reloadSelective(List<IReloadableAsset> listeners) {
return reloadSelective(Runnable::run, Runnable::run, listeners); return reloadSelective(Runnable::run, Runnable::run, listeners);
} }
public AssetManager reloadSelective(Executor offthread, Executor syncer, List<IReloadableAsset> listeners) { public AssetManager reloadSelective(Executor offthread, Executor syncer, List<IReloadableAsset> listeners) {
PackReloadingTask.reload(provider, listeners, offthread, syncer).join(); PackReloadingTask.reload(provider, listeners, offthread, syncer).join();
return this; return this;
} }
public AssetManager reloadAssets(List<IAssetPackage> packages) { public AssetManager reloadAssets(List<IAssetPackage> packages) {
provider.close(); provider.close();
provider = new LayeredAssetProvider(packages); provider = new LayeredAssetProvider(packages);
return this; return this;
} }
@Override @Override
public void close() { public void close() {
provider.close(); provider.close();
listeners.forEach(IReloadableAsset::destroy); listeners.forEach(IReloadableAsset::destroy);
} }
@Override @Override
public FileTime getModifiedTime(AssetLocation location) { public FileTime getModifiedTime(AssetLocation location) {
return provider.getModifiedTime(location); return provider.getModifiedTime(location);
} }
@Override @Override
public FileTime getLatestTime(AssetLocation... locations) { public FileTime getLatestTime(AssetLocation... locations) {
return provider.getLatestTime(locations); return provider.getLatestTime(locations);
} }
@Override @Override
public IAsset getAsset(AssetLocation location) { public IAsset getAsset(AssetLocation location) {
return provider.getAsset(location); return provider.getAsset(location);
} }
@Override @Override
public MultiAsset getAllAssets(AssetLocation location) { public MultiAsset getAllAssets(AssetLocation location) {
return provider.getAllAssets(location); return provider.getAllAssets(location);
} }
@Override @Override
public Map<AssetLocation, IAsset> listAssets(String folder, Predicate<AssetLocation> filter) { public Map<AssetLocation, IAsset> listAssets(String folder, Predicate<AssetLocation> filter) {
return provider.listAssets(folder, filter); return provider.listAssets(folder, filter);
} }
@Override @Override
public Map<AssetLocation, MultiAsset> listAllAssets(String folder, Predicate<AssetLocation> filter) { public Map<AssetLocation, MultiAsset> listAllAssets(String folder, Predicate<AssetLocation> filter) {
return provider.listAllAssets(folder, filter); return provider.listAllAssets(folder, filter);
} }
} }

View File

@ -1,29 +1,29 @@
package speiger.src.coreengine.assets.base; package speiger.src.coreengine.assets.base;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.Closeable; import java.io.Closeable;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.List; import java.util.List;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import speiger.src.coreengine.assets.AssetLocation; import speiger.src.coreengine.assets.AssetLocation;
public interface IAsset extends Closeable public interface IAsset extends Closeable
{ {
public IAssetPackage owner(); public IAssetPackage owner();
public AssetLocation location(); public AssetLocation location();
@Override @Override
public void close(); public void close();
public IAsset subAsset(String alternative); public IAsset subAsset(String alternative);
public InputStream stream() throws IOException; public InputStream stream() throws IOException;
public ByteBuffer bytes() throws IOException; public ByteBuffer bytes() throws IOException;
public BufferedReader reader() throws IOException; public BufferedReader reader() throws IOException;
public List<String> lines() throws IOException; public List<String> lines() throws IOException;
public JsonObject json() throws IOException; public JsonObject json() throws IOException;
public BufferedImage texture() throws Exception; public BufferedImage texture() throws Exception;
public <T> T custom(IAssetParser<T> parser) throws IOException; public <T> T custom(IAssetParser<T> parser) throws IOException;
} }

View File

@ -1,31 +1,31 @@
package speiger.src.coreengine.assets.base; package speiger.src.coreengine.assets.base;
import java.io.Closeable; import java.io.Closeable;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.attribute.FileTime; import java.nio.file.attribute.FileTime;
import java.util.List; import java.util.List;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
import speiger.src.coreengine.assets.AssetLocation; import speiger.src.coreengine.assets.AssetLocation;
import speiger.src.coreengine.assets.impl.FolderAssetPackage; import speiger.src.coreengine.assets.impl.FolderAssetPackage;
import speiger.src.coreengine.assets.impl.ZipAssetPackage; import speiger.src.coreengine.assets.impl.ZipAssetPackage;
import speiger.src.coreengine.utils.helpers.IOUtils; import speiger.src.coreengine.utils.helpers.IOUtils;
public interface IAssetPackage extends Closeable public interface IAssetPackage extends Closeable
{ {
@Override @Override
public void close(); public void close();
public void getModifiedTime(String domain, BiConsumer<AssetLocation, FileTime> accept); public void getModifiedTime(String domain, BiConsumer<AssetLocation, FileTime> accept);
public List<String> getDomains(); public List<String> getDomains();
public IAsset getAsset(AssetLocation location); public IAsset getAsset(AssetLocation location);
public void gatherAssets(AssetLocation folder, BiConsumer<AssetLocation, IAsset> accept); public void gatherAssets(AssetLocation folder, BiConsumer<AssetLocation, IAsset> accept);
public static IAssetPackage of(Path path) { public static IAssetPackage of(Path path) {
if(Files.exists(path)) { if(Files.exists(path)) {
if(Files.isDirectory(path)) return new FolderAssetPackage(path); if(Files.isDirectory(path)) return new FolderAssetPackage(path);
if(IOUtils.isZip(path)) return new ZipAssetPackage(path); if(IOUtils.isZip(path)) return new ZipAssetPackage(path);
} }
return null; return null;
} }
} }

View File

@ -1,22 +1,22 @@
package speiger.src.coreengine.assets.base; package speiger.src.coreengine.assets.base;
import java.nio.file.attribute.FileTime; import java.nio.file.attribute.FileTime;
import java.util.Map; import java.util.Map;
import java.util.function.Predicate; import java.util.function.Predicate;
import speiger.src.coreengine.assets.AssetLocation; import speiger.src.coreengine.assets.AssetLocation;
public interface IAssetProvider { public interface IAssetProvider {
public IAsset getAsset(AssetLocation location); public IAsset getAsset(AssetLocation location);
public MultiAsset getAllAssets(AssetLocation location); public MultiAsset getAllAssets(AssetLocation location);
public FileTime getModifiedTime(AssetLocation location); public FileTime getModifiedTime(AssetLocation location);
public FileTime getLatestTime(AssetLocation...locations); public FileTime getLatestTime(AssetLocation...locations);
public Map<AssetLocation, IAsset> listAssets(String folder, Predicate<AssetLocation> filter); public Map<AssetLocation, IAsset> listAssets(String folder, Predicate<AssetLocation> filter);
public Map<AssetLocation, MultiAsset> listAllAssets(String folder, Predicate<AssetLocation> filter); public Map<AssetLocation, MultiAsset> listAllAssets(String folder, Predicate<AssetLocation> filter);
public static interface ICloseableAssetProvider extends IAssetProvider, AutoCloseable { public static interface ICloseableAssetProvider extends IAssetProvider, AutoCloseable {
@Override @Override
public void close(); public void close();
} }
} }

View File

@ -1,85 +1,85 @@
package speiger.src.coreengine.assets.base; package speiger.src.coreengine.assets.base;
import java.io.Closeable; import java.io.Closeable;
import java.io.IOException; import java.io.IOException;
import java.util.Iterator; import java.util.Iterator;
import java.util.NoSuchElementException; import java.util.NoSuchElementException;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Supplier; import java.util.function.Supplier;
import speiger.src.collections.ints.functions.consumer.IntObjectConsumer; import speiger.src.collections.ints.functions.consumer.IntObjectConsumer;
import speiger.src.collections.objects.collections.ObjectIterable; import speiger.src.collections.objects.collections.ObjectIterable;
import speiger.src.collections.objects.collections.ObjectIterator; import speiger.src.collections.objects.collections.ObjectIterator;
import speiger.src.collections.objects.functions.consumer.ObjectObjectConsumer; import speiger.src.collections.objects.functions.consumer.ObjectObjectConsumer;
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;
public class MultiAsset implements Closeable, ObjectIterable<IAsset> { public class MultiAsset implements Closeable, ObjectIterable<IAsset> {
ObjectList<IAsset> assets; ObjectList<IAsset> assets;
public MultiAsset(IAsset...assets) { public MultiAsset(IAsset...assets) {
this(ObjectArrayList.wrap(assets)); this(ObjectArrayList.wrap(assets));
} }
public MultiAsset(ObjectList<IAsset> assets) { public MultiAsset(ObjectList<IAsset> assets) {
this.assets = assets.unmodifiable(); this.assets = assets.unmodifiable();
} }
@Override @Override
public void close() { public void close() {
if(assets != null) { if(assets != null) {
assets.forEach(IAsset::close); assets.forEach(IAsset::close);
assets = null; assets = null;
} }
} }
public int size() { public int size() {
return assets.size(); return assets.size();
} }
public IAsset get(int index) { public IAsset get(int index) {
return assets.get(index); return assets.get(index);
} }
public <T> Iterable<T> map(AssetMapper<T> mappingFunction, Supplier<T> defaultValue) { public <T> Iterable<T> map(AssetMapper<T> mappingFunction, Supplier<T> defaultValue) {
return () -> new Iterator<T>() { return () -> new Iterator<T>() {
int index = 0; int index = 0;
int size = assets.size(); int size = assets.size();
@Override @Override
public boolean hasNext() { return index < size; } public boolean hasNext() { return index < size; }
@Override @Override
public T next() { public T next() {
if(!hasNext()) throw new NoSuchElementException(); if(!hasNext()) throw new NoSuchElementException();
try { return mappingFunction.apply(assets.get(index++)); } try { return mappingFunction.apply(assets.get(index++)); }
catch(IOException e) { catch(IOException e) {
e.printStackTrace(); e.printStackTrace();
return defaultValue.get(); return defaultValue.get();
} }
} }
}; };
} }
@Override @Override
public void forEach(Consumer<? super IAsset> action) { public void forEach(Consumer<? super IAsset> action) {
assets.forEach(action); assets.forEach(action);
} }
@Override @Override
public <E> void forEach(E input, ObjectObjectConsumer<E, IAsset> action) { public <E> void forEach(E input, ObjectObjectConsumer<E, IAsset> action) {
assets.forEach(input, action); assets.forEach(input, action);
} }
@Override @Override
public void forEachIndexed(IntObjectConsumer<IAsset> action) { public void forEachIndexed(IntObjectConsumer<IAsset> action) {
assets.forEachIndexed(action); assets.forEachIndexed(action);
} }
@Override @Override
public ObjectIterator<IAsset> iterator() { public ObjectIterator<IAsset> iterator() {
return assets.iterator(); return assets.iterator();
} }
public static interface AssetMapper<T> { public static interface AssetMapper<T> {
public T apply(IAsset asset) throws IOException; public T apply(IAsset asset) throws IOException;
} }
} }

View File

@ -1,44 +1,44 @@
package speiger.src.coreengine.assets.impl; package speiger.src.coreengine.assets.impl;
import java.io.Closeable; import java.io.Closeable;
import java.util.List; import java.util.List;
import speiger.src.collections.objects.lists.ObjectArrayList; import speiger.src.collections.objects.lists.ObjectArrayList;
import speiger.src.coreengine.assets.AssetLocation; import speiger.src.coreengine.assets.AssetLocation;
import speiger.src.coreengine.assets.base.IAsset; import speiger.src.coreengine.assets.base.IAsset;
import speiger.src.coreengine.assets.base.IAssetPackage; import speiger.src.coreengine.assets.base.IAssetPackage;
public abstract class BaseAsset implements IAsset { public abstract class BaseAsset implements IAsset {
protected AssetLocation location; protected AssetLocation location;
protected IAssetPackage owner; protected IAssetPackage owner;
protected List<Closeable> closeable = new ObjectArrayList<>(); protected List<Closeable> closeable = new ObjectArrayList<>();
public BaseAsset(AssetLocation location, IAssetPackage owner) { public BaseAsset(AssetLocation location, IAssetPackage owner) {
this.location = location; this.location = location;
this.owner = owner; this.owner = owner;
} }
@Override @Override
public void close() { public void close() {
for(Closeable close : closeable) { for(Closeable close : closeable) {
try { close.close(); } try { close.close(); }
catch(Exception e) { e.printStackTrace(); } catch(Exception e) { e.printStackTrace(); }
} }
closeable.clear(); closeable.clear();
} }
protected <T extends Closeable> T markClosed(T value) { protected <T extends Closeable> T markClosed(T value) {
closeable.add(value); closeable.add(value);
return value; return value;
} }
@Override @Override
public AssetLocation location() { public AssetLocation location() {
return location; return location;
} }
@Override @Override
public IAssetPackage owner() { public IAssetPackage owner() {
return owner; return owner;
} }
} }

View File

@ -1,71 +1,71 @@
package speiger.src.coreengine.assets.impl; package speiger.src.coreengine.assets.impl;
import java.io.IOException; import java.io.IOException;
import java.nio.file.DirectoryStream; import java.nio.file.DirectoryStream;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.attribute.FileTime; import java.nio.file.attribute.FileTime;
import java.util.List; import java.util.List;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
import java.util.stream.Stream; import java.util.stream.Stream;
import speiger.src.collections.objects.lists.ObjectArrayList; import speiger.src.collections.objects.lists.ObjectArrayList;
import speiger.src.coreengine.assets.AssetLocation; import speiger.src.coreengine.assets.AssetLocation;
import speiger.src.coreengine.assets.base.IAsset; import speiger.src.coreengine.assets.base.IAsset;
import speiger.src.coreengine.assets.base.IAssetPackage; import speiger.src.coreengine.assets.base.IAssetPackage;
import speiger.src.coreengine.utils.collections.iterators.IterableWrapper; import speiger.src.coreengine.utils.collections.iterators.IterableWrapper;
public class FolderAssetPackage implements IAssetPackage { public class FolderAssetPackage implements IAssetPackage {
Path baseFolder; Path baseFolder;
public FolderAssetPackage(Path baseFolder) { public FolderAssetPackage(Path baseFolder) {
this.baseFolder = baseFolder; this.baseFolder = baseFolder;
} }
@Override @Override
public void close() {} public void close() {}
@Override @Override
public void getModifiedTime(String domain, BiConsumer<AssetLocation, FileTime> accept) { public void getModifiedTime(String domain, BiConsumer<AssetLocation, FileTime> accept) {
try { try {
Path start = baseFolder.resolve("assets/").resolve(domain); Path start = baseFolder.resolve("assets/").resolve(domain);
for(Path path : IterableWrapper.wrap(Files.walk(start).filter(Files::isRegularFile).iterator())) { for(Path path : IterableWrapper.wrap(Files.walk(start).filter(Files::isRegularFile).iterator())) {
accept.accept(AssetLocation.of(domain, start.relativize(path).toString().replace("\\", "/")), Files.getLastModifiedTime(path)); accept.accept(AssetLocation.of(domain, start.relativize(path).toString().replace("\\", "/")), Files.getLastModifiedTime(path));
} }
} }
catch(IOException e) { e.printStackTrace(); } catch(IOException e) { e.printStackTrace(); }
} }
@Override @Override
public List<String> getDomains() { public List<String> getDomains() {
List<String> domains = new ObjectArrayList<>(); List<String> domains = new ObjectArrayList<>();
try(DirectoryStream<Path> dirs = Files.newDirectoryStream(baseFolder.resolve("assets"))) { try(DirectoryStream<Path> dirs = Files.newDirectoryStream(baseFolder.resolve("assets"))) {
for(Path path : dirs) { for(Path path : dirs) {
domains.add(path.getFileName().toString()); domains.add(path.getFileName().toString());
} }
} }
catch(IOException e) { e.printStackTrace(); } catch(IOException e) { e.printStackTrace(); }
return domains; return domains;
} }
@Override @Override
public IAsset getAsset(AssetLocation location) { public IAsset getAsset(AssetLocation location) {
Path path = baseFolder.resolve(location.actualLocation()); Path path = baseFolder.resolve(location.actualLocation());
return Files.exists(path) ? new SimpleAsset(location, this, path) : null; return Files.exists(path) ? new SimpleAsset(location, this, path) : null;
} }
@Override @Override
public void gatherAssets(AssetLocation folder, BiConsumer<AssetLocation, IAsset> result) { public void gatherAssets(AssetLocation folder, BiConsumer<AssetLocation, IAsset> result) {
Path start = baseFolder.resolve(folder.actualLocation()); Path start = baseFolder.resolve(folder.actualLocation());
if(Files.notExists(start)) return; if(Files.notExists(start)) return;
try(Stream<Path> stream = Files.walk(start).filter(Files::isRegularFile)) { try(Stream<Path> stream = Files.walk(start).filter(Files::isRegularFile)) {
for(Path path : IterableWrapper.wrap(stream.iterator())) { for(Path path : IterableWrapper.wrap(stream.iterator())) {
AssetLocation location = folder.subAsset(start.relativize(path).toString().replace("\\", "/")); AssetLocation location = folder.subAsset(start.relativize(path).toString().replace("\\", "/"));
result.accept(location, new SimpleAsset(location, this, path)); result.accept(location, new SimpleAsset(location, this, path));
} }
} }
catch(IOException e) { catch(IOException e) {
e.printStackTrace(); e.printStackTrace();
} }
} }
} }

View File

@ -1,161 +1,161 @@
package speiger.src.coreengine.assets.impl; package speiger.src.coreengine.assets.impl;
import java.nio.file.attribute.FileTime; import java.nio.file.attribute.FileTime;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.function.Predicate; import java.util.function.Predicate;
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;
import speiger.src.collections.objects.maps.interfaces.Object2ObjectMap; import speiger.src.collections.objects.maps.interfaces.Object2ObjectMap;
import speiger.src.collections.objects.utils.maps.Object2ObjectMaps; import speiger.src.collections.objects.utils.maps.Object2ObjectMaps;
import speiger.src.coreengine.assets.AssetLocation; import speiger.src.coreengine.assets.AssetLocation;
import speiger.src.coreengine.assets.base.IAsset; import speiger.src.coreengine.assets.base.IAsset;
import speiger.src.coreengine.assets.base.IAssetPackage; import speiger.src.coreengine.assets.base.IAssetPackage;
import speiger.src.coreengine.assets.base.IAssetProvider; import speiger.src.coreengine.assets.base.IAssetProvider;
import speiger.src.coreengine.assets.base.IAssetProvider.ICloseableAssetProvider; import speiger.src.coreengine.assets.base.IAssetProvider.ICloseableAssetProvider;
import speiger.src.coreengine.assets.base.MultiAsset; import speiger.src.coreengine.assets.base.MultiAsset;
import speiger.src.coreengine.math.ArrayUtil; import speiger.src.coreengine.math.ArrayUtil;
public class LayeredAssetProvider implements ICloseableAssetProvider { public class LayeredAssetProvider implements ICloseableAssetProvider {
public static final FileTime DEFAULT_TIME = FileTime.fromMillis(0L); public static final FileTime DEFAULT_TIME = FileTime.fromMillis(0L);
Map<String, DomainAssetProvider> domains = Object2ObjectMap.builder().linkedMap(); Map<String, DomainAssetProvider> domains = Object2ObjectMap.builder().linkedMap();
List<IAssetPackage> packages; List<IAssetPackage> packages;
public LayeredAssetProvider(List<IAssetPackage> packages) { public LayeredAssetProvider(List<IAssetPackage> packages) {
this.packages = packages; this.packages = packages;
for(IAssetPackage pack : packages) { for(IAssetPackage pack : packages) {
for(String domain : pack.getDomains()) { for(String domain : pack.getDomains()) {
domains.computeIfAbsent(domain, DomainAssetProvider::new).addPackage(pack); domains.computeIfAbsent(domain, DomainAssetProvider::new).addPackage(pack);
} }
} }
domains.values().forEach(DomainAssetProvider::buildCaches); domains.values().forEach(DomainAssetProvider::buildCaches);
} }
@Override @Override
public void close() { public void close() {
packages.forEach(IAssetPackage::close); packages.forEach(IAssetPackage::close);
} }
@Override @Override
public FileTime getModifiedTime(AssetLocation location) { public FileTime getModifiedTime(AssetLocation location) {
DomainAssetProvider provider = domains.get(location.domain()); DomainAssetProvider provider = domains.get(location.domain());
return provider == null ? DEFAULT_TIME : provider.getModifiedTime(location); return provider == null ? DEFAULT_TIME : provider.getModifiedTime(location);
} }
@Override @Override
public FileTime getLatestTime(AssetLocation... locations) { public FileTime getLatestTime(AssetLocation... locations) {
FileTime time = DEFAULT_TIME; FileTime time = DEFAULT_TIME;
for(AssetLocation location : locations) { for(AssetLocation location : locations) {
time = ArrayUtil.higher(time, getModifiedTime(location)); time = ArrayUtil.higher(time, getModifiedTime(location));
} }
return time; return time;
} }
@Override @Override
public IAsset getAsset(AssetLocation location) { public IAsset getAsset(AssetLocation location) {
DomainAssetProvider provider = domains.get(location.domain()); DomainAssetProvider provider = domains.get(location.domain());
return provider == null ? null : provider.getAsset(location); return provider == null ? null : provider.getAsset(location);
} }
@Override @Override
public MultiAsset getAllAssets(AssetLocation location) { public MultiAsset getAllAssets(AssetLocation location) {
DomainAssetProvider provider = domains.get(location.domain()); DomainAssetProvider provider = domains.get(location.domain());
return provider == null ? null : provider.getAllAssets(location); return provider == null ? null : provider.getAllAssets(location);
} }
@Override @Override
public Map<AssetLocation, IAsset> listAssets(String folder, Predicate<AssetLocation> filter) { public Map<AssetLocation, IAsset> listAssets(String folder, Predicate<AssetLocation> filter) {
Map<AssetLocation, IAsset> result = Object2ObjectMap.builder().linkedMap(); Map<AssetLocation, IAsset> result = Object2ObjectMap.builder().linkedMap();
for(DomainAssetProvider provider : domains.values()) { for(DomainAssetProvider provider : domains.values()) {
result.putAll(provider.listAssets(folder, filter)); result.putAll(provider.listAssets(folder, filter));
} }
return result; return result;
} }
@Override @Override
public Map<AssetLocation, MultiAsset> listAllAssets(String folder, Predicate<AssetLocation> filter) { public Map<AssetLocation, MultiAsset> listAllAssets(String folder, Predicate<AssetLocation> filter) {
Map<AssetLocation, MultiAsset> result = Object2ObjectMap.builder().linkedMap(); Map<AssetLocation, MultiAsset> result = Object2ObjectMap.builder().linkedMap();
for(DomainAssetProvider provider : domains.values()) { for(DomainAssetProvider provider : domains.values()) {
result.putAll(provider.listAllAssets(folder, filter)); result.putAll(provider.listAllAssets(folder, filter));
} }
return result; return result;
} }
private static class DomainAssetProvider implements IAssetProvider { private static class DomainAssetProvider implements IAssetProvider {
final String domain; final String domain;
ObjectList<IAssetPackage> packages = new ObjectArrayList<>(); ObjectList<IAssetPackage> packages = new ObjectArrayList<>();
Map<AssetLocation, FileTime> lastChanges = Object2ObjectMap.builder().map(); Map<AssetLocation, FileTime> lastChanges = Object2ObjectMap.builder().map();
public DomainAssetProvider(String domain) { public DomainAssetProvider(String domain) {
this.domain = domain; this.domain = domain;
} }
public void addPackage(IAssetPackage pack) { public void addPackage(IAssetPackage pack) {
packages.add(pack); packages.add(pack);
} }
private void buildCaches() { private void buildCaches() {
for(int i = packages.size()-1;i>=0;i--) { for(int i = packages.size()-1;i>=0;i--) {
packages.get(i).getModifiedTime(domain, lastChanges::putIfAbsent); packages.get(i).getModifiedTime(domain, lastChanges::putIfAbsent);
} }
} }
@Override @Override
public FileTime getModifiedTime(AssetLocation location) { public FileTime getModifiedTime(AssetLocation location) {
return lastChanges.getOrDefault(location, DEFAULT_TIME); return lastChanges.getOrDefault(location, DEFAULT_TIME);
} }
@Override @Override
public FileTime getLatestTime(AssetLocation... locations) { public FileTime getLatestTime(AssetLocation... locations) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@Override @Override
public IAsset getAsset(AssetLocation location) { public IAsset getAsset(AssetLocation location) {
for(int i = packages.size()-1;i>=0;i--) { for(int i = packages.size()-1;i>=0;i--) {
IAsset asset = packages.get(i).getAsset(location); IAsset asset = packages.get(i).getAsset(location);
if(asset != null) return asset; if(asset != null) return asset;
} }
return null; return null;
} }
@Override @Override
public MultiAsset getAllAssets(AssetLocation location) { public MultiAsset getAllAssets(AssetLocation location) {
ObjectList<IAsset> result = new ObjectArrayList<>(); ObjectList<IAsset> result = new ObjectArrayList<>();
for(int i = packages.size()-1;i>=0;i--) { for(int i = packages.size()-1;i>=0;i--) {
IAsset asset = packages.get(i).getAsset(location); IAsset asset = packages.get(i).getAsset(location);
if(asset != null) result.add(asset); if(asset != null) result.add(asset);
} }
return new MultiAsset(result); return new MultiAsset(result);
} }
@Override @Override
public Map<AssetLocation, IAsset> listAssets(String folder, Predicate<AssetLocation> filter) { public Map<AssetLocation, IAsset> listAssets(String folder, Predicate<AssetLocation> filter) {
AssetLocation base = AssetLocation.of(domain, folder); AssetLocation base = AssetLocation.of(domain, folder);
Map<AssetLocation, IAsset> result = Object2ObjectMap.builder().linkedMap(); Map<AssetLocation, IAsset> result = Object2ObjectMap.builder().linkedMap();
for(int i = packages.size()-1;i>=0;i--) { for(int i = packages.size()-1;i>=0;i--) {
packages.get(i).gatherAssets(base, (K, V) -> { packages.get(i).gatherAssets(base, (K, V) -> {
if(filter.test(K)) result.putIfAbsent(K, V); if(filter.test(K)) result.putIfAbsent(K, V);
}); });
} }
return result; return result;
} }
@Override @Override
public Map<AssetLocation, MultiAsset> listAllAssets(String folder, Predicate<AssetLocation> filter) { public Map<AssetLocation, MultiAsset> listAllAssets(String folder, Predicate<AssetLocation> filter) {
AssetLocation base = AssetLocation.of(domain, folder); AssetLocation base = AssetLocation.of(domain, folder);
Object2ObjectMap<AssetLocation, ObjectList<IAsset>> assets = Object2ObjectMap.builder().linkedMap(); Object2ObjectMap<AssetLocation, ObjectList<IAsset>> assets = Object2ObjectMap.builder().linkedMap();
for(int i = packages.size()-1;i>=0;i--) { for(int i = packages.size()-1;i>=0;i--) {
packages.get(i).gatherAssets(base, (K, V) -> { packages.get(i).gatherAssets(base, (K, V) -> {
if(filter.test(K)) assets.supplyIfAbsent(K, ObjectArrayList::new).add(V); if(filter.test(K)) assets.supplyIfAbsent(K, ObjectArrayList::new).add(V);
}); });
} }
Map<AssetLocation, MultiAsset> result = Object2ObjectMap.builder().linkedMap(); Map<AssetLocation, MultiAsset> result = Object2ObjectMap.builder().linkedMap();
for(Object2ObjectMap.Entry<AssetLocation, ObjectList<IAsset>> entry : Object2ObjectMaps.fastIterable(assets)) { for(Object2ObjectMap.Entry<AssetLocation, ObjectList<IAsset>> entry : Object2ObjectMaps.fastIterable(assets)) {
result.put(entry.getKey(), new MultiAsset(entry.getValue())); result.put(entry.getKey(), new MultiAsset(entry.getValue()));
} }
return result; return result;
} }
} }
} }

View File

@ -1,51 +1,51 @@
package speiger.src.coreengine.assets.impl; package speiger.src.coreengine.assets.impl;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.List; import java.util.List;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import speiger.src.coreengine.assets.AssetLocation; import speiger.src.coreengine.assets.AssetLocation;
import speiger.src.coreengine.assets.base.IAsset; import speiger.src.coreengine.assets.base.IAsset;
import speiger.src.coreengine.assets.base.IAssetPackage; import speiger.src.coreengine.assets.base.IAssetPackage;
import speiger.src.coreengine.assets.base.IAssetParser; import speiger.src.coreengine.assets.base.IAssetParser;
import speiger.src.coreengine.utils.helpers.JsonUtil; import speiger.src.coreengine.utils.helpers.JsonUtil;
public class SimpleAsset extends BaseAsset { public class SimpleAsset extends BaseAsset {
Path path; Path path;
public SimpleAsset(AssetLocation location, IAssetPackage owner, Path path) { public SimpleAsset(AssetLocation location, IAssetPackage owner, Path path) {
super(location, owner); super(location, owner);
this.path = path; this.path = path;
} }
@Override @Override
public IAsset subAsset(String alternative) { public IAsset subAsset(String alternative) {
Path newPath = path.resolveSibling(path.getFileName().toString()+"."+alternative); Path newPath = path.resolveSibling(path.getFileName().toString()+"."+alternative);
return Files.exists(newPath) ? new SimpleAsset(location.alternate(alternative), owner, newPath) : null; return Files.exists(newPath) ? new SimpleAsset(location.alternate(alternative), owner, newPath) : null;
} }
@Override @Override
public InputStream stream() throws IOException { return markClosed(Files.newInputStream(path)); } public InputStream stream() throws IOException { return markClosed(Files.newInputStream(path)); }
@Override @Override
public ByteBuffer bytes() throws IOException { return ByteBuffer.wrap(Files.readAllBytes(path)); } public ByteBuffer bytes() throws IOException { return ByteBuffer.wrap(Files.readAllBytes(path)); }
@Override @Override
public BufferedImage texture() throws Exception { return ImageIO.read(stream()); } public BufferedImage texture() throws Exception { return ImageIO.read(stream()); }
@Override @Override
public BufferedReader reader() throws IOException { return markClosed(Files.newBufferedReader(path)); } public BufferedReader reader() throws IOException { return markClosed(Files.newBufferedReader(path)); }
@Override @Override
public List<String> lines() throws IOException { return Files.readAllLines(path); } public List<String> lines() throws IOException { return Files.readAllLines(path); }
@Override @Override
public JsonObject json() throws IOException { return JsonUtil.loadFile(path); } public JsonObject json() throws IOException { return JsonUtil.loadFile(path); }
@Override @Override
public <T> T custom(IAssetParser<T> parser) throws IOException { return parser.parseAsset(path, closeable::add); } public <T> T custom(IAssetParser<T> parser) throws IOException { return parser.parseAsset(path, closeable::add); }
} }

View File

@ -1,107 +1,107 @@
package speiger.src.coreengine.assets.impl; package speiger.src.coreengine.assets.impl;
import java.io.IOException; import java.io.IOException;
import java.nio.file.DirectoryStream; import java.nio.file.DirectoryStream;
import java.nio.file.FileSystem; import java.nio.file.FileSystem;
import java.nio.file.FileSystems; import java.nio.file.FileSystems;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.attribute.FileTime; import java.nio.file.attribute.FileTime;
import java.util.List; import java.util.List;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
import java.util.stream.Stream; import java.util.stream.Stream;
import speiger.src.collections.objects.lists.ObjectArrayList; import speiger.src.collections.objects.lists.ObjectArrayList;
import speiger.src.coreengine.assets.AssetLocation; import speiger.src.coreengine.assets.AssetLocation;
import speiger.src.coreengine.assets.base.IAsset; import speiger.src.coreengine.assets.base.IAsset;
import speiger.src.coreengine.assets.base.IAssetPackage; import speiger.src.coreengine.assets.base.IAssetPackage;
import speiger.src.coreengine.utils.collections.iterators.IterableWrapper; import speiger.src.coreengine.utils.collections.iterators.IterableWrapper;
public class ZipAssetPackage implements IAssetPackage { public class ZipAssetPackage implements IAssetPackage {
Path baseFolder; Path baseFolder;
FileSystem cache; FileSystem cache;
public ZipAssetPackage(Path baseFolder) { public ZipAssetPackage(Path baseFolder) {
this.baseFolder = baseFolder; this.baseFolder = baseFolder;
} }
@Override @Override
public void close() { public void close() {
if(cache != null) { if(cache != null) {
try { cache.close(); } try { cache.close(); }
catch(Exception e) { e.printStackTrace(); } catch(Exception e) { e.printStackTrace(); }
cache = null; cache = null;
} }
} }
@Override @Override
public void getModifiedTime(String domain, BiConsumer<AssetLocation, FileTime> accept) { public void getModifiedTime(String domain, BiConsumer<AssetLocation, FileTime> accept) {
try { try {
try(FileSystem system = FileSystems.newFileSystem(baseFolder)) { try(FileSystem system = FileSystems.newFileSystem(baseFolder)) {
Path start = system.getPath("assets"); Path start = system.getPath("assets");
for(Path path : IterableWrapper.wrap(Files.walk(start.resolve(domain)).filter(Files::isRegularFile).iterator())) { for(Path path : IterableWrapper.wrap(Files.walk(start.resolve(domain)).filter(Files::isRegularFile).iterator())) {
accept.accept(AssetLocation.of(domain, start.relativize(path).toString().replace("\\", "/")), Files.getLastModifiedTime(path)); accept.accept(AssetLocation.of(domain, start.relativize(path).toString().replace("\\", "/")), Files.getLastModifiedTime(path));
} }
} }
} }
catch(IOException e) { e.printStackTrace(); } catch(IOException e) { e.printStackTrace(); }
} }
protected FileSystem getReference() throws IOException { protected FileSystem getReference() throws IOException {
if(cache == null) cache = FileSystems.newFileSystem(baseFolder); if(cache == null) cache = FileSystems.newFileSystem(baseFolder);
return cache; return cache;
} }
@Override @Override
public List<String> getDomains() { public List<String> getDomains() {
List<String> domains = new ObjectArrayList<>(); List<String> domains = new ObjectArrayList<>();
try(FileSystem system = FileSystems.newFileSystem(baseFolder)) { try(FileSystem system = FileSystems.newFileSystem(baseFolder)) {
try(DirectoryStream<Path> dirs = Files.newDirectoryStream(system.getPath("assets"))) { try(DirectoryStream<Path> dirs = Files.newDirectoryStream(system.getPath("assets"))) {
for(Path path : dirs) { for(Path path : dirs) {
String s = path.getFileName().toString(); String s = path.getFileName().toString();
domains.add(s.substring(0, s.length())); domains.add(s.substring(0, s.length()));
} }
} }
catch(Exception e) { catch(Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
} }
catch(Exception e) { catch(Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
return domains; return domains;
} }
@Override @Override
public IAsset getAsset(AssetLocation location) { public IAsset getAsset(AssetLocation location) {
try { try {
Path path = getReference().getPath(location.actualLocation()); Path path = getReference().getPath(location.actualLocation());
return Files.exists(path) ? new SimpleAsset(location, this, path) : null; return Files.exists(path) ? new SimpleAsset(location, this, path) : null;
} }
catch(Exception e) { catch(Exception e) {
e.printStackTrace(); e.printStackTrace();
return null; return null;
} }
} }
@Override @Override
public void gatherAssets(AssetLocation folder, BiConsumer<AssetLocation, IAsset> result) { public void gatherAssets(AssetLocation folder, BiConsumer<AssetLocation, IAsset> result) {
try { try {
FileSystem system = getReference(); FileSystem system = getReference();
Path start = system.getPath(folder.actualLocation()); Path start = system.getPath(folder.actualLocation());
if(Files.notExists(start)) return; if(Files.notExists(start)) return;
try(Stream<Path> stream = Files.walk(start).filter(Files::isRegularFile)) { try(Stream<Path> stream = Files.walk(start).filter(Files::isRegularFile)) {
for(Path path : IterableWrapper.wrap(stream.iterator())) { for(Path path : IterableWrapper.wrap(stream.iterator())) {
AssetLocation location = folder.subAsset(start.relativize(path).toString().replace("\\", "/")); AssetLocation location = folder.subAsset(start.relativize(path).toString().replace("\\", "/"));
result.accept(location, new SimpleAsset(location, this, path)); result.accept(location, new SimpleAsset(location, this, path));
} }
} }
catch(IOException e) { catch(IOException e) {
e.printStackTrace(); e.printStackTrace();
} }
} }
catch(Exception e) { catch(Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
} }
} }

View File

@ -1,106 +1,106 @@
package speiger.src.coreengine.assets.language; package speiger.src.coreengine.assets.language;
import java.util.Map; import java.util.Map;
import com.google.gson.JsonArray; import com.google.gson.JsonArray;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import speiger.src.collections.objects.maps.impl.hash.Object2ObjectOpenHashMap; import speiger.src.collections.objects.maps.impl.hash.Object2ObjectOpenHashMap;
import speiger.src.collections.objects.utils.maps.Object2ObjectMaps; import speiger.src.collections.objects.utils.maps.Object2ObjectMaps;
import speiger.src.coreengine.assets.AssetLocation; import speiger.src.coreengine.assets.AssetLocation;
import speiger.src.coreengine.assets.AssetManager; import speiger.src.coreengine.assets.AssetManager;
import speiger.src.coreengine.assets.base.MultiAsset; import speiger.src.coreengine.assets.base.MultiAsset;
import speiger.src.coreengine.assets.reloader.IReloadableResource; import speiger.src.coreengine.assets.reloader.IReloadableResource;
public class LanguageManager implements IReloadableResource { public class LanguageManager implements IReloadableResource {
final AssetLocation location = AssetLocation.of("lang"); final AssetLocation location = AssetLocation.of("lang");
Map<String, Language> languages = new Object2ObjectOpenHashMap<>(); Map<String, Language> languages = new Object2ObjectOpenHashMap<>();
AssetManager assets; AssetManager assets;
String currentLanguage; String currentLanguage;
@Override @Override
public void reload() { public void reload() {
languages.clear(); languages.clear();
try(MultiAsset langs = assets.getAllAssets(location.subAsset("langs.json"))) { try(MultiAsset langs = assets.getAllAssets(location.subAsset("langs.json"))) {
for(int i = 0,m = langs.size();i < m;i++) { for(int i = 0,m = langs.size();i < m;i++) {
preLoadLanguage(langs.get(i).json()); preLoadLanguage(langs.get(i).json());
} }
} }
catch(Exception e) { catch(Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
if(loadLanguage(currentLanguage)) { if(loadLanguage(currentLanguage)) {
I18n.CURRENT_LANGUAGE = languages.get(currentLanguage); I18n.CURRENT_LANGUAGE = languages.get(currentLanguage);
} }
else { else {
Language dummy = new Language("en_US", "English"); Language dummy = new Language("en_US", "English");
dummy.load(Object2ObjectMaps.empty()); dummy.load(Object2ObjectMaps.empty());
I18n.CURRENT_LANGUAGE = dummy; I18n.CURRENT_LANGUAGE = dummy;
} }
} }
public boolean setLanguage(String lang) { public boolean setLanguage(String lang) {
if(loadLanguage(lang)) { if(loadLanguage(lang)) {
I18n.CURRENT_LANGUAGE = languages.get(lang); I18n.CURRENT_LANGUAGE = languages.get(lang);
Language currentLang = languages.get(currentLanguage); Language currentLang = languages.get(currentLanguage);
currentLanguage = lang; currentLanguage = lang;
if(currentLang != null) currentLang.clear(); if(currentLang != null) currentLang.clear();
return true; return true;
} }
return false; return false;
} }
protected boolean loadLanguage(String loadingLang) { protected boolean loadLanguage(String loadingLang) {
Language lang = languages.get(loadingLang); Language lang = languages.get(loadingLang);
if(lang == null) return false; if(lang == null) return false;
Map<String, String> map = new Object2ObjectOpenHashMap<>(); Map<String, String> map = new Object2ObjectOpenHashMap<>();
loadLanguage(loadingLang, map); loadLanguage(loadingLang, map);
if(loadingLang != "en_US") loadLanguage("en_US", map); if(loadingLang != "en_US") loadLanguage("en_US", map);
lang.load(map); lang.load(map);
return true; return true;
} }
protected void loadLanguage(String lang, Map<String, String> data) { protected void loadLanguage(String lang, Map<String, String> data) {
try(MultiAsset language = assets.getAllAssets(location.subAsset(lang+".lang"))) { try(MultiAsset language = assets.getAllAssets(location.subAsset(lang+".lang"))) {
for(int i = 0,m = language.size();i < m;i++) { for(int i = 0,m = language.size();i < m;i++) {
try { try {
for(Map.Entry<String, JsonElement> element : language.get(i).json().entrySet()) { for(Map.Entry<String, JsonElement> element : language.get(i).json().entrySet()) {
loadEntry(element.getKey(), element.getValue(), data); loadEntry(element.getKey(), element.getValue(), data);
} }
} }
catch(Exception e) { catch(Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
} }
} }
catch(Exception e) { catch(Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
} }
protected void loadEntry(String basePath, JsonElement el, Map<String, String> data) { protected void loadEntry(String basePath, JsonElement el, Map<String, String> data) {
if(el.isJsonPrimitive()) data.putIfAbsent(basePath, el.getAsString()); if(el.isJsonPrimitive()) data.putIfAbsent(basePath, el.getAsString());
else if(el.isJsonObject()) { else if(el.isJsonObject()) {
for(Map.Entry<String, JsonElement> elements : el.getAsJsonObject().entrySet()) { for(Map.Entry<String, JsonElement> elements : el.getAsJsonObject().entrySet()) {
String key = elements.getKey(); String key = elements.getKey();
if(key.isEmpty()) loadEntry(basePath, elements.getValue(), data); if(key.isEmpty()) loadEntry(basePath, elements.getValue(), data);
else loadEntry(basePath+"."+key, elements.getValue(), data); else loadEntry(basePath+"."+key, elements.getValue(), data);
} }
} }
} }
protected void preLoadLanguage(JsonObject object) { protected void preLoadLanguage(JsonObject object) {
JsonArray array = object.getAsJsonArray("languages"); JsonArray array = object.getAsJsonArray("languages");
if(array == null) return; if(array == null) return;
for(int i = 0,m = array.size();i < m;i++) { for(int i = 0,m = array.size();i < m;i++) {
JsonArray subArray = array.get(i).getAsJsonArray(); JsonArray subArray = array.get(i).getAsJsonArray();
if(subArray.size() != 2) continue; if(subArray.size() != 2) continue;
String key = subArray.get(0).getAsString(); String key = subArray.get(0).getAsString();
String value = subArray.get(1).getAsString(); String value = subArray.get(1).getAsString();
if(key.length() != 2 || value.length() > 16) continue; if(key.length() != 2 || value.length() > 16) continue;
languages.computeIfAbsent(key, T -> new Language(key, value)); languages.computeIfAbsent(key, _ -> new Language(key, value));
} }
} }
} }

View File

@ -1,16 +0,0 @@
package speiger.src.coreengine.math.vector;
import speiger.src.coreengine.math.vector.floats.Vec2f;
import speiger.src.coreengine.math.vector.floats.Vec3f;
public class VectorUtil
{
public static float barryCentric(Vec3f p1, Vec3f p2, Vec3f p3, Vec2f pos)
{
float det = (p2.z() - p3.z()) * (p1.x() - p3.x()) + (p3.x() - p2.x()) * (p1.z() - p3.z());
float l1 = ((p2.z() - p3.z()) * (pos.x() - p3.x()) + (p3.x() - p2.x()) * (pos.y() - p3.z())) / det;
float l2 = ((p3.z() - p1.z()) * (pos.x() - p3.x()) + (p1.x() - p3.x()) * (pos.y() - p3.z())) / det;
float l3 = 1.0f - l1 - l2;
return l1 * p1.y() + l2 * p2.y() + l3 * p3.y();
}
}

View File

@ -1,51 +0,0 @@
package speiger.src.coreengine.math.vector.bytes;
import java.util.Objects;
public class Vec2bImmutable implements Vec2b {
final byte x;
final byte y;
public Vec2bImmutable() {
x = 0;
y = 0;
}
public Vec2bImmutable(byte value) {
x = value;
y = value;
}
public Vec2bImmutable(byte x, byte y) {
this.x = x;
this.y = y;
}
@Override
public boolean isMutable() { return false; }
@Override
public byte x() { return x; }
@Override
public byte y() { return y; }
@Override
public Vec2b x(byte x) { return this.x == x ? this : Vec2b.of(x, y); }
@Override
public Vec2b y(byte y) { return this.y == y ? this : Vec2b.of(x, y); }
@Override
public Vec2b copy() { return Vec2b.of(this); }
@Override
public Vec2b set(byte x, byte y) { return this.x == x && this.y == y ? this : Vec2b.of(x, y); }
@Override
public int hashCode() { return Objects.hash(x, y); }
@Override
public boolean equals(Object obj) {
if(obj instanceof Vec2b) {
Vec2b vec = (Vec2b)obj;
return vec.x() == x && vec.y() == y;
}
return false;
}
@Override
public String toString() { return "Vec2b[x="+x+", y="+y+"]"; }
}

View File

@ -1,59 +0,0 @@
package speiger.src.coreengine.math.vector.bytes;
import java.util.Objects;
public class Vec3bImmutable implements Vec3b {
final byte x;
final byte y;
final byte z;
public Vec3bImmutable() {
x = 0;
y = 0;
z = 0;
}
public Vec3bImmutable(byte value) {
x = value;
y = value;
z = value;
}
public Vec3bImmutable(byte x, byte y, byte z) {
this.x = x;
this.y = y;
this.z = z;
}
@Override
public boolean isMutable() { return false; }
@Override
public byte x() { return x; }
@Override
public byte y() { return y; }
@Override
public byte z() { return z; }
@Override
public Vec3b x(byte x) { return this.x == x ? this : Vec3b.of(x, y, z); }
@Override
public Vec3b y(byte y) { return this.y == y ? this : Vec3b.of(x, y, z); }
@Override
public Vec3b z(byte z) { return this.z == z ? this : Vec3b.of(x, y, z); }
@Override
public Vec3b copy() { return Vec3b.of(this); }
@Override
public Vec3b set(byte x, byte y, byte z) { return this.x == x && this.y == y && this.z == z ? this : Vec3b.of(x, y, z); }
@Override
public int hashCode() { return Objects.hash(x, y, z); }
@Override
public boolean equals(Object obj) {
if(obj instanceof Vec3b) {
Vec3b vec = (Vec3b)obj;
return vec.x() == x && vec.y() == y && vec.z() == z;
}
return false;
}
@Override
public String toString() { return "Vec3b[x="+x+", y="+y+", z="+z+"]"; }
}

View File

@ -1,68 +0,0 @@
package speiger.src.coreengine.math.vector.bytes;
import java.util.Objects;
public class Vec4bImmutable implements Vec4b {
final byte x;
final byte y;
final byte z;
final byte w;
public Vec4bImmutable() {
x = 0;
y = 0;
z = 0;
w = 0;
}
public Vec4bImmutable(byte value) {
x = value;
y = value;
z = value;
w = value;
}
public Vec4bImmutable(byte x, byte y, byte z, byte w) {
this.x = x;
this.y = y;
this.z = z;
this.w = w;
}
@Override
public boolean isMutable() { return false; }
@Override
public byte x() { return x; }
@Override
public byte y() { return y; }
@Override
public byte z() { return z; }
@Override
public byte w() { return w; }
@Override
public Vec4b x(byte x) { return this.x == x ? this : Vec4b.of(x, y, z, w); }
@Override
public Vec4b y(byte y) { return this.y == y ? this : Vec4b.of(x, y, z, w); }
@Override
public Vec4b z(byte z) { return this.z == z ? this : Vec4b.of(x, y, z, w); }
@Override
public Vec4b w(byte w) { return this.w == w ? this : Vec4b.of(x, y, z, w); }
@Override
public Vec4b copy() { return Vec4b.of(this); }
@Override
public Vec4b set(byte x, byte y, byte z, byte w) { return this.x == x && this.y == y && this.z == z && this.w == w ? this : Vec4b.of(x, y, z, w); }
@Override
public int hashCode() { return Objects.hash(x, y, z, w); }
@Override
public boolean equals(Object obj) {
if(obj instanceof Vec4b) {
Vec4b vec = (Vec4b)obj;
return vec.x() == x && vec.y() == y && vec.z() == z && vec.w() == w;
}
return false;
}
@Override
public String toString() { return "Vec4b[x="+x+", y="+y+", z="+z+", w="+w+"]"; }
}

View File

@ -1,118 +1,118 @@
package speiger.src.coreengine.rendering.gui.font; package speiger.src.coreengine.rendering.gui.font;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.function.BiFunction; import java.util.function.BiFunction;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import speiger.src.collections.floats.maps.interfaces.Float2ObjectMap; import speiger.src.collections.floats.maps.interfaces.Float2ObjectMap;
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;
import speiger.src.collections.objects.maps.interfaces.Object2ObjectMap; import speiger.src.collections.objects.maps.interfaces.Object2ObjectMap;
import speiger.src.coreengine.assets.AssetFilter; import speiger.src.coreengine.assets.AssetFilter;
import speiger.src.coreengine.assets.AssetLocation; import speiger.src.coreengine.assets.AssetLocation;
import speiger.src.coreengine.assets.base.IAsset; import speiger.src.coreengine.assets.base.IAsset;
import speiger.src.coreengine.assets.base.IAssetProvider; import speiger.src.coreengine.assets.base.IAssetProvider;
import speiger.src.coreengine.assets.base.MultiAsset; import speiger.src.coreengine.assets.base.MultiAsset;
import speiger.src.coreengine.assets.base.SteppedReloadableAsset; import speiger.src.coreengine.assets.base.SteppedReloadableAsset;
import speiger.src.coreengine.rendering.gui.font.glyth.Glyth; import speiger.src.coreengine.rendering.gui.font.glyth.Glyth;
import speiger.src.coreengine.rendering.gui.font.glyth.IGlythSheetInfo; import speiger.src.coreengine.rendering.gui.font.glyth.IGlythSheetInfo;
import speiger.src.coreengine.rendering.gui.font.providers.FreeTypeProvider; import speiger.src.coreengine.rendering.gui.font.providers.FreeTypeProvider;
import speiger.src.coreengine.rendering.gui.font.providers.IFontProvider; import speiger.src.coreengine.rendering.gui.font.providers.IFontProvider;
import speiger.src.coreengine.rendering.gui.font.providers.STBTrueTypeProvider; import speiger.src.coreengine.rendering.gui.font.providers.STBTrueTypeProvider;
import speiger.src.coreengine.utils.helpers.JsonUtil; import speiger.src.coreengine.utils.helpers.JsonUtil;
public class FontManager extends SteppedReloadableAsset<Map<AssetLocation, ObjectList<IFontProvider>>> { public class FontManager extends SteppedReloadableAsset<Map<AssetLocation, ObjectList<IFontProvider>>> {
private static final int TEXTURE_SIZE = 512; private static final int TEXTURE_SIZE = 512;
private static final AssetFilter FILTER = AssetFilter.json("font"); private static final AssetFilter FILTER = AssetFilter.json("font");
Float2ObjectMap<Font> cachedFonts = Float2ObjectMap.builder().map(); Float2ObjectMap<Font> cachedFonts = Float2ObjectMap.builder().map();
Map<AssetLocation, FontGroup> fonts = Object2ObjectMap.builder().linkedMap(); Map<AssetLocation, FontGroup> fonts = Object2ObjectMap.builder().linkedMap();
Map<String, BiFunction<JsonObject, IAssetProvider, IFontProvider>> fontParsers = Object2ObjectMap.builder().map(); Map<String, BiFunction<JsonObject, IAssetProvider, IFontProvider>> fontParsers = Object2ObjectMap.builder().map();
List<Runnable> listeners = new ObjectArrayList<>(); List<Runnable> listeners = new ObjectArrayList<>();
List<FontTexture> textures = new ObjectArrayList<>(); List<FontTexture> textures = new ObjectArrayList<>();
public FontManager() { public FontManager() {
registerParser("stb-ttf", STBTrueTypeProvider::create); registerParser("stb-ttf", STBTrueTypeProvider::create);
registerParser("free-ttf", FreeTypeProvider::load); registerParser("free-ttf", FreeTypeProvider::load);
} }
public void registerParser(String id, BiFunction<JsonObject, IAssetProvider, IFontProvider> parser) { public void registerParser(String id, BiFunction<JsonObject, IAssetProvider, IFontProvider> parser) {
fontParsers.putIfAbsent(id, parser); fontParsers.putIfAbsent(id, parser);
} }
@Override @Override
public String getName() { return "Font Manager"; } public String getName() { return "Font Manager"; }
@Override @Override
protected Map<AssetLocation, ObjectList<IFontProvider>> prepare(IAssetProvider provider) { protected Map<AssetLocation, ObjectList<IFontProvider>> prepare(IAssetProvider provider) {
Map<AssetLocation, IFontProvider> loadingCache = Object2ObjectMap.builder().linkedMap(); Map<AssetLocation, IFontProvider> loadingCache = Object2ObjectMap.builder().linkedMap();
Object2ObjectMap<AssetLocation, ObjectList<IFontProvider>> providers = Object2ObjectMap.builder().linkedMap(); Object2ObjectMap<AssetLocation, ObjectList<IFontProvider>> providers = Object2ObjectMap.builder().linkedMap();
for(Entry<AssetLocation, MultiAsset> entry : FILTER.multiRoot(provider).entrySet()) { for(Entry<AssetLocation, MultiAsset> entry : FILTER.multiRoot(provider).entrySet()) {
AssetLocation id = entry.getKey(); AssetLocation id = entry.getKey();
for(JsonObject obj : entry.getValue().map(IAsset::json, JsonObject::new)) { for(JsonObject obj : entry.getValue().map(IAsset::json, JsonObject::new)) {
JsonUtil.iterateValues(obj.get("providers"), T -> { JsonUtil.iterateValues(obj.get("providers"), T -> {
AssetLocation location = AssetLocation.tryOf(T.getAsString()); AssetLocation location = AssetLocation.tryOf(T.getAsString());
if(location == null || !location.isInFolder()) return; if(location == null || !location.isInFolder()) return;
IFontProvider font = loadingCache.computeIfAbsent(location.prefix("font"), E -> getFont(E, provider)); IFontProvider font = loadingCache.computeIfAbsent(location.prefix("font"), E -> getFont(E, provider));
if(font == null) return; if(font == null) return;
providers.supplyIfAbsent(FILTER.id(id), ObjectArrayList::new).add(font); providers.supplyIfAbsent(FILTER.id(id), ObjectArrayList::new).add(font);
}); });
} }
} }
return providers; return providers;
} }
@Override @Override
protected void apply(Map<AssetLocation, ObjectList<IFontProvider>> value, IAssetProvider provider) { protected void apply(Map<AssetLocation, ObjectList<IFontProvider>> value, IAssetProvider provider) {
reset(); reset();
value.forEach((K, V) -> fonts.put(K, new FontGroup(K, V))); value.forEach((K, V) -> fonts.put(K, new FontGroup(K, V)));
} }
@Override @Override
public void destroy() { public void destroy() {
reset(); reset();
listeners.clear(); listeners.clear();
} }
private void reset() { private void reset() {
listeners.forEach(Runnable::run); listeners.forEach(Runnable::run);
textures.forEach(FontTexture::delete); textures.forEach(FontTexture::delete);
textures.clear(); textures.clear();
fonts.values().forEach(FontGroup::close); fonts.values().forEach(FontGroup::close);
fonts.clear(); fonts.clear();
cachedFonts.clear(); cachedFonts.clear();
} }
public Font createFont() { public Font createFont() {
return createFont(1F); return createFont(1F);
} }
public Font createFont(float oversample) { public Font createFont(float oversample) {
return cachedFonts.computeIfAbsent(oversample, T -> new Font(fonts, this::stitch, T, listeners::add)); return cachedFonts.computeIfAbsent(oversample, T -> new Font(fonts, this::stitch, T, listeners::add));
} }
private Glyth stitch(IGlythSheetInfo info) { private Glyth stitch(IGlythSheetInfo info) {
for(int i = 0,m=textures.size();i<m;i++) { for(int i = 0,m=textures.size();i<m;i++) {
Glyth glyth = textures.get(i).build(info); Glyth glyth = textures.get(i).build(info);
if(glyth != null) return glyth; if(glyth != null) return glyth;
} }
FontTexture texture = new FontTexture(TEXTURE_SIZE, info.isColored()); FontTexture texture = new FontTexture(TEXTURE_SIZE, info.isColored());
textures.add(texture); textures.add(texture);
Glyth glyth = texture.build(info); Glyth glyth = texture.build(info);
return glyth; return glyth;
} }
private IFontProvider getFont(AssetLocation location, IAssetProvider provider) { private IFontProvider getFont(AssetLocation location, IAssetProvider provider) {
try(IAsset asset = provider.getAsset(location)) { try(IAsset asset = provider.getAsset(location)) {
JsonObject obj = asset.json(); JsonObject obj = asset.json();
BiFunction<JsonObject, IAssetProvider, IFontProvider> builder = fontParsers.get(obj.get("type").getAsString()); BiFunction<JsonObject, IAssetProvider, IFontProvider> builder = fontParsers.get(obj.get("type").getAsString());
return builder == null ? null : builder.apply(obj, provider); return builder == null ? null : builder.apply(obj, provider);
} }
catch(Exception e) { catch(Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
return null; return null;
} }
} }

View File

@ -1,297 +1,297 @@
package speiger.src.coreengine.rendering.gui.font.providers; package speiger.src.coreengine.rendering.gui.font.providers;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import org.lwjgl.PointerBuffer; import org.lwjgl.PointerBuffer;
import org.lwjgl.system.MemoryStack; import org.lwjgl.system.MemoryStack;
import org.lwjgl.system.MemoryUtil; import org.lwjgl.system.MemoryUtil;
import org.lwjgl.util.freetype.FT_Bitmap; import org.lwjgl.util.freetype.FT_Bitmap;
import org.lwjgl.util.freetype.FT_Face; import org.lwjgl.util.freetype.FT_Face;
import org.lwjgl.util.freetype.FT_GlyphSlot; import org.lwjgl.util.freetype.FT_GlyphSlot;
import org.lwjgl.util.freetype.FT_Vector; import org.lwjgl.util.freetype.FT_Vector;
import org.lwjgl.util.freetype.FreeType; import org.lwjgl.util.freetype.FreeType;
import org.lwjgl.util.harfbuzz.HarfBuzz; import org.lwjgl.util.harfbuzz.HarfBuzz;
import org.lwjgl.util.harfbuzz.hb_glyph_position_t; import org.lwjgl.util.harfbuzz.hb_glyph_position_t;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import speiger.src.collections.ints.sets.IntOpenHashSet; import speiger.src.collections.ints.sets.IntOpenHashSet;
import speiger.src.collections.ints.sets.IntSet; import speiger.src.collections.ints.sets.IntSet;
import speiger.src.collections.longs.misc.pairs.LongObjectPair; import speiger.src.collections.longs.misc.pairs.LongObjectPair;
import speiger.src.coreengine.assets.AssetLocation; import speiger.src.coreengine.assets.AssetLocation;
import speiger.src.coreengine.assets.base.IAsset; import speiger.src.coreengine.assets.base.IAsset;
import speiger.src.coreengine.assets.base.IAssetProvider; import speiger.src.coreengine.assets.base.IAssetProvider;
import speiger.src.coreengine.assets.parsers.NativeMemoryParser; import speiger.src.coreengine.assets.parsers.NativeMemoryParser;
import speiger.src.coreengine.rendering.gui.font.FontTexture; import speiger.src.coreengine.rendering.gui.font.FontTexture;
import speiger.src.coreengine.rendering.gui.font.glyth.Glyth; import speiger.src.coreengine.rendering.gui.font.glyth.Glyth;
import speiger.src.coreengine.rendering.gui.font.glyth.IGlythSheetInfo; import speiger.src.coreengine.rendering.gui.font.glyth.IGlythSheetInfo;
import speiger.src.coreengine.rendering.gui.font.glyth.UnbakedGlyth; import speiger.src.coreengine.rendering.gui.font.glyth.UnbakedGlyth;
import speiger.src.coreengine.rendering.gui.font.glyth.UnbakedGlyth.EmptyGlythData; import speiger.src.coreengine.rendering.gui.font.glyth.UnbakedGlyth.EmptyGlythData;
import speiger.src.coreengine.rendering.textures.custom.Drawable; import speiger.src.coreengine.rendering.textures.custom.Drawable;
import speiger.src.coreengine.utils.helpers.JsonUtil; import speiger.src.coreengine.utils.helpers.JsonUtil;
public class FreeTypeProvider implements IFontProvider { public class FreeTypeProvider implements IFontProvider {
FreeTypeInstance[] instance; FreeTypeInstance[] instance;
public FreeTypeProvider(FreeTypeInstance[] instance) { public FreeTypeProvider(FreeTypeInstance[] instance) {
this.instance = instance; this.instance = instance;
} }
public static IFontProvider create(AssetLocation location, IAssetProvider provider) { public static IFontProvider create(AssetLocation location, IAssetProvider provider) {
try(IAsset asset = provider.getAsset(location)) { try(IAsset asset = provider.getAsset(location)) {
return load(asset.json(), provider); return load(asset.json(), provider);
} }
catch(Exception e) { e.printStackTrace(); } catch(Exception e) { e.printStackTrace(); }
return null; return null;
} }
public static IFontProvider load(JsonObject data, IAssetProvider provider) { public static IFontProvider load(JsonObject data, IAssetProvider provider) {
long library = FreeTypeLibrary.get(); long library = FreeTypeLibrary.get();
if(library == 0L) return null; if(library == 0L) return null;
FreeTypeInstance[] instances = new FreeTypeInstance[4]; FreeTypeInstance[] instances = new FreeTypeInstance[4];
instances[0] = create(library, 0, data.getAsJsonObject("regular"), provider); instances[0] = create(library, 0, data.getAsJsonObject("regular"), provider);
if(instances[0] == null) return null; if(instances[0] == null) return null;
instances[1] = create(library, 1, data.getAsJsonObject("bold"), provider); instances[1] = create(library, 1, data.getAsJsonObject("bold"), provider);
instances[2] = create(library, 2, data.getAsJsonObject("italic"), provider); instances[2] = create(library, 2, data.getAsJsonObject("italic"), provider);
instances[3] = create(library, 3, data.getAsJsonObject("bold_italic"), provider); instances[3] = create(library, 3, data.getAsJsonObject("bold_italic"), provider);
return new FreeTypeProvider(instances); return new FreeTypeProvider(instances);
} }
private static FreeTypeInstance create(long library, int style, JsonObject obj, IAssetProvider provider) { private static FreeTypeInstance create(long library, int style, JsonObject obj, IAssetProvider provider) {
if(obj == null || !obj.has("file")) return null; if(obj == null || !obj.has("file")) return null;
AssetLocation location = AssetLocation.of(obj.get("file").getAsString()); AssetLocation location = AssetLocation.of(obj.get("file").getAsString());
float oversample = JsonUtil.getOrDefault(obj, "oversample", 1F); float oversample = JsonUtil.getOrDefault(obj, "oversample", 1F);
float shadowOffset = JsonUtil.getOrDefault(obj, "shadowOffset", 1F); float shadowOffset = JsonUtil.getOrDefault(obj, "shadowOffset", 1F);
float xOff = 0; float xOff = 0;
float yOff = 0; float yOff = 0;
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
JsonObject shift = obj.getAsJsonObject("offset"); JsonObject shift = obj.getAsJsonObject("offset");
if(shift != null) { if(shift != null) {
xOff = JsonUtil.getOrDefault(shift, "x", 0F); xOff = JsonUtil.getOrDefault(shift, "x", 0F);
yOff = JsonUtil.getOrDefault(shift, "y", 0F); yOff = JsonUtil.getOrDefault(shift, "y", 0F);
} }
JsonUtil.iterateValues(obj.get("skip"), T -> builder.append(T.getAsString())); JsonUtil.iterateValues(obj.get("skip"), T -> builder.append(T.getAsString()));
LongObjectPair<FT_Face> value = parse(location, provider, library); LongObjectPair<FT_Face> value = parse(location, provider, library);
if(value == null) return null; if(value == null) return null;
return new FreeTypeInstance(style, value.getLongKey(), value.getValue(), oversample, xOff, yOff, shadowOffset, builder.toString()); return new FreeTypeInstance(style, value.getLongKey(), value.getValue(), oversample, xOff, yOff, shadowOffset, builder.toString());
} }
private static LongObjectPair<FT_Face> parse(AssetLocation location, IAssetProvider provider, long library) { private static LongObjectPair<FT_Face> parse(AssetLocation location, IAssetProvider provider, long library) {
try(IAsset asset = provider.getAsset(location); MemoryStack stack = MemoryStack.stackPush()) { try(IAsset asset = provider.getAsset(location); MemoryStack stack = MemoryStack.stackPush()) {
ByteBuffer buffer = asset.custom(NativeMemoryParser.INSTANCE); ByteBuffer buffer = asset.custom(NativeMemoryParser.INSTANCE);
PointerBuffer facePointer = stack.mallocPointer(1); PointerBuffer facePointer = stack.mallocPointer(1);
if(FreeTypeLibrary.parseError(FreeType.FT_New_Memory_Face(library, buffer, 0L, facePointer), "Creating Font Face")) { if(FreeTypeLibrary.parseError(FreeType.FT_New_Memory_Face(library, buffer, 0L, facePointer), "Creating Font Face")) {
MemoryUtil.memFree(buffer); MemoryUtil.memFree(buffer);
return null; return null;
} }
FT_Face face = FT_Face.create(facePointer.get()); FT_Face face = FT_Face.create(facePointer.get());
String s = FreeType.FT_Get_Font_Format(face); String s = FreeType.FT_Get_Font_Format(face);
if(!"TrueType".equals(s)) { if(!"TrueType".equals(s)) {
MemoryUtil.memFree(buffer); MemoryUtil.memFree(buffer);
throw new IllegalStateException("Font type ["+s+"] is not true type"); throw new IllegalStateException("Font type ["+s+"] is not true type");
} }
if(FreeTypeLibrary.parseError(FreeType.FT_Select_Charmap(face, FreeType.FT_ENCODING_UNICODE), "Applying Unicode Encoding")) { if(FreeTypeLibrary.parseError(FreeType.FT_Select_Charmap(face, FreeType.FT_ENCODING_UNICODE), "Applying Unicode Encoding")) {
MemoryUtil.memFree(buffer); MemoryUtil.memFree(buffer);
return null; return null;
} }
return LongObjectPair.of(MemoryUtil.memAddress(buffer), face); return LongObjectPair.of(MemoryUtil.memAddress(buffer), face);
} }
catch(Exception exception) { catch(Exception exception) {
exception.printStackTrace(); exception.printStackTrace();
return null; return null;
} }
} }
@Override @Override
public UnbakedGlyth glythData(int codepoint, int style, float size, float oversample) { public UnbakedGlyth glythData(int codepoint, int style, float size, float oversample) {
FreeTypeInstance instance = this.instance[style & 0x3]; FreeTypeInstance instance = this.instance[style & 0x3];
return instance != null ? instance.gylthData(codepoint, size, oversample) : null; return instance != null ? instance.gylthData(codepoint, size, oversample) : null;
} }
@Override @Override
public void close() { public void close() {
for(int i = 0;i<4;i++) { for(int i = 0;i<4;i++) {
if(instance[i] != null) { if(instance[i] != null) {
instance[i].free(); instance[i].free();
} }
} }
instance = null; instance = null;
} }
public static class FreeTypeGlyth implements UnbakedGlyth { public static class FreeTypeGlyth implements UnbakedGlyth {
final FT_Face face; final FT_Face face;
final int width; final int width;
final int height; final int height;
final float xOff; final float xOff;
final float yOff; final float yOff;
final float oversample; final float oversample;
private final float advance; private final float advance;
final int glyth; final int glyth;
final int glythCodepoint; final int glythCodepoint;
final long harfBuzzFont; final long harfBuzzFont;
public FreeTypeGlyth(FT_Face face, long harfBuzzFont, float xOff, float yOff, int width, int height, float advance, float oversample, int glyth, int glythCodepoint) { public FreeTypeGlyth(FT_Face face, long harfBuzzFont, float xOff, float yOff, int width, int height, float advance, float oversample, int glyth, int glythCodepoint) {
this.face = face; this.face = face;
this.harfBuzzFont = harfBuzzFont; this.harfBuzzFont = harfBuzzFont;
this.width = width; this.width = width;
this.height = height; this.height = height;
this.oversample = oversample; this.oversample = oversample;
this.advance = advance / oversample; this.advance = advance / oversample;
this.xOff = xOff / oversample; this.xOff = xOff / oversample;
this.yOff = yOff / oversample; this.yOff = yOff / oversample;
this.glyth = glyth; this.glyth = glyth;
this.glythCodepoint = glythCodepoint; this.glythCodepoint = glythCodepoint;
} }
@Override @Override
public float advance() { public float advance() {
return advance; return advance;
} }
@Override @Override
public float kerning(int codepoint) { public float kerning(int codepoint) {
int index = FreeType.FT_Get_Char_Index(face, codepoint); int index = FreeType.FT_Get_Char_Index(face, codepoint);
if(index == 0) return 0; if(index == 0) return 0;
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
builder.append(Character.toChars(codepoint)); builder.append(Character.toChars(codepoint));
builder.append(Character.toChars(glythCodepoint)); builder.append(Character.toChars(glythCodepoint));
float hbresult = (getAdvance(Character.toString(codepoint)) - getAdvance(builder.toString())) / 64F; float hbresult = (getAdvance(Character.toString(codepoint)) - getAdvance(builder.toString())) / 64F;
return hbresult; return hbresult;
} }
private float getAdvance(String adv) { private float getAdvance(String adv) {
long id = HarfBuzz.hb_buffer_create(); long id = HarfBuzz.hb_buffer_create();
try { try {
HarfBuzz.hb_buffer_add_utf8(id, adv, 0, adv.length()); HarfBuzz.hb_buffer_add_utf8(id, adv, 0, adv.length());
HarfBuzz.hb_buffer_guess_segment_properties(id); HarfBuzz.hb_buffer_guess_segment_properties(id);
HarfBuzz.hb_shape(harfBuzzFont, id, null); HarfBuzz.hb_shape(harfBuzzFont, id, null);
hb_glyph_position_t.Buffer positions = HarfBuzz.hb_buffer_get_glyph_positions(id); hb_glyph_position_t.Buffer positions = HarfBuzz.hb_buffer_get_glyph_positions(id);
float result = positions.hasRemaining() ? positions.x_advance() : 0F; float result = positions.hasRemaining() ? positions.x_advance() : 0F;
HarfBuzz.hb_buffer_destroy(positions.address()); HarfBuzz.hb_buffer_destroy(positions.address());
return result; return result;
} }
finally { finally {
HarfBuzz.hb_buffer_destroy(id); HarfBuzz.hb_buffer_destroy(id);
} }
} }
@Override @Override
public Glyth bake(GlythBaker baker) { public Glyth bake(GlythBaker baker) {
return baker.bake(new IGlythSheetInfo() { return baker.bake(new IGlythSheetInfo() {
@Override @Override
public float xOffset() { return xOff; } public float xOffset() { return xOff; }
@Override @Override
public float yOffset() { return yOff; } public float yOffset() { return yOff; }
@Override @Override
public int width() { return width; } public int width() { return width; }
@Override @Override
public int height() { return height; } public int height() { return height; }
@Override @Override
public float oversample() { return oversample; } public float oversample() { return oversample; }
@Override @Override
public void upload(int texture, int x, int y) { public void upload(int texture, int x, int y) {
Drawable drawable = new Drawable(FontTexture.formatByColor(false), width, height); Drawable drawable = new Drawable(FontTexture.formatByColor(false), width, height);
if(drawable.drawFont(face, glyth)) { if(drawable.drawFont(face, glyth)) {
drawable.upload(texture, x, y, 0, 0, width, height); drawable.upload(texture, x, y, 0, 0, width, height);
} }
drawable.close(); drawable.close();
} }
@Override @Override
public boolean isColored() { return false; } public boolean isColored() { return false; }
}); });
} }
} }
public static class FreeTypeInstance { public static class FreeTypeInstance {
final int style; final int style;
long data; long data;
final FT_Face face; final FT_Face face;
IntSet skip = new IntOpenHashSet(); IntSet skip = new IntOpenHashSet();
final float oversample; final float oversample;
final float xOff; final float xOff;
final float yOff; final float yOff;
final float shadowOffset; final float shadowOffset;
final long harfBuzzFont; final long harfBuzzFont;
public FreeTypeInstance(int style, long data, FT_Face face, float oversample, float xOff, float yOff, float shadowOffset, String skip) { public FreeTypeInstance(int style, long data, FT_Face face, float oversample, float xOff, float yOff, float shadowOffset, String skip) {
this.style = style; this.style = style;
this.data = data; this.data = data;
this.face = face; this.face = face;
this.harfBuzzFont = HarfBuzz.hb_ft_font_create_referenced(face.address()); this.harfBuzzFont = HarfBuzz.hb_ft_font_create_referenced(face.address());
skip.codePoints().forEach(this.skip::add); skip.codePoints().forEach(this.skip::add);
this.oversample = oversample; this.oversample = oversample;
this.xOff = xOff; this.xOff = xOff;
this.yOff = yOff; this.yOff = yOff;
this.shadowOffset = shadowOffset; this.shadowOffset = shadowOffset;
try(MemoryStack stack = MemoryStack.stackPush()) { try(MemoryStack stack = MemoryStack.stackPush()) {
FT_Vector ft_vector = FT_Vector.malloc(stack).set(Math.round(oversample * xOff * 64F), Math.round(oversample * -yOff * 64F)); FT_Vector ft_vector = FT_Vector.malloc(stack).set(Math.round(oversample * xOff * 64F), Math.round(oversample * -yOff * 64F));
FreeType.FT_Set_Transform(face, null, ft_vector); FreeType.FT_Set_Transform(face, null, ft_vector);
} }
} }
public void free() { public void free() {
if(data == 0L) return; if(data == 0L) return;
FreeType.FT_Done_Face(face); FreeType.FT_Done_Face(face);
MemoryUtil.nmemFree(data); MemoryUtil.nmemFree(data);
data = 0L; data = 0L;
} }
public UnbakedGlyth gylthData(int codepoint, float size, float oversample) { public UnbakedGlyth gylthData(int codepoint, float size, float oversample) {
if(skip.contains(codepoint)) return null; if(skip.contains(codepoint)) return null;
int index = FreeType.FT_Get_Char_Index(face, codepoint); int index = FreeType.FT_Get_Char_Index(face, codepoint);
if(index == 0) return null; if(index == 0) return null;
oversample *= this.oversample; oversample *= this.oversample;
int pixels = Math.round(size * oversample); int pixels = Math.round(size * oversample);
if(FreeTypeLibrary.parseError(FreeType.FT_Set_Pixel_Sizes(face, 0, pixels), "Set Pixel Size")) return null; if(FreeTypeLibrary.parseError(FreeType.FT_Set_Pixel_Sizes(face, 0, pixels), "Set Pixel Size")) return null;
if(FreeTypeLibrary.parseError(FreeType.FT_Load_Glyph(face, index, FreeType.FT_LOAD_NO_BITMAP | FreeType.FT_LOAD_BITMAP_METRICS_ONLY), "Loading Glyth")) return null; if(FreeTypeLibrary.parseError(FreeType.FT_Load_Glyph(face, index, FreeType.FT_LOAD_NO_BITMAP | FreeType.FT_LOAD_BITMAP_METRICS_ONLY), "Loading Glyth")) return null;
FT_GlyphSlot slot = face.glyph(); FT_GlyphSlot slot = face.glyph();
if(slot == null) { if(slot == null) {
System.out.println("Glyth didn't load for some reason"); System.out.println("Glyth didn't load for some reason");
return null; return null;
} }
float advance = slot.advance().x() / 64F; float advance = slot.advance().x() / 64F;
FT_Bitmap bitmap = slot.bitmap(); FT_Bitmap bitmap = slot.bitmap();
int left = slot.bitmap_left(); int left = slot.bitmap_left();
int top = slot.bitmap_top(); int top = slot.bitmap_top();
int width = bitmap.width(); int width = bitmap.width();
int height = bitmap.rows(); int height = bitmap.rows();
if(width > 0 && height > 0) return new FreeTypeGlyth(face, harfBuzzFont, left, -top, width, height, advance, oversample, index, codepoint); if(width > 0 && height > 0) return new FreeTypeGlyth(face, harfBuzzFont, left, -top, width, height, advance, oversample, index, codepoint);
return new EmptyGlythData(advance / oversample); return new EmptyGlythData(advance / oversample);
} }
} }
public static class FreeTypeLibrary { public static class FreeTypeLibrary {
private static long pointer = 0L; private static long pointer = 0L;
public static long get() { public static long get() {
if(pointer == 0L) { if(pointer == 0L) {
try(MemoryStack stack = MemoryStack.stackPush()) { try(MemoryStack stack = MemoryStack.stackPush()) {
PointerBuffer pointBuffer = stack.callocPointer(1); PointerBuffer pointBuffer = stack.callocPointer(1);
int result = FreeType.FT_Init_FreeType(pointBuffer); int result = FreeType.FT_Init_FreeType(pointBuffer);
if(result != 0) { if(result != 0) {
throw new IllegalStateException(FreeType.FT_Error_String(result)); throw new IllegalStateException(FreeType.FT_Error_String(result));
} }
pointer = pointBuffer.get(); pointer = pointBuffer.get();
} }
} }
return pointer; return pointer;
} }
public static boolean parseError(int result, String action) { public static boolean parseError(int result, String action) {
if(result == 0) return false; if(result == 0) return false;
String error = FreeType.FT_Error_String(result); String error = FreeType.FT_Error_String(result);
System.out.println("Couldn't do ["+action+"] because of "+error); System.out.println("Couldn't do ["+action+"] because of "+error);
return true; return true;
} }
public static void close() { public static void close() {
if(pointer == 0L) return; if(pointer == 0L) return;
FreeType.FT_Done_Library(pointer); FreeType.FT_Done_Library(pointer);
pointer = 0L; pointer = 0L;
} }
} }
} }

View File

@ -1,214 +1,214 @@
package speiger.src.coreengine.rendering.gui.font.providers; package speiger.src.coreengine.rendering.gui.font.providers;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.IntBuffer; import java.nio.IntBuffer;
import org.lwjgl.stb.STBTTFontinfo; import org.lwjgl.stb.STBTTFontinfo;
import org.lwjgl.stb.STBTruetype; import org.lwjgl.stb.STBTruetype;
import org.lwjgl.system.MemoryStack; import org.lwjgl.system.MemoryStack;
import org.lwjgl.system.MemoryUtil; import org.lwjgl.system.MemoryUtil;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import speiger.src.collections.ints.sets.IntOpenHashSet; import speiger.src.collections.ints.sets.IntOpenHashSet;
import speiger.src.collections.ints.sets.IntSet; import speiger.src.collections.ints.sets.IntSet;
import speiger.src.coreengine.assets.AssetLocation; import speiger.src.coreengine.assets.AssetLocation;
import speiger.src.coreengine.assets.base.IAsset; import speiger.src.coreengine.assets.base.IAsset;
import speiger.src.coreengine.assets.base.IAssetProvider; import speiger.src.coreengine.assets.base.IAssetProvider;
import speiger.src.coreengine.assets.parsers.NativeMemoryParser; import speiger.src.coreengine.assets.parsers.NativeMemoryParser;
import speiger.src.coreengine.rendering.gui.font.FontTexture; import speiger.src.coreengine.rendering.gui.font.FontTexture;
import speiger.src.coreengine.rendering.gui.font.glyth.Glyth; import speiger.src.coreengine.rendering.gui.font.glyth.Glyth;
import speiger.src.coreengine.rendering.gui.font.glyth.UnbakedGlyth; import speiger.src.coreengine.rendering.gui.font.glyth.IGlythSheetInfo;
import speiger.src.coreengine.rendering.gui.font.glyth.UnbakedGlyth.EmptyGlythData; import speiger.src.coreengine.rendering.gui.font.glyth.UnbakedGlyth;
import speiger.src.coreengine.rendering.gui.font.glyth.IGlythSheetInfo; import speiger.src.coreengine.rendering.gui.font.glyth.UnbakedGlyth.EmptyGlythData;
import speiger.src.coreengine.rendering.textures.custom.Drawable; import speiger.src.coreengine.rendering.textures.custom.Drawable;
import speiger.src.coreengine.utils.helpers.JsonUtil; import speiger.src.coreengine.utils.helpers.JsonUtil;
public class STBTrueTypeProvider implements IFontProvider { public class STBTrueTypeProvider implements IFontProvider {
TrueTypeInstance[] instances; TrueTypeInstance[] instances;
public STBTrueTypeProvider(TrueTypeInstance[] instances) { public STBTrueTypeProvider(TrueTypeInstance[] instances) {
this.instances = instances; this.instances = instances;
} }
public static IFontProvider create(AssetLocation location, IAssetProvider provider) { public static IFontProvider create(AssetLocation location, IAssetProvider provider) {
try(IAsset asset = provider.getAsset(location)) { try(IAsset asset = provider.getAsset(location)) {
return create(asset.json(), provider); return create(asset.json(), provider);
} }
catch(Exception e) { e.printStackTrace(); } catch(Exception e) { e.printStackTrace(); }
return null; return null;
} }
public static IFontProvider create(JsonObject data, IAssetProvider provider) { public static IFontProvider create(JsonObject data, IAssetProvider provider) {
TrueTypeInstance[] instances = new TrueTypeInstance[4]; TrueTypeInstance[] instances = new TrueTypeInstance[4];
instances[0] = create(0, data.getAsJsonObject("regular"), provider); instances[0] = create(0, data.getAsJsonObject("regular"), provider);
if(instances[0] == null) return null; if(instances[0] == null) return null;
instances[1] = create(1, data.getAsJsonObject("bold"), provider); instances[1] = create(1, data.getAsJsonObject("bold"), provider);
instances[2] = create(2, data.getAsJsonObject("italic"), provider); instances[2] = create(2, data.getAsJsonObject("italic"), provider);
instances[3] = create(3, data.getAsJsonObject("bold_italic"), provider); instances[3] = create(3, data.getAsJsonObject("bold_italic"), provider);
return new STBTrueTypeProvider(instances); return new STBTrueTypeProvider(instances);
} }
private static TrueTypeInstance create(int style, JsonObject obj, IAssetProvider provider) { private static TrueTypeInstance create(int style, JsonObject obj, IAssetProvider provider) {
if(obj == null || !obj.has("file")) return null; if(obj == null || !obj.has("file")) return null;
AssetLocation location = AssetLocation.of(obj.get("file").getAsString()); AssetLocation location = AssetLocation.of(obj.get("file").getAsString());
float oversample = JsonUtil.getOrDefault(obj, "oversample", 1F); float oversample = JsonUtil.getOrDefault(obj, "oversample", 1F);
float shadowOffset = JsonUtil.getOrDefault(obj, "shadowOffset", 1F); float shadowOffset = JsonUtil.getOrDefault(obj, "shadowOffset", 1F);
float xOff = 0; float xOff = 0;
float yOff = 0; float yOff = 0;
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
JsonObject shift = obj.getAsJsonObject("offset"); JsonObject shift = obj.getAsJsonObject("offset");
if(shift != null) { if(shift != null) {
xOff = JsonUtil.getOrDefault(shift, "x", 0); xOff = JsonUtil.getOrDefault(shift, "x", 0);
yOff = JsonUtil.getOrDefault(shift, "y", 0); yOff = JsonUtil.getOrDefault(shift, "y", 0);
} }
JsonUtil.iterateValues(obj.get("skip"), T -> builder.append(T.getAsString())); JsonUtil.iterateValues(obj.get("skip"), T -> builder.append(T.getAsString()));
try(IAsset asset = provider.getAsset(location)) { try(IAsset asset = provider.getAsset(location)) {
ByteBuffer buffer = asset.custom(NativeMemoryParser.INSTANCE); ByteBuffer buffer = asset.custom(NativeMemoryParser.INSTANCE);
STBTTFontinfo info = STBTTFontinfo.create(); STBTTFontinfo info = STBTTFontinfo.create();
if(!STBTruetype.stbtt_InitFont(info, buffer)) { if(!STBTruetype.stbtt_InitFont(info, buffer)) {
System.out.println("Couldn't load font"); System.out.println("Couldn't load font");
MemoryUtil.memFree(buffer); MemoryUtil.memFree(buffer);
info.free(); info.free();
return null; return null;
} }
return new TrueTypeInstance(style, MemoryUtil.memAddress(buffer), info, oversample, xOff, yOff, shadowOffset, builder.toString()); return new TrueTypeInstance(style, MemoryUtil.memAddress(buffer), info, oversample, xOff, yOff, shadowOffset, builder.toString());
} }
catch(Exception e) { catch(Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
return null; return null;
} }
public static class TrueTypeInstance { public static class TrueTypeInstance {
final int style; final int style;
long data; long data;
final STBTTFontinfo info; final STBTTFontinfo info;
IntSet skip = new IntOpenHashSet(); IntSet skip = new IntOpenHashSet();
final float oversample; final float oversample;
final float xOff; final float xOff;
final float yOff; final float yOff;
final float shadowOffset; final float shadowOffset;
final float ascent; final float ascent;
public TrueTypeInstance(int style, long data, STBTTFontinfo info, float oversample, float xOff, float yOff, float shadowOffset, String skip) { public TrueTypeInstance(int style, long data, STBTTFontinfo info, float oversample, float xOff, float yOff, float shadowOffset, String skip) {
this.style = style; this.style = style;
this.data = data; this.data = data;
this.info = info; this.info = info;
skip.codePoints().forEach(this.skip::add); skip.codePoints().forEach(this.skip::add);
this.oversample = oversample; this.oversample = oversample;
this.xOff = xOff; this.xOff = xOff;
this.yOff = yOff; this.yOff = yOff;
this.shadowOffset = shadowOffset; this.shadowOffset = shadowOffset;
int[] ascent = new int[1]; int[] ascent = new int[1];
STBTruetype.stbtt_GetFontVMetrics(info, ascent, new int[1], new int[1]); STBTruetype.stbtt_GetFontVMetrics(info, ascent, new int[1], new int[1]);
this.ascent = ascent[0]; this.ascent = ascent[0];
} }
public void free() { public void free() {
if(data == 0L) return; if(data == 0L) return;
info.free(); info.free();
MemoryUtil.nmemFree(data); MemoryUtil.nmemFree(data);
data = 0L; data = 0L;
} }
public UnbakedGlyth glythData(int codepoint, float size, float oversample) { public UnbakedGlyth glythData(int codepoint, float size, float oversample) {
if(skip.contains(codepoint)) return null; if(skip.contains(codepoint)) return null;
int glyth = STBTruetype.nstbtt_FindGlyphIndex(info.address(), codepoint); int glyth = STBTruetype.nstbtt_FindGlyphIndex(info.address(), codepoint);
if(glyth == 0) return null; if(glyth == 0) return null;
oversample *= this.oversample; oversample *= this.oversample;
float scale = STBTruetype.stbtt_ScaleForPixelHeight(info, size * oversample); float scale = STBTruetype.stbtt_ScaleForPixelHeight(info, size * oversample);
try(MemoryStack stack = MemoryStack.stackPush()) { try(MemoryStack stack = MemoryStack.stackPush()) {
IntBuffer left = stack.mallocInt(1); IntBuffer left = stack.mallocInt(1);
IntBuffer bottom = stack.mallocInt(1); IntBuffer bottom = stack.mallocInt(1);
IntBuffer right = stack.mallocInt(1); IntBuffer right = stack.mallocInt(1);
IntBuffer top = stack.mallocInt(1); IntBuffer top = stack.mallocInt(1);
IntBuffer advance = stack.mallocInt(1); IntBuffer advance = stack.mallocInt(1);
IntBuffer leftSideBearing = stack.mallocInt(1); IntBuffer leftSideBearing = stack.mallocInt(1);
STBTruetype.stbtt_GetGlyphHMetrics(info, glyth, advance, leftSideBearing); STBTruetype.stbtt_GetGlyphHMetrics(info, glyth, advance, leftSideBearing);
STBTruetype.stbtt_GetGlyphBitmapBoxSubpixel(info, glyth, scale, scale, xOff, yOff, left, bottom, right, top); STBTruetype.stbtt_GetGlyphBitmapBoxSubpixel(info, glyth, scale, scale, xOff, yOff, left, bottom, right, top);
int minX = left.get(0); int minX = left.get(0);
int minY = -top.get(0); int minY = -top.get(0);
int maxX = right.get(0); int maxX = right.get(0);
int maxY = -bottom.get(0); int maxY = -bottom.get(0);
if(maxX - minX <= 0 || maxY - minY <= 0) return new EmptyGlythData(advance.get(0) * scale / oversample); if(maxX - minX <= 0 || maxY - minY <= 0) return new EmptyGlythData(advance.get(0) * scale / oversample);
return new STBGlyth(this, minX, minY, maxX, maxY, advance.get(0), leftSideBearing.get(0), scale, oversample, glyth); return new STBGlyth(this, minX, minY, maxX, maxY, advance.get(0), leftSideBearing.get(0), scale, oversample, glyth);
} }
catch(Exception e) { catch(Exception e) {
e.printStackTrace(); e.printStackTrace();
return null; return null;
} }
} }
} }
@Override @Override
public UnbakedGlyth glythData(int codepoint, int style, float size, float oversample) { public UnbakedGlyth glythData(int codepoint, int style, float size, float oversample) {
TrueTypeInstance instance = instances[style & 0x3]; TrueTypeInstance instance = instances[style & 0x3];
return instance == null ? null : instance.glythData(codepoint, size, oversample); return instance == null ? null : instance.glythData(codepoint, size, oversample);
} }
@Override @Override
public void close() { public void close() {
if(instances == null) return; if(instances == null) return;
for(int i = 0;i<4;i++) { for(int i = 0;i<4;i++) {
if(instances[i] == null) continue; if(instances[i] == null) continue;
instances[i].free(); instances[i].free();
} }
instances = null; instances = null;
} }
private static class STBGlyth implements UnbakedGlyth { private static class STBGlyth implements UnbakedGlyth {
final TrueTypeInstance owner; final TrueTypeInstance owner;
final float xOffset; final float xOffset;
final float yOffset; final float yOffset;
final int width; final int width;
final int height; final int height;
final float oversample; final float oversample;
final float scale; final float scale;
final float advance; final float advance;
final int glyth; final int glyth;
public STBGlyth(TrueTypeInstance owner, int minX, int minY, int maxX, int maxY, float advance, float leftPadding, float scale, float oversample, int glyth) { public STBGlyth(TrueTypeInstance owner, int minX, int minY, int maxX, int maxY, float advance, float leftPadding, float scale, float oversample, int glyth) {
this.owner = owner; this.owner = owner;
this.width = maxX - minX; this.width = maxX - minX;
this.height = maxY - minY; this.height = maxY - minY;
this.scale = scale; this.scale = scale;
this.oversample = oversample; this.oversample = oversample;
this.xOffset = ((leftPadding * scale) + minX + owner.xOff) / oversample; this.xOffset = ((leftPadding * scale) + minX + owner.xOff) / oversample;
this.yOffset = ((owner.ascent * scale) - maxY + owner.yOff) / oversample; this.yOffset = ((owner.ascent * scale) - maxY + owner.yOff) / oversample;
this.advance = advance * scale / oversample; this.advance = advance * scale / oversample;
this.glyth = glyth; this.glyth = glyth;
} }
@Override @Override
public float advance() { return advance; } public float advance() { return advance; }
@Override @Override
public float shadowOffset() { return owner.shadowOffset; } public float shadowOffset() { return owner.shadowOffset; }
@Override @Override
public float kerning(int codepoint) { return STBTruetype.stbtt_GetCodepointKernAdvance(owner.info, codepoint, glyth) * scale / oversample; } public float kerning(int codepoint) { return STBTruetype.stbtt_GetCodepointKernAdvance(owner.info, codepoint, glyth) * scale / oversample; }
@Override @Override
public Glyth bake(GlythBaker baker) { public Glyth bake(GlythBaker baker) {
return baker.bake(new IGlythSheetInfo() { return baker.bake(new IGlythSheetInfo() {
@Override @Override
public float xOffset() { return xOffset; } public float xOffset() { return xOffset; }
@Override @Override
public float yOffset() { return yOffset; } public float yOffset() { return yOffset; }
@Override @Override
public int width() { return width; } public int width() { return width; }
@Override @Override
public int height() { return height; } public int height() { return height; }
@Override @Override
public float oversample() { return oversample; } public float oversample() { return oversample; }
@Override @Override
public boolean isColored() { return false; } public boolean isColored() { return false; }
@Override @Override
public void upload(int texture, int x, int y) { public void upload(int texture, int x, int y) {
Drawable drawable = new Drawable(FontTexture.formatByColor(false), width, height); Drawable drawable = new Drawable(FontTexture.formatByColor(false), width, height);
drawable.drawFont(owner.info, glyth, owner.xOff, owner.yOff, 0, 0, width, height, scale, scale); drawable.drawFont(owner.info, glyth, owner.xOff, owner.yOff, 0, 0, width, height, scale, scale);
drawable.upload(texture, x, y, 0, 0, width, height); drawable.upload(texture, x, y, 0, 0, width, height);
drawable.close(); drawable.close();
} }
}); });
} }
} }
} }

View File

@ -690,7 +690,7 @@ public abstract class GuiComponent extends FlagHolder
public final GuiComponent addListener(Runnable runnable, int index) public final GuiComponent addListener(Runnable runnable, int index)
{ {
listeners[index].add(T -> runnable.run()); listeners[index].add(_ -> runnable.run());
return this; return this;
} }

View File

@ -9,9 +9,9 @@ import speiger.src.coreengine.rendering.guiOld.renderer.FontRenderer;
import speiger.src.coreengine.rendering.guiOld.renderer.GuiShader; import speiger.src.coreengine.rendering.guiOld.renderer.GuiShader;
import speiger.src.coreengine.rendering.guiOld.renderer.UIRenderer; import speiger.src.coreengine.rendering.guiOld.renderer.UIRenderer;
import speiger.src.coreengine.rendering.guiOld.renderer.provider.FontManager; import speiger.src.coreengine.rendering.guiOld.renderer.provider.FontManager;
import speiger.src.coreengine.rendering.inputOld.events.MouseEvent;
import speiger.src.coreengine.rendering.inputOld.events.KeyEvent.CharTypeEvent; import speiger.src.coreengine.rendering.inputOld.events.KeyEvent.CharTypeEvent;
import speiger.src.coreengine.rendering.inputOld.events.KeyEvent.KeyPressEvent; import speiger.src.coreengine.rendering.inputOld.events.KeyEvent.KeyPressEvent;
import speiger.src.coreengine.rendering.inputOld.events.MouseEvent;
import speiger.src.coreengine.rendering.inputOld.window.IWindowListener; import speiger.src.coreengine.rendering.inputOld.window.IWindowListener;
import speiger.src.coreengine.rendering.inputOld.window.ScaledResolution; import speiger.src.coreengine.rendering.inputOld.window.ScaledResolution;
import speiger.src.coreengine.rendering.inputOld.window.Window; import speiger.src.coreengine.rendering.inputOld.window.Window;

View File

@ -13,8 +13,8 @@ import speiger.src.coreengine.rendering.guiOld.base.IButtonComponent;
import speiger.src.coreengine.rendering.guiOld.components.list.SelectionEntry; import speiger.src.coreengine.rendering.guiOld.components.list.SelectionEntry;
import speiger.src.coreengine.rendering.guiOld.helper.Align; import speiger.src.coreengine.rendering.guiOld.helper.Align;
import speiger.src.coreengine.rendering.guiOld.helper.box.IGuiBox; import speiger.src.coreengine.rendering.guiOld.helper.box.IGuiBox;
import speiger.src.coreengine.rendering.guiOld.helper.constrains.Constrains;
import speiger.src.coreengine.rendering.guiOld.helper.constrains.Constrain.Target; import speiger.src.coreengine.rendering.guiOld.helper.constrains.Constrain.Target;
import speiger.src.coreengine.rendering.guiOld.helper.constrains.Constrains;
import speiger.src.coreengine.rendering.guiOld.renderer.UIRenderer; import speiger.src.coreengine.rendering.guiOld.renderer.UIRenderer;
import speiger.src.coreengine.rendering.guiOld.renderer.buffer.RenderBuffer; import speiger.src.coreengine.rendering.guiOld.renderer.buffer.RenderBuffer;
import speiger.src.coreengine.rendering.tesselationOld.Tesselator; import speiger.src.coreengine.rendering.tesselationOld.Tesselator;

View File

@ -1,334 +1,334 @@
package speiger.src.coreengine.rendering.guiOld.components; package speiger.src.coreengine.rendering.guiOld.components;
import speiger.src.collections.floats.functions.FloatSupplier; import speiger.src.collections.floats.functions.FloatSupplier;
import speiger.src.collections.objects.functions.function.ToFloatFunction; import speiger.src.collections.objects.functions.function.ToFloatFunction;
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;
import speiger.src.coreengine.math.misc.ColorUtils; import speiger.src.coreengine.math.misc.ColorUtils;
import speiger.src.coreengine.math.misc.Facing; import speiger.src.coreengine.math.misc.Facing;
import speiger.src.coreengine.rendering.guiOld.GuiComponent; import speiger.src.coreengine.rendering.guiOld.GuiComponent;
import speiger.src.coreengine.rendering.guiOld.base.IButtonComponent; import speiger.src.coreengine.rendering.guiOld.base.IButtonComponent;
import speiger.src.coreengine.rendering.guiOld.helper.Align; import speiger.src.coreengine.rendering.guiOld.helper.Align;
import speiger.src.coreengine.rendering.guiOld.helper.constrains.Constrains; import speiger.src.coreengine.rendering.guiOld.helper.constrains.Constrain.Target;
import speiger.src.coreengine.rendering.guiOld.helper.constrains.DynamicConstrain; import speiger.src.coreengine.rendering.guiOld.helper.constrains.Constrains;
import speiger.src.coreengine.rendering.guiOld.helper.constrains.Constrain.Target; import speiger.src.coreengine.rendering.guiOld.helper.constrains.DynamicConstrain;
public class SingleTabPanelComponent extends PanelComponent public class SingleTabPanelComponent extends PanelComponent
{ {
PanelComponent selection = new PanelComponent(); PanelComponent selection = new PanelComponent();
PanelComponent panel = new PanelComponent().setScissors(true); PanelComponent panel = new PanelComponent().setScissors(true);
ObjectList<Tab> tabs = new ObjectArrayList<>(); ObjectList<Tab> tabs = new ObjectArrayList<>();
int selectedTab = -1; int selectedTab = -1;
float tabScale = 1F; float tabScale = 1F;
Facing facing; Facing facing;
int backgroundColor = ColorUtils.GRAY; int backgroundColor = ColorUtils.GRAY;
int unselectedColor = ColorUtils.GRAY; int unselectedColor = ColorUtils.GRAY;
int selectedColor = ColorUtils.DARK_GRAY; int selectedColor = ColorUtils.DARK_GRAY;
float padding = 30F; float padding = 30F;
public SingleTabPanelComponent() public SingleTabPanelComponent()
{ {
this(Facing.NORTH); this(Facing.NORTH);
} }
public SingleTabPanelComponent(Facing facing) public SingleTabPanelComponent(Facing facing)
{ {
this(0F, 0F, 0F, 0F, facing); this(0F, 0F, 0F, 0F, facing);
} }
public SingleTabPanelComponent(float x, float y, float width, float height) public SingleTabPanelComponent(float x, float y, float width, float height)
{ {
this(x, y, width, height, Facing.NORTH); this(x, y, width, height, Facing.NORTH);
} }
public SingleTabPanelComponent(float x, float y, float width, float height, Facing facing) public SingleTabPanelComponent(float x, float y, float width, float height, Facing facing)
{ {
super(x, y, width, height); super(x, y, width, height);
this.facing = facing; this.facing = facing;
} }
public SingleTabPanelComponent setFacing(Facing facing) public SingleTabPanelComponent setFacing(Facing facing)
{ {
this.facing = facing; this.facing = facing;
updateConstrains(selection, createView()); updateConstrains(selection, createView());
for(Tab tab : tabs) for(Tab tab : tabs)
{ {
updateConstrains(tab.align(facing.isZAxis() ? Align.CENTER : (facing == Facing.WEST ? Align.LEFT_TOP : Align.RIGHT_BOTTOM)), createConstraint(tab)); updateConstrains(tab.align(facing.isZAxis() ? Align.CENTER : (facing == Facing.WEST ? Align.LEFT_TOP : Align.RIGHT_BOTTOM)), createConstraint(tab));
} }
updateConstrains(panel, createPanel()); updateConstrains(panel, createPanel());
onChanged(true); onChanged(true);
return this; return this;
} }
public SingleTabPanelComponent setPadding(float padding) public SingleTabPanelComponent setPadding(float padding)
{ {
this.padding = padding; this.padding = padding;
for(Tab tab : tabs) for(Tab tab : tabs)
{ {
tab.updatePadding(); tab.updatePadding();
} }
onChanged(true); onChanged(true);
return this; return this;
} }
public SingleTabPanelComponent addTab(String name) public SingleTabPanelComponent addTab(String name)
{ {
Tab newTab = new Tab(name).align(facing.isZAxis() ? Align.CENTER : (facing == Facing.WEST ? Align.LEFT_TOP : Align.RIGHT_BOTTOM)); Tab newTab = new Tab(name).align(facing.isZAxis() ? Align.CENTER : (facing == Facing.WEST ? Align.LEFT_TOP : Align.RIGHT_BOTTOM));
tabs.add(newTab); tabs.add(newTab);
if(selectedTab == -1) { if(selectedTab == -1) {
selectedTab = tabs.size()-1; selectedTab = tabs.size()-1;
} }
newTab.onAction(() -> selectTab(newTab)); newTab.onAction(() -> selectTab(newTab));
selection.addChild(newTab, createConstraint(newTab)); selection.addChild(newTab, createConstraint(newTab));
onChanged(true); onChanged(true);
return this; return this;
} }
public Facing getFacing() public Facing getFacing()
{ {
return facing; return facing;
} }
public int findTab(String name) public int findTab(String name)
{ {
for(int i = 0,m=tabs.size();i<m;i++) { for(int i = 0,m=tabs.size();i<m;i++) {
if(tabs.get(i).name.equals(name)) return i; if(tabs.get(i).name.equals(name)) return i;
} }
return -1; return -1;
} }
public int getActiveIndex() public int getActiveIndex()
{ {
return selectedTab; return selectedTab;
} }
public PanelComponent getPanel() public PanelComponent getPanel()
{ {
return panel; return panel;
} }
@Override @Override
protected boolean renderSelf(int mouseX, int mouseY, float particalTicks) protected boolean renderSelf(int mouseX, int mouseY, float particalTicks)
{ {
getRenderer().drawQuad(selection.getBox(), backgroundColor); getRenderer().drawQuad(selection.getBox(), backgroundColor);
return true; return true;
} }
@Override @Override
public void init() public void init()
{ {
addChild(selection, createView()); addChild(selection, createView());
addChild(panel, createPanel()); addChild(panel, createPanel());
super.init(); super.init();
} }
@Override @Override
protected void repaint() protected void repaint()
{ {
if(facing.isZAxis()) if(facing.isZAxis())
{ {
float room = getBox().getBaseWidth(); float room = getBox().getBaseWidth();
float requiredSpace = 0F; float requiredSpace = 0F;
for(int i = 0,m=tabs.size();i<m;i++) for(int i = 0,m=tabs.size();i<m;i++)
{ {
Tab tab = tabs.get(i); Tab tab = tabs.get(i);
float width = tab.getWidth() * tab.getTextScale(); float width = tab.getWidth() * tab.getTextScale();
if(i == selectedTab) room -= width; if(i == selectedTab) room -= width;
else requiredSpace += width; else requiredSpace += width;
} }
tabScale = Math.min(1F, room / requiredSpace); tabScale = Math.min(1F, room / requiredSpace);
} }
else else
{ {
tabScale = 0F; tabScale = 0F;
for(int i = 0,m=tabs.size();i<m;i++) for(int i = 0,m=tabs.size();i<m;i++)
{ {
Tab tab = tabs.get(i); Tab tab = tabs.get(i);
tabScale = Math.max(tabScale, tab.getWidth() * tab.getTextScale()); tabScale = Math.max(tabScale, tab.getWidth() * tab.getTextScale());
} }
tabScale *= getBox().getScale(); tabScale *= getBox().getScale();
tabScale += 1F; tabScale += 1F;
} }
} }
protected Constrains createView() protected Constrains createView()
{ {
switch(facing) switch(facing)
{ {
case NORTH: return Constrains.parent(Target.X).parent(Target.Y).parent(Target.WIDTH).height(7.5F).build(); case NORTH: return Constrains.parent(Target.X).parent(Target.Y).parent(Target.WIDTH).height(7.5F).build();
case SOUTH: return Constrains.parent(Target.X).invParent(7.7F, Target.Y).parent(Target.WIDTH).height(7.5F).build(); case SOUTH: return Constrains.parent(Target.X).invParent(7.7F, Target.Y).parent(Target.WIDTH).height(7.5F).build();
case EAST: return Constrains.xPos(new DynamicConstrain(this::getXOffset).setInverted(true)).parent(Target.Y).dynamic(this::getPanelWidth, Target.WIDTH).parent(Target.HEIGHT).build(); case EAST: return Constrains.xPos(new DynamicConstrain(this::getXOffset).setInverted(true)).parent(Target.Y).dynamic(this::getPanelWidth, Target.WIDTH).parent(Target.HEIGHT).build();
case WEST: return Constrains.parent(Target.X).parent(Target.Y).dynamic(this::getPanelWidth, Target.WIDTH).parent(Target.HEIGHT).build(); case WEST: return Constrains.parent(Target.X).parent(Target.Y).dynamic(this::getPanelWidth, Target.WIDTH).parent(Target.HEIGHT).build();
default: return Constrains.parent(); default: return Constrains.parent();
} }
} }
protected Constrains createPanel() protected Constrains createPanel()
{ {
switch(facing) switch(facing)
{ {
case NORTH: return Constrains.parent(0F, 7.2F, 0F, 3.6F); case NORTH: return Constrains.parent(0F, 7.2F, 0F, 3.6F);
case SOUTH: return Constrains.parent(0F, 0F, 0F, 3.6F); case SOUTH: return Constrains.parent(0F, 0F, 0F, 3.6F);
case EAST: return Constrains.parent(Target.X).parent(Target.Y).width(new DynamicConstrain(this::getPanelWidth).setInverted(true)).parent(Target.HEIGHT).build(); case EAST: return Constrains.parent(Target.X).parent(Target.Y).width(new DynamicConstrain(this::getPanelWidth).setInverted(true)).parent(Target.HEIGHT).build();
case WEST: return Constrains.dynamic(this::getXOffset, Target.X).parent(0F, Target.Y).width(new DynamicConstrain(this::getPanelWidth).setInverted(true)).parent(Target.HEIGHT).build(); case WEST: return Constrains.dynamic(this::getXOffset, Target.X).parent(0F, Target.Y).width(new DynamicConstrain(this::getPanelWidth).setInverted(true)).parent(Target.HEIGHT).build();
default: return Constrains.parent(); default: return Constrains.parent();
} }
} }
protected Constrains createConstraint(Tab tab) protected Constrains createConstraint(Tab tab)
{ {
if(facing.isZAxis()) return Constrains.parent(Target.Y).parent(Target.HEIGHT).dynamic(new DynamicTab(tab, this::getOffset), Target.X).dynamic(new DynamicTab(tab, this::getWidth), Target.WIDTH).build(); if(facing.isZAxis()) return Constrains.parent(Target.Y).parent(Target.HEIGHT).dynamic(new DynamicTab(tab, this::getOffset), Target.X).dynamic(new DynamicTab(tab, this::getWidth), Target.WIDTH).build();
return Constrains.parent(Target.X).dynamic(new DynamicTab(tab, this::getOffset), Target.Y).parent(Target.WIDTH).height(7.5F).build(); return Constrains.parent(Target.X).dynamic(new DynamicTab(tab, this::getOffset), Target.Y).parent(Target.WIDTH).height(7.5F).build();
} }
protected void selectTab(Tab tab) protected void selectTab(Tab tab)
{ {
if(selectTab(tabs.indexOf(tab))) if(selectTab(tabs.indexOf(tab)))
{ {
notifyListeners(LISTENER_USER_ACTION); notifyListeners(LISTENER_USER_ACTION);
} }
} }
public boolean selectTab(int index) public boolean selectTab(int index)
{ {
if(index < 0 || index >= tabs.size()) return false; if(index < 0 || index >= tabs.size()) return false;
if(selectedTab == index) return false; if(selectedTab == index) return false;
selectedTab = index; selectedTab = index;
onChanged(true); onChanged(true);
return true; return true;
} }
protected float getOffset(Tab tab) protected float getOffset(Tab tab)
{ {
int index = tabs.indexOf(tab); int index = tabs.indexOf(tab);
float offset = 0F; float offset = 0F;
for(int i = 0;i<index;i++) for(int i = 0;i<index;i++)
{ {
Tab entry = tabs.get(i); Tab entry = tabs.get(i);
if(facing.isZAxis()) offset += entry.getWidth() * (i == selectedTab ? 1F : tabScale) * entry.getTextScale(); if(facing.isZAxis()) offset += entry.getWidth() * (i == selectedTab ? 1F : tabScale) * entry.getTextScale();
else offset += tab.getBox().getBaseHeight(); else offset += tab.getBox().getBaseHeight();
} }
return offset; return offset;
} }
protected float getPanelOffset() protected float getPanelOffset()
{ {
return facing == Facing.EAST ? 0F : tabScale + 0.25F; return facing == Facing.EAST ? 0F : tabScale + 0.25F;
} }
protected float getPanelWidth() protected float getPanelWidth()
{ {
return tabScale + 0.25F; return tabScale + 0.25F;
} }
protected float getXOffset() protected float getXOffset()
{ {
return tabScale + 0.25F; return tabScale + 0.25F;
} }
protected float getWidth(Tab tab) protected float getWidth(Tab tab)
{ {
return facing.isZAxis() ? tab.getWidth() * (selectedTab == tabs.indexOf(tab) ? 1F : tabScale) * tab.getTextScale() : tabScale; return facing.isZAxis() ? tab.getWidth() * (selectedTab == tabs.indexOf(tab) ? 1F : tabScale) * tab.getTextScale() : tabScale;
} }
private static class DynamicTab implements FloatSupplier private static class DynamicTab implements FloatSupplier
{ {
Tab tab; Tab tab;
ToFloatFunction<Tab> function; ToFloatFunction<Tab> function;
public DynamicTab(Tab tab, ToFloatFunction<Tab> function) public DynamicTab(Tab tab, ToFloatFunction<Tab> function)
{ {
this.tab = tab; this.tab = tab;
this.function = function; this.function = function;
} }
@Override @Override
public float getAsFloat() public float getAsFloat()
{ {
return function.applyAsFloat(tab); return function.applyAsFloat(tab);
} }
} }
private class Tab extends GuiComponent implements IButtonComponent private class Tab extends GuiComponent implements IButtonComponent
{ {
String name; String name;
float width = -1F; float width = -1F;
TextComponent comp; TextComponent comp;
public Tab(String name) public Tab(String name)
{ {
super(0F, 0F, 100F, 7.5F); super(0F, 0F, 100F, 7.5F);
this.name = name; this.name = name;
comp = new TextComponent(name).setTextScale(0.4F).singleLine(true).horizontal(Align.LEFT_TOP); comp = new TextComponent(name).setTextScale(0.4F).singleLine(true).horizontal(Align.LEFT_TOP);
setFlag(FLAG_SUPPORT_BINDING); setFlag(FLAG_SUPPORT_BINDING);
} }
public Tab align(Align align) public Tab align(Align align)
{ {
comp.horizontal(align); comp.horizontal(align);
return this; return this;
} }
public void updatePadding() public void updatePadding()
{ {
if(getGui() != null) width = getFont().width(name)+padding; if(getGui() != null) width = getFont().width(name)+padding;
} }
@Override @Override
public void init() public void init()
{ {
addChild(comp, Constrains.parent()); addChild(comp, Constrains.parent());
updatePadding(); updatePadding();
} }
public float getWidth() public float getWidth()
{ {
return width; return width;
} }
public float getTextScale() public float getTextScale()
{ {
return comp.getTextScale(); return comp.getTextScale();
} }
@Override @Override
protected void repaint() protected void repaint()
{ {
String s = name; String s = name;
float scale = comp.getTextScale(); float scale = comp.getTextScale();
float width = (this.width-padding)*scale; float width = (this.width-padding)*scale;
float desiredWidth = getBox().getBaseWidth(); float desiredWidth = getBox().getBaseWidth();
if(width > desiredWidth) { if(width > desiredWidth) {
while(s.length() >= 1 && getFont().width(s+"...") * scale > desiredWidth) { while(s.length() >= 1 && getFont().width(s+"...") * scale > desiredWidth) {
s = s.substring(0, s.length()-1); s = s.substring(0, s.length()-1);
} }
comp.setText(s+"..."); comp.setText(s+"...");
return; return;
} }
comp.setText(s); comp.setText(s);
} }
@Override @Override
protected boolean renderSelf(int mouseX, int mouseY, float particalTicks) protected boolean renderSelf(int mouseX, int mouseY, float particalTicks)
{ {
boolean notSelected = tabs.indexOf(this) != selectedTab; boolean notSelected = tabs.indexOf(this) != selectedTab;
getRenderer().drawQuad(getBox(), notSelected ? unselectedColor : selectedColor); getRenderer().drawQuad(getBox(), notSelected ? unselectedColor : selectedColor);
if(notSelected) getRenderer().drawFrame(getBox(), selectedColor); if(notSelected) getRenderer().drawFrame(getBox(), selectedColor);
return true; return true;
} }
@Override @Override
public void onRelease(int button, int mouseX, int mouseY) public void onRelease(int button, int mouseX, int mouseY)
{ {
notifyListeners(LISTENER_USER_ACTION); notifyListeners(LISTENER_USER_ACTION);
} }
@Override @Override
protected boolean onUserKey() protected boolean onUserKey()
{ {
notifyListeners(LISTENER_USER_ACTION); notifyListeners(LISTENER_USER_ACTION);
return true; return true;
} }
} }
} }

View File

@ -1,339 +1,339 @@
package speiger.src.coreengine.rendering.guiOld.components; package speiger.src.coreengine.rendering.guiOld.components;
import speiger.src.collections.floats.functions.FloatSupplier; import speiger.src.collections.floats.functions.FloatSupplier;
import speiger.src.collections.objects.functions.function.ToFloatFunction; import speiger.src.collections.objects.functions.function.ToFloatFunction;
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;
import speiger.src.coreengine.math.misc.ColorUtils; import speiger.src.coreengine.math.misc.ColorUtils;
import speiger.src.coreengine.math.misc.Facing; import speiger.src.coreengine.math.misc.Facing;
import speiger.src.coreengine.rendering.guiOld.GuiComponent; import speiger.src.coreengine.rendering.guiOld.GuiComponent;
import speiger.src.coreengine.rendering.guiOld.base.IButtonComponent; import speiger.src.coreengine.rendering.guiOld.base.IButtonComponent;
import speiger.src.coreengine.rendering.guiOld.helper.Align; import speiger.src.coreengine.rendering.guiOld.helper.Align;
import speiger.src.coreengine.rendering.guiOld.helper.constrains.Constrains; import speiger.src.coreengine.rendering.guiOld.helper.constrains.Constrain.Target;
import speiger.src.coreengine.rendering.guiOld.helper.constrains.DynamicConstrain; import speiger.src.coreengine.rendering.guiOld.helper.constrains.Constrains;
import speiger.src.coreengine.rendering.guiOld.helper.constrains.Constrain.Target; import speiger.src.coreengine.rendering.guiOld.helper.constrains.DynamicConstrain;
public class TabbedPanelComponent extends PanelComponent public class TabbedPanelComponent extends PanelComponent
{ {
PanelComponent selection = new PanelComponent(); PanelComponent selection = new PanelComponent();
ObjectList<Tab> tabs = new ObjectArrayList<>(); ObjectList<Tab> tabs = new ObjectArrayList<>();
int selectedTab = -1; int selectedTab = -1;
float tabScale = 1F; float tabScale = 1F;
Facing facing; Facing facing;
int backgroundColor = ColorUtils.GRAY; int backgroundColor = ColorUtils.GRAY;
int unselectedColor = ColorUtils.GRAY; int unselectedColor = ColorUtils.GRAY;
int selectedColor = ColorUtils.DARK_GRAY; int selectedColor = ColorUtils.DARK_GRAY;
float padding = 30F; float padding = 30F;
public TabbedPanelComponent() public TabbedPanelComponent()
{ {
this(Facing.NORTH); this(Facing.NORTH);
} }
public TabbedPanelComponent(Facing facing) public TabbedPanelComponent(Facing facing)
{ {
this(0F, 0F, 0F, 0F, facing); this(0F, 0F, 0F, 0F, facing);
} }
public TabbedPanelComponent(float x, float y, float width, float height) public TabbedPanelComponent(float x, float y, float width, float height)
{ {
this(x, y, width, height, Facing.NORTH); this(x, y, width, height, Facing.NORTH);
} }
public TabbedPanelComponent(float x, float y, float width, float height, Facing facing) public TabbedPanelComponent(float x, float y, float width, float height, Facing facing)
{ {
super(x, y, width, height); super(x, y, width, height);
this.facing = facing; this.facing = facing;
} }
public TabbedPanelComponent setFacing(Facing facing) public TabbedPanelComponent setFacing(Facing facing)
{ {
this.facing = facing; this.facing = facing;
updateConstrains(selection, createView()); updateConstrains(selection, createView());
for(Tab tab : tabs) for(Tab tab : tabs)
{ {
updateConstrains(tab.align(facing.isZAxis() ? Align.CENTER : (facing == Facing.WEST ? Align.LEFT_TOP : Align.RIGHT_BOTTOM)), createConstraint(tab)); updateConstrains(tab.align(facing.isZAxis() ? Align.CENTER : (facing == Facing.WEST ? Align.LEFT_TOP : Align.RIGHT_BOTTOM)), createConstraint(tab));
updateConstrains(tab.getPanel(), createPanel()); updateConstrains(tab.getPanel(), createPanel());
} }
onChanged(true); onChanged(true);
return this; return this;
} }
public TabbedPanelComponent setPadding(float padding) public TabbedPanelComponent setPadding(float padding)
{ {
this.padding = padding; this.padding = padding;
for(Tab tab : tabs) for(Tab tab : tabs)
{ {
tab.updatePadding(); tab.updatePadding();
} }
onChanged(true); onChanged(true);
return this; return this;
} }
public Facing getFacing() public Facing getFacing()
{ {
return facing; return facing;
} }
public PanelComponent addTab(String name) public PanelComponent addTab(String name)
{ {
Tab newTab = new Tab(name).align(facing.isZAxis() ? Align.CENTER : (facing == Facing.WEST ? Align.LEFT_TOP : Align.RIGHT_BOTTOM)); Tab newTab = new Tab(name).align(facing.isZAxis() ? Align.CENTER : (facing == Facing.WEST ? Align.LEFT_TOP : Align.RIGHT_BOTTOM));
tabs.add(newTab); tabs.add(newTab);
if(selectedTab == -1) { if(selectedTab == -1) {
selectedTab = tabs.size()-1; selectedTab = tabs.size()-1;
newTab.getPanel().setVisible(true); newTab.getPanel().setVisible(true);
} }
newTab.onAction(() -> selectTab(newTab)); newTab.onAction(() -> selectTab(newTab));
selection.addChild(newTab, createConstraint(newTab)); selection.addChild(newTab, createConstraint(newTab));
addChild(newTab.getPanel(), createPanel()); addChild(newTab.getPanel(), createPanel());
onChanged(true); onChanged(true);
return newTab.getPanel(); return newTab.getPanel();
} }
public int findTab(String name) public int findTab(String name)
{ {
for(int i = 0,m=tabs.size();i<m;i++) { for(int i = 0,m=tabs.size();i<m;i++) {
if(tabs.get(i).name.equals(name)) return i; if(tabs.get(i).name.equals(name)) return i;
} }
return -1; return -1;
} }
public int getActiveIndex() public int getActiveIndex()
{ {
return selectedTab; return selectedTab;
} }
public PanelComponent getActiveTab() public PanelComponent getActiveTab()
{ {
return selectedTab == -1 ? null : tabs.get(selectedTab).getPanel(); return selectedTab == -1 ? null : tabs.get(selectedTab).getPanel();
} }
@Override @Override
protected boolean renderSelf(int mouseX, int mouseY, float particalTicks) protected boolean renderSelf(int mouseX, int mouseY, float particalTicks)
{ {
getRenderer().drawQuad(selection.getBox(), backgroundColor); getRenderer().drawQuad(selection.getBox(), backgroundColor);
return true; return true;
} }
@Override @Override
public void init() public void init()
{ {
addChild(selection, createView()); addChild(selection, createView());
super.init(); super.init();
} }
@Override @Override
protected void repaint() protected void repaint()
{ {
if(facing.isZAxis()) if(facing.isZAxis())
{ {
float room = getBox().getBaseWidth(); float room = getBox().getBaseWidth();
float requiredSpace = 0F; float requiredSpace = 0F;
for(int i = 0,m=tabs.size();i<m;i++) for(int i = 0,m=tabs.size();i<m;i++)
{ {
Tab tab = tabs.get(i); Tab tab = tabs.get(i);
float width = tab.getWidth() * tab.getTextScale(); float width = tab.getWidth() * tab.getTextScale();
if(i == selectedTab) room -= width; if(i == selectedTab) room -= width;
else requiredSpace += width; else requiredSpace += width;
} }
tabScale = Math.min(1F, room / requiredSpace); tabScale = Math.min(1F, room / requiredSpace);
} }
else else
{ {
tabScale = 0F; tabScale = 0F;
for(int i = 0,m=tabs.size();i<m;i++) for(int i = 0,m=tabs.size();i<m;i++)
{ {
Tab tab = tabs.get(i); Tab tab = tabs.get(i);
tabScale = Math.max(tabScale, tab.getWidth() * tab.getTextScale()); tabScale = Math.max(tabScale, tab.getWidth() * tab.getTextScale());
} }
tabScale *= getBox().getScale(); tabScale *= getBox().getScale();
tabScale += 1F; tabScale += 1F;
} }
} }
protected Constrains createView() protected Constrains createView()
{ {
switch(facing) switch(facing)
{ {
case NORTH: return Constrains.parent(Target.X).parent(Target.Y).parent(Target.WIDTH).height(7.5F).build(); case NORTH: return Constrains.parent(Target.X).parent(Target.Y).parent(Target.WIDTH).height(7.5F).build();
case SOUTH: return Constrains.parent(Target.X).invParent(7.7F, Target.Y).parent(Target.WIDTH).height(7.5F).build(); case SOUTH: return Constrains.parent(Target.X).invParent(7.7F, Target.Y).parent(Target.WIDTH).height(7.5F).build();
case EAST: return Constrains.xPos(new DynamicConstrain(this::getXOffset).setInverted(true)).parent(Target.Y).dynamic(this::getPanelWidth, Target.WIDTH).parent(Target.HEIGHT).build(); case EAST: return Constrains.xPos(new DynamicConstrain(this::getXOffset).setInverted(true)).parent(Target.Y).dynamic(this::getPanelWidth, Target.WIDTH).parent(Target.HEIGHT).build();
case WEST: return Constrains.parent(Target.X).parent(Target.Y).dynamic(this::getPanelWidth, Target.WIDTH).parent(Target.HEIGHT).build(); case WEST: return Constrains.parent(Target.X).parent(Target.Y).dynamic(this::getPanelWidth, Target.WIDTH).parent(Target.HEIGHT).build();
default: return Constrains.parent(); default: return Constrains.parent();
} }
} }
protected Constrains createPanel() protected Constrains createPanel()
{ {
switch(facing) switch(facing)
{ {
case NORTH: return Constrains.parent(0F, 7.2F, 0F, 3.6F); case NORTH: return Constrains.parent(0F, 7.2F, 0F, 3.6F);
case SOUTH: return Constrains.parent(0F, 0F, 0F, 3.6F); case SOUTH: return Constrains.parent(0F, 0F, 0F, 3.6F);
case EAST: return Constrains.parent(Target.X).parent(Target.Y).width(new DynamicConstrain(this::getPanelWidth).setInverted(true)).parent(Target.HEIGHT).build(); case EAST: return Constrains.parent(Target.X).parent(Target.Y).width(new DynamicConstrain(this::getPanelWidth).setInverted(true)).parent(Target.HEIGHT).build();
case WEST: return Constrains.dynamic(this::getXOffset, Target.X).parent(0F, Target.Y).width(new DynamicConstrain(this::getPanelWidth).setInverted(true)).parent(Target.HEIGHT).build(); case WEST: return Constrains.dynamic(this::getXOffset, Target.X).parent(0F, Target.Y).width(new DynamicConstrain(this::getPanelWidth).setInverted(true)).parent(Target.HEIGHT).build();
default: return Constrains.parent(); default: return Constrains.parent();
} }
} }
protected Constrains createConstraint(Tab tab) protected Constrains createConstraint(Tab tab)
{ {
if(facing.isZAxis()) return Constrains.parent(Target.Y).parent(Target.HEIGHT).dynamic(new DynamicTab(tab, this::getOffset), Target.X).dynamic(new DynamicTab(tab, this::getWidth), Target.WIDTH).build(); if(facing.isZAxis()) return Constrains.parent(Target.Y).parent(Target.HEIGHT).dynamic(new DynamicTab(tab, this::getOffset), Target.X).dynamic(new DynamicTab(tab, this::getWidth), Target.WIDTH).build();
return Constrains.parent(Target.X).dynamic(new DynamicTab(tab, this::getOffset), Target.Y).parent(Target.WIDTH).height(7.5F).build(); return Constrains.parent(Target.X).dynamic(new DynamicTab(tab, this::getOffset), Target.Y).parent(Target.WIDTH).height(7.5F).build();
} }
protected void selectTab(Tab tab) protected void selectTab(Tab tab)
{ {
selectTab(tabs.indexOf(tab)); selectTab(tabs.indexOf(tab));
} }
public boolean selectTab(int index) public boolean selectTab(int index)
{ {
if(index < 0 || index >= tabs.size()) return false; if(index < 0 || index >= tabs.size()) return false;
if(selectedTab == index) return false; if(selectedTab == index) return false;
if(selectedTab != -1) tabs.get(selectedTab).getPanel().setVisible(false); if(selectedTab != -1) tabs.get(selectedTab).getPanel().setVisible(false);
selectedTab = index; selectedTab = index;
tabs.get(selectedTab).getPanel().setVisible(true); tabs.get(selectedTab).getPanel().setVisible(true);
onChanged(true); onChanged(true);
return true; return true;
} }
protected float getOffset(Tab tab) protected float getOffset(Tab tab)
{ {
int index = tabs.indexOf(tab); int index = tabs.indexOf(tab);
float offset = 0F; float offset = 0F;
for(int i = 0;i<index;i++) for(int i = 0;i<index;i++)
{ {
Tab entry = tabs.get(i); Tab entry = tabs.get(i);
if(facing.isZAxis()) offset += entry.getWidth() * (i == selectedTab ? 1F : tabScale) * entry.getTextScale(); if(facing.isZAxis()) offset += entry.getWidth() * (i == selectedTab ? 1F : tabScale) * entry.getTextScale();
else offset += tab.getBox().getBaseHeight(); else offset += tab.getBox().getBaseHeight();
} }
return offset; return offset;
} }
protected float getPanelOffset() protected float getPanelOffset()
{ {
return facing == Facing.EAST ? 0F : tabScale + 0.25F; return facing == Facing.EAST ? 0F : tabScale + 0.25F;
} }
protected float getPanelWidth() protected float getPanelWidth()
{ {
return tabScale + 0.25F; return tabScale + 0.25F;
} }
protected float getXOffset() protected float getXOffset()
{ {
return tabScale + 0.25F; return tabScale + 0.25F;
} }
protected float getWidth(Tab tab) protected float getWidth(Tab tab)
{ {
return facing.isZAxis() ? tab.getWidth() * (selectedTab == tabs.indexOf(tab) ? 1F : tabScale) * tab.getTextScale() : tabScale; return facing.isZAxis() ? tab.getWidth() * (selectedTab == tabs.indexOf(tab) ? 1F : tabScale) * tab.getTextScale() : tabScale;
} }
private static class DynamicTab implements FloatSupplier private static class DynamicTab implements FloatSupplier
{ {
Tab tab; Tab tab;
ToFloatFunction<Tab> function; ToFloatFunction<Tab> function;
public DynamicTab(Tab tab, ToFloatFunction<Tab> function) public DynamicTab(Tab tab, ToFloatFunction<Tab> function)
{ {
this.tab = tab; this.tab = tab;
this.function = function; this.function = function;
} }
@Override @Override
public float getAsFloat() public float getAsFloat()
{ {
return function.applyAsFloat(tab); return function.applyAsFloat(tab);
} }
} }
private class Tab extends GuiComponent implements IButtonComponent private class Tab extends GuiComponent implements IButtonComponent
{ {
String name; String name;
float width = -1F; float width = -1F;
TextComponent comp; TextComponent comp;
PanelComponent panel = new PanelComponent().setScissors(true).setVisible(false).cast(); PanelComponent panel = new PanelComponent().setScissors(true).setVisible(false).cast();
public Tab(String name) public Tab(String name)
{ {
super(0F, 0F, 100F, 7.5F); super(0F, 0F, 100F, 7.5F);
this.name = name; this.name = name;
comp = new TextComponent(name).setTextScale(0.4F).singleLine(true).horizontal(Align.LEFT_TOP); comp = new TextComponent(name).setTextScale(0.4F).singleLine(true).horizontal(Align.LEFT_TOP);
setFlag(FLAG_SUPPORT_BINDING); setFlag(FLAG_SUPPORT_BINDING);
} }
public Tab align(Align align) public Tab align(Align align)
{ {
comp.horizontal(align); comp.horizontal(align);
return this; return this;
} }
public void updatePadding() public void updatePadding()
{ {
if(getGui() != null) width = getFont().width(name)+padding; if(getGui() != null) width = getFont().width(name)+padding;
} }
@Override @Override
public void init() public void init()
{ {
addChild(comp, Constrains.parent()); addChild(comp, Constrains.parent());
updatePadding(); updatePadding();
} }
public float getWidth() public float getWidth()
{ {
return width; return width;
} }
public float getTextScale() public float getTextScale()
{ {
return comp.getTextScale(); return comp.getTextScale();
} }
@Override @Override
protected void repaint() protected void repaint()
{ {
String s = name; String s = name;
float scale = comp.getTextScale(); float scale = comp.getTextScale();
float width = (this.width-padding)*scale; float width = (this.width-padding)*scale;
float desiredWidth = getBox().getBaseWidth(); float desiredWidth = getBox().getBaseWidth();
if(width > desiredWidth) { if(width > desiredWidth) {
while(s.length() >= 1 && getFont().width(s+"...") * scale > desiredWidth) { while(s.length() >= 1 && getFont().width(s+"...") * scale > desiredWidth) {
s = s.substring(0, s.length()-1); s = s.substring(0, s.length()-1);
} }
comp.setText(s+"..."); comp.setText(s+"...");
return; return;
} }
comp.setText(s); comp.setText(s);
} }
public PanelComponent getPanel() public PanelComponent getPanel()
{ {
return panel; return panel;
} }
@Override @Override
protected boolean renderSelf(int mouseX, int mouseY, float particalTicks) protected boolean renderSelf(int mouseX, int mouseY, float particalTicks)
{ {
boolean notSelected = tabs.indexOf(this) != selectedTab; boolean notSelected = tabs.indexOf(this) != selectedTab;
getRenderer().drawQuad(getBox(), notSelected ? unselectedColor : selectedColor); getRenderer().drawQuad(getBox(), notSelected ? unselectedColor : selectedColor);
if(notSelected) getRenderer().drawFrame(getBox(), selectedColor); if(notSelected) getRenderer().drawFrame(getBox(), selectedColor);
return true; return true;
} }
@Override @Override
public void onRelease(int button, int mouseX, int mouseY) public void onRelease(int button, int mouseX, int mouseY)
{ {
notifyListeners(LISTENER_USER_ACTION); notifyListeners(LISTENER_USER_ACTION);
} }
@Override @Override
protected boolean onUserKey() protected boolean onUserKey()
{ {
notifyListeners(LISTENER_USER_ACTION); notifyListeners(LISTENER_USER_ACTION);
return true; return true;
} }
} }
} }

View File

@ -11,8 +11,8 @@ import speiger.src.coreengine.rendering.guiOld.base.IKeyComponent;
import speiger.src.coreengine.rendering.guiOld.helper.Align; import speiger.src.coreengine.rendering.guiOld.helper.Align;
import speiger.src.coreengine.rendering.guiOld.helper.box.IGuiBox; import speiger.src.coreengine.rendering.guiOld.helper.box.IGuiBox;
import speiger.src.coreengine.rendering.guiOld.helper.box.ParentBox; import speiger.src.coreengine.rendering.guiOld.helper.box.ParentBox;
import speiger.src.coreengine.rendering.guiOld.helper.constrains.Constrains;
import speiger.src.coreengine.rendering.guiOld.helper.constrains.Constrain.Target; import speiger.src.coreengine.rendering.guiOld.helper.constrains.Constrain.Target;
import speiger.src.coreengine.rendering.guiOld.helper.constrains.Constrains;
import speiger.src.coreengine.rendering.guiOld.renderer.UIRenderer; import speiger.src.coreengine.rendering.guiOld.renderer.UIRenderer;
import speiger.src.coreengine.rendering.guiOld.renderer.lexer.TextMetadata; import speiger.src.coreengine.rendering.guiOld.renderer.lexer.TextMetadata;
import speiger.src.coreengine.rendering.guiOld.renderer.lexer.Word; import speiger.src.coreengine.rendering.guiOld.renderer.lexer.Word;

View File

@ -59,8 +59,8 @@ public class ColorPickerWindowComponent extends WindowComponent
addBox(selectedBox); addBox(selectedBox);
addChild(brightness.onChange(minimizedListener).onAction(T -> setColor(hsv[0], hsv[1], T.cast(SliderComponent.class).getValue() * 0.01F))); addChild(brightness.onChange(minimizedListener).onAction(T -> setColor(hsv[0], hsv[1], T.cast(SliderComponent.class).getValue() * 0.01F)));
addChild(saturation.onChange(minimizedListener).onAction(T -> setColor(hsv[0], T.cast(SliderComponent.class).getValue() * 0.01F, hsv[2]))); addChild(saturation.onChange(minimizedListener).onAction(T -> setColor(hsv[0], T.cast(SliderComponent.class).getValue() * 0.01F, hsv[2])));
addChild(code.setScale(0.5F).onChange(minimizedListener).onAction(T -> onTyped())); addChild(code.setScale(0.5F).onChange(minimizedListener).onAction(_ -> onTyped()));
addChild(new ButtonComponent(0F, 0F, 0F, 20F, "Select", ColorUtils.GREEN).setScale(0.4F).onAction(T -> apply()), new Constrains(null, new ParentConstrain(8F).invert(), new RelativeConstrain(0.5F / 0.4F), null)); addChild(new ButtonComponent(0F, 0F, 0F, 20F, "Select", ColorUtils.GREEN).setScale(0.4F).onAction(_ -> apply()), new Constrains(null, new ParentConstrain(8F).invert(), new RelativeConstrain(0.5F / 0.4F), null));
addChild(new ButtonComponent(0F, 0F, 0F, 20F, "Cancel", ColorUtils.RED).setScale(0.4F).onAction(T -> T.getGui().removeComponent(this)), new Constrains(new RelativeConstrain(0.5F), new ParentConstrain(8F).invert(), new RelativeConstrain(0.5F / 0.4F), null)); addChild(new ButtonComponent(0F, 0F, 0F, 20F, "Cancel", ColorUtils.RED).setScale(0.4F).onAction(T -> T.getGui().removeComponent(this)), new Constrains(new RelativeConstrain(0.5F), new ParentConstrain(8F).invert(), new RelativeConstrain(0.5F / 0.4F), null));
setColor(hsv[0], hsv[1], hsv[2]); setColor(hsv[0], hsv[1], hsv[2]);
} }

View File

@ -15,17 +15,17 @@ import speiger.src.coreengine.math.misc.Facing;
import speiger.src.coreengine.math.vector.floats.Vec2f; import speiger.src.coreengine.math.vector.floats.Vec2f;
import speiger.src.coreengine.rendering.guiOld.base.IKeyComponent; import speiger.src.coreengine.rendering.guiOld.base.IKeyComponent;
import speiger.src.coreengine.rendering.guiOld.components.PieComponent; import speiger.src.coreengine.rendering.guiOld.components.PieComponent;
import speiger.src.coreengine.rendering.guiOld.components.PieComponent.IPieIndex;
import speiger.src.coreengine.rendering.guiOld.components.PieComponent.PieIndex;
import speiger.src.coreengine.rendering.guiOld.components.SingleTabPanelComponent; import speiger.src.coreengine.rendering.guiOld.components.SingleTabPanelComponent;
import speiger.src.coreengine.rendering.guiOld.components.TextComponent; import speiger.src.coreengine.rendering.guiOld.components.TextComponent;
import speiger.src.coreengine.rendering.guiOld.components.WindowComponent; import speiger.src.coreengine.rendering.guiOld.components.WindowComponent;
import speiger.src.coreengine.rendering.guiOld.components.PieComponent.IPieIndex;
import speiger.src.coreengine.rendering.guiOld.components.PieComponent.PieIndex;
import speiger.src.coreengine.rendering.guiOld.helper.Align; import speiger.src.coreengine.rendering.guiOld.helper.Align;
import speiger.src.coreengine.rendering.guiOld.helper.constrains.Constrain; import speiger.src.coreengine.rendering.guiOld.helper.constrains.Constrain;
import speiger.src.coreengine.rendering.guiOld.helper.constrains.Constrain.Target;
import speiger.src.coreengine.rendering.guiOld.helper.constrains.Constrains; import speiger.src.coreengine.rendering.guiOld.helper.constrains.Constrains;
import speiger.src.coreengine.rendering.guiOld.helper.constrains.DynamicConstrain; import speiger.src.coreengine.rendering.guiOld.helper.constrains.DynamicConstrain;
import speiger.src.coreengine.rendering.guiOld.helper.constrains.PixelConstrain; import speiger.src.coreengine.rendering.guiOld.helper.constrains.PixelConstrain;
import speiger.src.coreengine.rendering.guiOld.helper.constrains.Constrain.Target;
import speiger.src.coreengine.rendering.inputOld.Keyboard; import speiger.src.coreengine.rendering.inputOld.Keyboard;
import speiger.src.coreengine.utils.profiler.IProfiler; import speiger.src.coreengine.utils.profiler.IProfiler;
import speiger.src.coreengine.utils.profiler.IProfiler.IProfilerEntry; import speiger.src.coreengine.utils.profiler.IProfiler.IProfilerEntry;

View File

@ -1,216 +1,216 @@
package speiger.src.coreengine.rendering.guiOld.components.window.debug; package speiger.src.coreengine.rendering.guiOld.components.window.debug;
import java.util.List; import java.util.List;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.ObjIntConsumer; import java.util.function.ObjIntConsumer;
import speiger.src.collections.ints.queues.IntArrayFIFOQueue; import speiger.src.collections.ints.queues.IntArrayFIFOQueue;
import speiger.src.collections.ints.queues.IntPriorityQueue; import speiger.src.collections.ints.queues.IntPriorityQueue;
import speiger.src.collections.objects.lists.ObjectArrayList; import speiger.src.collections.objects.lists.ObjectArrayList;
import speiger.src.coreengine.math.misc.ColorUtils; import speiger.src.coreengine.math.misc.ColorUtils;
import speiger.src.coreengine.math.misc.Facing; import speiger.src.coreengine.math.misc.Facing;
import speiger.src.coreengine.math.vector.floats.Vec2f; import speiger.src.coreengine.math.vector.floats.Vec2f;
import speiger.src.coreengine.rendering.guiOld.components.SingleTabPanelComponent; import speiger.src.coreengine.rendering.guiOld.components.SingleTabPanelComponent;
import speiger.src.coreengine.rendering.guiOld.components.TreeComponent; import speiger.src.coreengine.rendering.guiOld.components.TreeComponent;
import speiger.src.coreengine.rendering.guiOld.components.WindowComponent; import speiger.src.coreengine.rendering.guiOld.components.WindowComponent;
import speiger.src.coreengine.rendering.guiOld.components.tree.ProfilerTreeEntry; import speiger.src.coreengine.rendering.guiOld.components.tree.ProfilerTreeEntry;
import speiger.src.coreengine.rendering.guiOld.helper.constrains.Constrains; import speiger.src.coreengine.rendering.guiOld.helper.constrains.Constrain.Target;
import speiger.src.coreengine.rendering.guiOld.helper.constrains.Constrain.Target; import speiger.src.coreengine.rendering.guiOld.helper.constrains.Constrains;
import speiger.src.coreengine.utils.profiler.IProfiler; import speiger.src.coreengine.utils.profiler.IProfiler;
import speiger.src.coreengine.utils.profiler.IProfiler.IProfilerEntry; import speiger.src.coreengine.utils.profiler.IProfiler.IProfilerEntry;
public class TreeProfilerWindow extends WindowComponent public class TreeProfilerWindow extends WindowComponent
{ {
IntPriorityQueue todoList = new IntArrayFIFOQueue().synchronizeQueue(); IntPriorityQueue todoList = new IntArrayFIFOQueue().synchronizeQueue();
ObjIntConsumer<IProfiler> listener = (T, V) -> todoList.enqueue(V); ObjIntConsumer<IProfiler> listener = (_, V) -> todoList.enqueue(V);
SingleTabPanelComponent panel = new SingleTabPanelComponent(Facing.SOUTH).onAction(this::onProfilerChanged).cast(); SingleTabPanelComponent panel = new SingleTabPanelComponent(Facing.SOUTH).onAction(this::onProfilerChanged).cast();
TreeComponent<ProfilerTreeEntry> tree = panel.addChild(new TreeComponent<>(ColorUtils.GRAY, 9F).disableBackground(true).setSelectionMode(TreeComponent.SELECTION_MODE_INTERACT).cast(), Constrains.parent(Target.WIDTH).parent(4, Target.HEIGHT).build()); TreeComponent<ProfilerTreeEntry> tree = panel.addChild(new TreeComponent<>(ColorUtils.GRAY, 9F).disableBackground(true).setSelectionMode(TreeComponent.SELECTION_MODE_INTERACT).cast(), Constrains.parent(Target.WIDTH).parent(4, Target.HEIGHT).build());
List<ProfilerTab> tabs = new ObjectArrayList<>(); List<ProfilerTab> tabs = new ObjectArrayList<>();
int previouseTab = -1; int previouseTab = -1;
public TreeProfilerWindow(float x, float y, float width, float height, String name) public TreeProfilerWindow(float x, float y, float width, float height, String name)
{ {
super(x, y, width, height, DEFAULT_FLAGS, name); super(x, y, width, height, DEFAULT_FLAGS, name);
} }
public TreeProfilerWindow addProfiler(IProfiler profiler, String root) public TreeProfilerWindow addProfiler(IProfiler profiler, String root)
{ {
panel.addTab(profiler.getName()); panel.addTab(profiler.getName());
tabs.add(new ProfilerTab(profiler, root)); tabs.add(new ProfilerTab(profiler, root));
if(tabs.size() == 1) if(tabs.size() == 1)
{ {
onProfilerChanged(); onProfilerChanged();
} }
return this; return this;
} }
@Override @Override
public boolean canMoveIntoForground() public boolean canMoveIntoForground()
{ {
return true; return true;
} }
@Override @Override
public Vec2f getMinimumBounds() public Vec2f getMinimumBounds()
{ {
return Vec2f.of(100F, 50F); return Vec2f.of(100F, 50F);
} }
@Override @Override
public void init() public void init()
{ {
super.init(); super.init();
addChild(panel.set(0F, 7.5F).onChange(minimizedListener), Constrains.parent(0.25F, Target.WIDTH).parent(4F, Target.HEIGHT).build()); addChild(panel.set(0F, 7.5F).onChange(minimizedListener), Constrains.parent(0.25F, Target.WIDTH).parent(4F, Target.HEIGHT).build());
} }
@Override @Override
public void onClosed() public void onClosed()
{ {
super.onClosed(); super.onClosed();
applyProfiler(false, this::disable); applyProfiler(false, this::disable);
} }
@Override @Override
protected boolean fixedUpdateSelf() protected boolean fixedUpdateSelf()
{ {
ProfilerTab entry = getActiveTab(); ProfilerTab entry = getActiveTab();
if(entry == null) if(entry == null)
{ {
todoList.clear(); todoList.clear();
return true; return true;
} }
while(!todoList.isEmpty()) while(!todoList.isEmpty())
{ {
int index = todoList.dequeue(); int index = todoList.dequeue();
switch(index) switch(index)
{ {
case 0: case 0:
addEntries(entry.getRootEntry()); addEntries(entry.getRootEntry());
break; break;
case 1: case 1:
tree.setTree(null); tree.setTree(null);
break; break;
case 2: case 2:
if(tree.getTree() == null) if(tree.getTree() == null)
{ {
addEntries(entry.getRootEntry()); addEntries(entry.getRootEntry());
break; break;
} }
updateChildren(entry.getRootEntry(), tree.getTree()); updateChildren(entry.getRootEntry(), tree.getTree());
tree.onTreeChanged(); tree.onTreeChanged();
break; break;
} }
} }
return true; return true;
} }
protected void onProfilerChanged() protected void onProfilerChanged()
{ {
if(previouseTab == panel.getActiveIndex()) return; if(previouseTab == panel.getActiveIndex()) return;
applyProfiler(true, this::disable); applyProfiler(true, this::disable);
applyProfiler(false, this::enable); applyProfiler(false, this::enable);
previouseTab = panel.getActiveIndex(); previouseTab = panel.getActiveIndex();
ProfilerTab tab = tabs.get(previouseTab); ProfilerTab tab = tabs.get(previouseTab);
setCurrentEntry(tab.getRoot()); setCurrentEntry(tab.getRoot());
} }
protected void enable(IProfiler profiler) protected void enable(IProfiler profiler)
{ {
profiler.enable(); profiler.enable();
profiler.addListener(listener); profiler.addListener(listener);
} }
protected void disable(IProfiler profiler) protected void disable(IProfiler profiler)
{ {
profiler.removeListener(listener); profiler.removeListener(listener);
profiler.disable(); profiler.disable();
} }
protected void addEntries(IProfilerEntry entry) protected void addEntries(IProfilerEntry entry)
{ {
if(entry == null) return; if(entry == null) return;
ProfilerTreeEntry child = new ProfilerTreeEntry(entry); ProfilerTreeEntry child = new ProfilerTreeEntry(entry);
for(int i = 0,m=entry.getChildCount();i<m;i++) for(int i = 0,m=entry.getChildCount();i<m;i++)
{ {
addChildren(entry.getChild(i), child); addChildren(entry.getChild(i), child);
} }
tree.setTree(child); tree.setTree(child);
tree.openAll(); tree.openAll();
} }
public TreeProfilerWindow setCurrentEntry(String name) public TreeProfilerWindow setCurrentEntry(String name)
{ {
addEntries(getActive().getEntry(name)); addEntries(getActive().getEntry(name));
return this; return this;
} }
protected void updateChildren(IProfilerEntry entry, ProfilerTreeEntry tree) protected void updateChildren(IProfilerEntry entry, ProfilerTreeEntry tree)
{ {
if(entry == null || tree == null) return; if(entry == null || tree == null) return;
for(int i = 0,m=entry.getChildCount();i<m;i++) for(int i = 0,m=entry.getChildCount();i<m;i++)
{ {
addChildren(entry.getChild(i), tree); addChildren(entry.getChild(i), tree);
} }
} }
protected void addChildren(IProfilerEntry entry, ProfilerTreeEntry tree) protected void addChildren(IProfilerEntry entry, ProfilerTreeEntry tree)
{ {
if(entry == null || tree == null) return; if(entry == null || tree == null) return;
ProfilerTreeEntry child = new ProfilerTreeEntry(entry); ProfilerTreeEntry child = new ProfilerTreeEntry(entry);
int index = tree.indexOf(child); int index = tree.indexOf(child);
if(index != -1) child = (ProfilerTreeEntry)tree.getChild(index); if(index != -1) child = (ProfilerTreeEntry)tree.getChild(index);
else tree.addChild(child); else tree.addChild(child);
for(int i = 0,m=entry.getChildCount();i<m;i++) for(int i = 0,m=entry.getChildCount();i<m;i++)
{ {
addChildren(entry.getChild(i), child); addChildren(entry.getChild(i), child);
} }
} }
protected IProfiler getActive() protected IProfiler getActive()
{ {
return tabs.get(panel.getActiveIndex()).getProfiler(); return tabs.get(panel.getActiveIndex()).getProfiler();
} }
protected ProfilerTab getActiveTab() protected ProfilerTab getActiveTab()
{ {
int index = panel.getActiveIndex(); int index = panel.getActiveIndex();
return index < 0 || index >= tabs.size() ? null : tabs.get(index); return index < 0 || index >= tabs.size() ? null : tabs.get(index);
} }
protected void applyProfiler(boolean prev, Consumer<IProfiler> action) protected void applyProfiler(boolean prev, Consumer<IProfiler> action)
{ {
int index = prev ? previouseTab : panel.getActiveIndex(); int index = prev ? previouseTab : panel.getActiveIndex();
if(index >= 0) action.accept(tabs.get(index).getProfiler()); if(index >= 0) action.accept(tabs.get(index).getProfiler());
} }
private static class ProfilerTab private static class ProfilerTab
{ {
IProfiler profiler; IProfiler profiler;
String root; String root;
public ProfilerTab(IProfiler profiler, String root) public ProfilerTab(IProfiler profiler, String root)
{ {
this.profiler = profiler; this.profiler = profiler;
this.root = root; this.root = root;
} }
public IProfiler getProfiler() public IProfiler getProfiler()
{ {
return profiler; return profiler;
} }
public String getRoot() public String getRoot()
{ {
return root; return root;
} }
public IProfilerEntry getRootEntry() public IProfilerEntry getRootEntry()
{ {
return profiler.getEntry(root); return profiler.getEntry(root);
} }
} }
} }

View File

@ -46,8 +46,8 @@ public class ChoiceComponent extends WindowComponent
super.init(); super.init();
yesButton.getText().setTextScale(0.5F); yesButton.getText().setTextScale(0.5F);
noButton.getText().setTextScale(0.5F); noButton.getText().setTextScale(0.5F);
addChild(yesButton.onChange(minimizedListener).onAction(closeListener).onAction(T -> listener.accept(true)), new Constrains(new RelativeConstrain(0F), new ParentConstrain(10F).invert(), new RelativeConstrain(0.5F), new PixelConstrain(10F))); addChild(yesButton.onChange(minimizedListener).onAction(closeListener).onAction(_ -> listener.accept(true)), new Constrains(new RelativeConstrain(0F), new ParentConstrain(10F).invert(), new RelativeConstrain(0.5F), new PixelConstrain(10F)));
addChild(noButton.onChange(minimizedListener).onAction(closeListener).onAction(T -> listener.accept(false)), new Constrains(new RelativeConstrain(0.5F), new ParentConstrain(10F).invert(), new RelativeConstrain(0.5F), new PixelConstrain(10F))); addChild(noButton.onChange(minimizedListener).onAction(closeListener).onAction(_ -> listener.accept(false)), new Constrains(new RelativeConstrain(0.5F), new ParentConstrain(10F).invert(), new RelativeConstrain(0.5F), new PixelConstrain(10F)));
addChild(message, new Constrains(new PixelConstrain(10F), new PixelConstrain(11F), new ParentConstrain(10F), TextConstrain.height(message))); addChild(message, new Constrains(new PixelConstrain(10F), new PixelConstrain(11F), new ParentConstrain(10F), TextConstrain.height(message)));
getBox().setHeight(25F + message.getMetadata().getMaxHeight()); getBox().setHeight(25F + message.getMetadata().getMaxHeight());
} }

View File

@ -1,446 +1,446 @@
package speiger.src.coreengine.rendering.guiOld.renderer; package speiger.src.coreengine.rendering.guiOld.renderer;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL11;
import speiger.src.collections.floats.lists.FloatArrayList; import speiger.src.collections.floats.lists.FloatArrayList;
import speiger.src.collections.floats.lists.FloatList; import speiger.src.collections.floats.lists.FloatList;
import speiger.src.collections.objects.lists.ObjectArrayList; import speiger.src.collections.objects.lists.ObjectArrayList;
import speiger.src.collections.objects.utils.ObjectLists; import speiger.src.collections.objects.utils.ObjectLists;
import speiger.src.coreengine.rendering.guiOld.components.TextComponent; import speiger.src.coreengine.rendering.guiOld.components.TextComponent;
import speiger.src.coreengine.rendering.guiOld.helper.Align; import speiger.src.coreengine.rendering.guiOld.helper.Align;
import speiger.src.coreengine.rendering.guiOld.renderer.buffer.DelayedRenderBuffer; import speiger.src.coreengine.rendering.guiOld.renderer.buffer.DelayedRenderBuffer;
import speiger.src.coreengine.rendering.guiOld.renderer.buffer.RenderBuffer; import speiger.src.coreengine.rendering.guiOld.renderer.buffer.RenderBuffer;
import speiger.src.coreengine.rendering.guiOld.renderer.buffer.TranslatedVertexBuilder; import speiger.src.coreengine.rendering.guiOld.renderer.buffer.TranslatedVertexBuilder;
import speiger.src.coreengine.rendering.guiOld.renderer.lexer.Line; import speiger.src.coreengine.rendering.guiOld.renderer.lexer.Line;
import speiger.src.coreengine.rendering.guiOld.renderer.lexer.TextContext; import speiger.src.coreengine.rendering.guiOld.renderer.lexer.TextContext;
import speiger.src.coreengine.rendering.guiOld.renderer.lexer.TextLexer; import speiger.src.coreengine.rendering.guiOld.renderer.lexer.TextContext.WordContext;
import speiger.src.coreengine.rendering.guiOld.renderer.lexer.TextContext.WordContext; import speiger.src.coreengine.rendering.guiOld.renderer.lexer.TextLexer;
import speiger.src.coreengine.rendering.guiOld.renderer.provider.IFontProvider; import speiger.src.coreengine.rendering.guiOld.renderer.provider.IFontProvider;
import speiger.src.coreengine.rendering.models.DrawCall; import speiger.src.coreengine.rendering.models.DrawCall;
import speiger.src.coreengine.rendering.tesselationOld.IVertexBuilder; import speiger.src.coreengine.rendering.tesselationOld.IVertexBuilder;
import speiger.src.coreengine.rendering.tesselationOld.Tesselator; import speiger.src.coreengine.rendering.tesselationOld.Tesselator;
import speiger.src.coreengine.rendering.tesselationOld.VertexType; import speiger.src.coreengine.rendering.tesselationOld.VertexType;
import speiger.src.coreengine.rendering.texturesOld.base.ITexture; import speiger.src.coreengine.rendering.texturesOld.base.ITexture;
import speiger.src.coreengine.utils.helpers.TextUtil; 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 int EMPTY = (char)0; public static final int EMPTY = (char)0;
public static final int SPACE = ' '; public static final int SPACE = ' ';
public static final int TAB = '\t'; public static final int TAB = '\t';
public static final int LINE_SEPERATOR = '\n'; public static final int LINE_SEPERATOR = '\n';
Tesselator bufferBuilder = new Tesselator(655340); Tesselator bufferBuilder = new Tesselator(655340);
IFontProvider provider; IFontProvider provider;
final TextLexer lexer = new TextLexer(this); final TextLexer lexer = new TextLexer(this);
final DelayedRenderBuffer lineBuffer = new DelayedRenderBuffer(); final DelayedRenderBuffer lineBuffer = new DelayedRenderBuffer();
public void setProvider(IFontProvider provider) public void setProvider(IFontProvider provider)
{ {
this.provider = provider; this.provider = provider;
} }
@Override @Override
public CharInstance getInstance(int codepoint, boolean isBold) public CharInstance getInstance(int codepoint, boolean isBold)
{ {
return provider.getCharacter(codepoint, isBold); return provider.getCharacter(codepoint, isBold);
} }
@Override @Override
public float height() public float height()
{ {
return provider.height(); return provider.height();
} }
@Override @Override
public float baseLine() public float baseLine()
{ {
return provider.baseLine(); return provider.baseLine();
} }
@Override @Override
public ITexture getTexture() public ITexture getTexture()
{ {
return provider.getTexture(); return provider.getTexture();
} }
public IFontProvider getProvider() public IFontProvider getProvider()
{ {
return provider; return provider;
} }
public void destory() public void destory()
{ {
if(provider != null) if(provider != null)
{ {
provider.destroy(); provider.destroy();
provider = null; provider = null;
} }
} }
public List<DrawCall> renderText(String text, float x, float y, float z) public List<DrawCall> renderText(String text, float x, float y, float z)
{ {
if(text.isEmpty()) return ObjectLists.empty(); if(text.isEmpty()) return ObjectLists.empty();
List<DrawCall> drawCalls = new ObjectArrayList<>(); List<DrawCall> drawCalls = new ObjectArrayList<>();
TextContext context = new TextContext(1F, 0); TextContext context = new TextContext(1F, 0);
List<Line> lines = lexer.evaluateLines(text, context, Float.MAX_VALUE); List<Line> lines = lexer.evaluateLines(text, context, Float.MAX_VALUE);
if(lines.isEmpty()) return ObjectLists.empty(); if(lines.isEmpty()) return ObjectLists.empty();
WordContext effects = context.getEffect(); WordContext effects = context.getEffect();
int textColor = effects.color; int textColor = effects.color;
float yOffset = 0F; float yOffset = 0F;
IVertexBuilder builder = new TranslatedVertexBuilder(bufferBuilder, x, y, z, 1F); IVertexBuilder builder = new TranslatedVertexBuilder(bufferBuilder, x, y, z, 1F);
bufferBuilder.begin(GL11.GL_TRIANGLES, VertexType.IN_WORLD_UI); bufferBuilder.begin(GL11.GL_TRIANGLES, VertexType.IN_WORLD_UI);
for(int i = 0,m=lines.size();i<m;i++) for(int i = 0,m=lines.size();i<m;i++)
{ {
float xOffset = 9F; float xOffset = 9F;
for(CharInstance letter : lines.get(i).letterIterator()) for(CharInstance letter : lines.get(i).letterIterator())
{ {
xOffset += renderChar(letter, xOffset, yOffset, context.getScale(), effects.italic, effects.flipped, textColor, builder, true); xOffset += renderChar(letter, xOffset, yOffset, context.getScale(), effects.italic, effects.flipped, textColor, builder, true);
} }
yOffset += height() * context.getScale(); yOffset += height() * context.getScale();
} }
bufferBuilder.finishData(); bufferBuilder.finishData();
if(bufferBuilder.getVertexCount() > 0) if(bufferBuilder.getVertexCount() > 0)
{ {
drawCalls.add(bufferBuilder.getDrawCall(getTexture().getTextureId())); drawCalls.add(bufferBuilder.getDrawCall(getTexture().getTextureId()));
} }
bufferBuilder.setOffset(0F, 0F, 0F); bufferBuilder.setOffset(0F, 0F, 0F);
return drawCalls; return drawCalls;
} }
@Override @Override
public void updateText(TextComponent component) public void updateText(TextComponent component)
{ {
RenderBuffer buffer = component.getBuffer(); RenderBuffer buffer = component.getBuffer();
buffer.clear(); buffer.clear();
if(component.getText().isEmpty()) if(component.getText().isEmpty())
{ {
return; return;
} }
TextContext context = new TextContext(component); TextContext context = new TextContext(component);
float boxWidth = component.getBox().getWidth(); float boxWidth = component.getBox().getWidth();
float boxHeight = component.getBox().getHeight(); float boxHeight = component.getBox().getHeight();
List<Line> lines = lexer.evaluateLines(component.getText(), context, component.isWidthLimited() ? boxWidth : Float.MAX_VALUE); List<Line> lines = lexer.evaluateLines(component.getText(), context, component.isWidthLimited() ? boxWidth : Float.MAX_VALUE);
if(lines.isEmpty()) if(lines.isEmpty())
{ {
return; return;
} }
bufferBuilder.begin(GL11.GL_TRIANGLES, VertexType.UI); bufferBuilder.begin(GL11.GL_TRIANGLES, VertexType.UI);
int maxLanes = component.isHeightLimited() ? Math.min((int)(boxHeight / (height() * context.getScale())), lines.size()) : lines.size(); int maxLanes = component.isHeightLimited() ? Math.min((int)(boxHeight / (height() * context.getScale())), lines.size()) : lines.size();
float maxHeight = maxLanes * height() * context.getScale(); float maxHeight = maxLanes * height() * context.getScale();
float maxWidth = 0F; float maxWidth = 0F;
float yOffset = component.getVertical().align(boxHeight, maxHeight); float yOffset = component.getVertical().align(boxHeight, maxHeight);
float startX = component.getHorizontal().align(boxWidth, lines.get(0).getWidth()); float startX = component.getHorizontal().align(boxWidth, lines.get(0).getWidth());
component.getMetadata().setStart(startX, yOffset); component.getMetadata().setStart(startX, yOffset);
WordContext effects = context.getEffect(); WordContext effects = context.getEffect();
while(effects.isNext(0)) while(effects.isNext(0))
{ {
effects = effects.next(); effects = effects.next();
} }
int textColor = effects.color; int textColor = effects.color;
Float strikeThrough = effects.strike_through ? startX : null; Float strikeThrough = effects.strike_through ? startX : null;
Float underline = effects.underline ? startX : -1F; Float underline = effects.underline ? startX : -1F;
if(component.getBackgroundColor() != null) if(component.getBackgroundColor() != null)
{ {
Tesselator tes = buffer.start(GL11.GL_TRIANGLES, VertexType.UI).setOffset(0F, 0F, -0.001F); Tesselator tes = buffer.start(GL11.GL_TRIANGLES, VertexType.UI).setOffset(0F, 0F, -0.001F);
addBackground(tes, lines, maxLanes, yOffset, component.getHorizontal(), boxWidth, component.getBackgroundColor(), false); addBackground(tes, lines, maxLanes, yOffset, component.getHorizontal(), boxWidth, component.getBackgroundColor(), false);
tes.setOffset(0F, 0F, 0F); tes.setOffset(0F, 0F, 0F);
buffer.finishShape(0); buffer.finishShape(0);
} }
for(int i = 0, index = 0;i < maxLanes;i++) for(int i = 0, index = 0;i < maxLanes;i++)
{ {
float xOffset = component.getHorizontal().align(boxWidth, lines.get(i).getWidth()); float xOffset = component.getHorizontal().align(boxWidth, lines.get(i).getWidth());
maxWidth = Math.max(maxWidth, lines.get(i).getWidth()); maxWidth = Math.max(maxWidth, lines.get(i).getWidth());
strikeThrough = effects.strike_through ? xOffset : null; strikeThrough = effects.strike_through ? xOffset : null;
underline = effects.underline ? xOffset : null; underline = effects.underline ? xOffset : null;
for(CharInstance letter : lines.get(i).letterIterator()) for(CharInstance letter : lines.get(i).letterIterator())
{ {
xOffset += renderChar(letter, xOffset, yOffset, context.getScale(), effects.italic, effects.flipped, textColor, bufferBuilder, false); xOffset += renderChar(letter, xOffset, yOffset, context.getScale(), effects.italic, effects.flipped, textColor, bufferBuilder, false);
if(effects.isNext(++index)) if(effects.isNext(++index))
{ {
WordContext next = effects.next(); WordContext next = effects.next();
Float newStrike = getValue(effects.strike_through, next.strike_through, xOffset, strikeThrough); Float newStrike = getValue(effects.strike_through, next.strike_through, xOffset, strikeThrough);
if(newStrike == null && strikeThrough != null) if(newStrike == null && strikeThrough != null)
{ {
addStrikeThrough(strikeThrough, xOffset - strikeThrough, yOffset, textColor, lineBuffer); addStrikeThrough(strikeThrough, xOffset - strikeThrough, yOffset, textColor, lineBuffer);
} }
strikeThrough = newStrike; strikeThrough = newStrike;
Float newLine = getValue(effects.underline, next.underline, xOffset, strikeThrough); Float newLine = getValue(effects.underline, next.underline, xOffset, strikeThrough);
if(newLine == null && underline != null) if(newLine == null && underline != null)
{ {
addUnderline(underline, xOffset - underline, yOffset, textColor, lineBuffer, false); addUnderline(underline, xOffset - underline, yOffset, textColor, lineBuffer, false);
} }
textColor = next.color; textColor = next.color;
underline = newLine; underline = newLine;
effects = next; effects = next;
} }
} }
if(strikeThrough != null) if(strikeThrough != null)
{ {
addStrikeThrough(strikeThrough, xOffset - strikeThrough, yOffset, textColor, lineBuffer); addStrikeThrough(strikeThrough, xOffset - strikeThrough, yOffset, textColor, lineBuffer);
} }
if(underline != null) if(underline != null)
{ {
addUnderline(underline, xOffset - underline, yOffset, textColor, lineBuffer, false); addUnderline(underline, xOffset - underline, yOffset, textColor, lineBuffer, false);
} }
yOffset += height() * context.getScale(); yOffset += height() * context.getScale();
component.getMetadata().addLine(lines.get(i)); component.getMetadata().addLine(lines.get(i));
} }
maxWidth /= 2; maxWidth /= 2;
buffer.finishShape(getTexture().getTextureId(), bufferBuilder); buffer.finishShape(getTexture().getTextureId(), bufferBuilder);
if(lineBuffer.hasData()) if(lineBuffer.hasData())
{ {
Tesselator tes = buffer.start(GL11.GL_TRIANGLES, VertexType.UI).offset(0F, 0F, 0.001F); Tesselator tes = buffer.start(GL11.GL_TRIANGLES, VertexType.UI).offset(0F, 0F, 0.001F);
lineBuffer.merge(tes); lineBuffer.merge(tes);
tes.setOffset(0F, 0F, 0F); tes.setOffset(0F, 0F, 0F);
buffer.finishShape(0); buffer.finishShape(0);
} }
} }
protected float renderChar(CharInstance instance, float x, float y, float scale, float italic, boolean flipped, int color, IVertexBuilder buffer, boolean flipPos) protected float renderChar(CharInstance instance, float x, float y, float scale, float italic, boolean flipped, int color, IVertexBuilder buffer, boolean flipPos)
{ {
switch(instance.getCharacter()) switch(instance.getCharacter())
{ {
case TAB: case TAB:
return provider.getTabWidth() * scale; return provider.getTabWidth() * scale;
case SPACE: case SPACE:
return provider.getSpaceWidth() * scale; return provider.getSpaceWidth() * scale;
} }
if(instance.getXAdvance() <= 0F) if(instance.getXAdvance() <= 0F)
{ {
return 0F; return 0F;
} }
if(flipPos) flipped = !flipped; if(flipPos) flipped = !flipped;
float minX = x; float minX = x;
float minY = y; float minY = y;
float maxX = x + (instance.getWidth() * scale); float maxX = x + (instance.getWidth() * scale);
float maxY = flipPos ? y - (instance.getHeight() * scale) : y + (instance.getHeight() * scale); float maxY = flipPos ? y - (instance.getHeight() * scale) : y + (instance.getHeight() * scale);
float minV = flipped ? instance.getMaxV() : instance.getMinV(); float minV = flipped ? instance.getMaxV() : instance.getMinV();
float maxV = flipped ? instance.getMinV() : instance.getMaxV(); float maxV = flipped ? instance.getMinV() : instance.getMaxV();
buffer.pos(minX - italic, maxY, 0F).tex(instance.getMinU(), maxV).color4f(color).endVertex(); buffer.pos(minX - italic, maxY, 0F).tex(instance.getMinU(), maxV).color4f(color).endVertex();
buffer.pos(minX + italic, minY, 0F).tex(instance.getMinU(), minV).color4f(color).endVertex(); buffer.pos(minX + italic, minY, 0F).tex(instance.getMinU(), minV).color4f(color).endVertex();
buffer.pos(maxX - italic, maxY, 0F).tex(instance.getMaxU(), maxV).color4f(color).endVertex(); buffer.pos(maxX - italic, maxY, 0F).tex(instance.getMaxU(), maxV).color4f(color).endVertex();
buffer.pos(maxX - italic, maxY, 0F).tex(instance.getMaxU(), maxV).color4f(color).endVertex(); buffer.pos(maxX - italic, maxY, 0F).tex(instance.getMaxU(), maxV).color4f(color).endVertex();
buffer.pos(minX + italic, minY, 0F).tex(instance.getMinU(), minV).color4f(color).endVertex(); buffer.pos(minX + italic, minY, 0F).tex(instance.getMinU(), minV).color4f(color).endVertex();
buffer.pos(maxX + italic, minY, 0F).tex(instance.getMaxU(), minV).color4f(color).endVertex(); buffer.pos(maxX + italic, minY, 0F).tex(instance.getMaxU(), minV).color4f(color).endVertex();
return instance.getXAdvance() * scale; return instance.getXAdvance() * scale;
} }
protected void addBackground(IVertexBuilder tes, List<Line> lines, int maxLines, float yPos, Align align, float width, int color, boolean flipPos) protected void addBackground(IVertexBuilder tes, List<Line> lines, int maxLines, float yPos, Align align, float width, int color, boolean flipPos)
{ {
for(int i = 0;i < maxLines;i++) for(int i = 0;i < maxLines;i++)
{ {
float lineWidth = lines.get(i).getWidth(); float lineWidth = lines.get(i).getWidth();
float xOffset = align.align(width, lineWidth); float xOffset = align.align(width, lineWidth);
float maxY = flipPos ? yPos - height() : yPos + height(); float maxY = flipPos ? yPos - height() : yPos + height();
tes.pos(xOffset, maxY, 0.0F).tex(0F, 0F).color4f(color).endVertex(); tes.pos(xOffset, maxY, 0.0F).tex(0F, 0F).color4f(color).endVertex();
tes.pos(xOffset, yPos, 0.0F).tex(0F, 0F).color4f(color).endVertex(); tes.pos(xOffset, yPos, 0.0F).tex(0F, 0F).color4f(color).endVertex();
tes.pos(xOffset + lineWidth, maxY, 0.0F).tex(0F, 0F).color4f(color).endVertex(); tes.pos(xOffset + lineWidth, maxY, 0.0F).tex(0F, 0F).color4f(color).endVertex();
tes.pos(xOffset + lineWidth, maxY, 0.0F).tex(0F, 0F).color4f(color).endVertex(); tes.pos(xOffset + lineWidth, maxY, 0.0F).tex(0F, 0F).color4f(color).endVertex();
tes.pos(xOffset, yPos, 0.0F).tex(0F, 0F).color4f(color).endVertex(); tes.pos(xOffset, yPos, 0.0F).tex(0F, 0F).color4f(color).endVertex();
tes.pos(xOffset + lineWidth, yPos, 0.0F).tex(0F, 0F).color4f(color).endVertex(); tes.pos(xOffset + lineWidth, yPos, 0.0F).tex(0F, 0F).color4f(color).endVertex();
yPos = maxY; yPos = maxY;
} }
} }
protected void addUnderline(float xStart, float width, float yStart, int color, IVertexBuilder buffer, boolean flipPos) protected void addUnderline(float xStart, float width, float yStart, int color, IVertexBuilder buffer, boolean flipPos)
{ {
float minY = yStart + baseLine() + 0.5F; float minY = yStart + baseLine() + 0.5F;
float maxY = yStart + baseLine() + 1.5F; float maxY = yStart + baseLine() + 1.5F;
if(flipPos) if(flipPos)
{ {
minY = yStart - baseLine() - 0.5F; minY = yStart - baseLine() - 0.5F;
maxY = yStart - baseLine() - 1.5F; maxY = yStart - baseLine() - 1.5F;
} }
buffer.pos(xStart, maxY, 0F).tex(0F, 0F).color4f(color).endVertex(); buffer.pos(xStart, maxY, 0F).tex(0F, 0F).color4f(color).endVertex();
buffer.pos(xStart, minY, 0F).tex(0F, 0F).color4f(color).endVertex(); buffer.pos(xStart, minY, 0F).tex(0F, 0F).color4f(color).endVertex();
buffer.pos(xStart + width, maxY, 0F).tex(0F, 0F).color4f(color).endVertex(); buffer.pos(xStart + width, maxY, 0F).tex(0F, 0F).color4f(color).endVertex();
buffer.pos(xStart + width, maxY, 0F).tex(0F, 0F).color4f(color).endVertex(); buffer.pos(xStart + width, maxY, 0F).tex(0F, 0F).color4f(color).endVertex();
buffer.pos(xStart, minY, 0F).tex(0F, 0F).color4f(color).endVertex(); buffer.pos(xStart, minY, 0F).tex(0F, 0F).color4f(color).endVertex();
buffer.pos(xStart + width, minY, 0F).tex(0F, 0F).color4f(color).endVertex(); buffer.pos(xStart + width, minY, 0F).tex(0F, 0F).color4f(color).endVertex();
} }
protected void addStrikeThrough(float xStart, float width, float yStart, int color, IVertexBuilder buffer) protected void addStrikeThrough(float xStart, float width, float yStart, int color, IVertexBuilder buffer)
{ {
float minY = yStart + height() / 2.0F; float minY = yStart + height() / 2.0F;
float maxY = yStart + height() / 2.0F + 1.4F; float maxY = yStart + height() / 2.0F + 1.4F;
buffer.pos(xStart, maxY, 0.0F).tex(0F, 0F).color4f(color).endVertex(); buffer.pos(xStart, maxY, 0.0F).tex(0F, 0F).color4f(color).endVertex();
buffer.pos(xStart, minY, 0.0F).tex(0F, 0F).color4f(color).endVertex(); buffer.pos(xStart, minY, 0.0F).tex(0F, 0F).color4f(color).endVertex();
buffer.pos(xStart + width, maxY, 0.0F).tex(0F, 0F).color4f(color).endVertex(); buffer.pos(xStart + width, maxY, 0.0F).tex(0F, 0F).color4f(color).endVertex();
buffer.pos(xStart + width, maxY, 0.0F).tex(0F, 0F).color4f(color).endVertex(); buffer.pos(xStart + width, maxY, 0.0F).tex(0F, 0F).color4f(color).endVertex();
buffer.pos(xStart, minY, 0.0F).tex(0F, 0F).color4f(color).endVertex(); buffer.pos(xStart, minY, 0.0F).tex(0F, 0F).color4f(color).endVertex();
buffer.pos(xStart + width, minY, 0.0F).tex(0F, 0F).color4f(color).endVertex(); buffer.pos(xStart + width, minY, 0.0F).tex(0F, 0F).color4f(color).endVertex();
} }
protected Float getValue(boolean oldValue, boolean newValue, Float position, Float oldPosition) protected Float getValue(boolean oldValue, boolean newValue, Float position, Float oldPosition)
{ {
if((position == null && oldPosition == null) || (position != null && oldPosition != null)) return oldPosition; if((position == null && oldPosition == null) || (position != null && oldPosition != null)) return oldPosition;
return newValue ? position : null; return newValue ? position : null;
} }
@Override @Override
public String trimToWidth(String text, float limit, boolean reverse) public String trimToWidth(String text, float limit, boolean reverse)
{ {
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
float width = 0F; float width = 0F;
int start = reverse ? text.length() - 1 : 0; int start = reverse ? text.length() - 1 : 0;
int direction = reverse ? -1 : 1; int direction = reverse ? -1 : 1;
for(int i = start;i >= 0 && i < text.length() && width < limit;i += direction) for(int i = start;i >= 0 && i < text.length() && width < limit;i += direction)
{ {
char letter = text.charAt(i); char letter = text.charAt(i);
width += width(letter); width += width(letter);
if(width > limit) break; if(width > limit) break;
if(reverse) builder.insert(0, letter); if(reverse) builder.insert(0, letter);
else builder.append(letter); else builder.append(letter);
} }
return builder.toString(); return builder.toString();
} }
@Override @Override
public float width(int codepoint, boolean bold) public float width(int codepoint, boolean bold)
{ {
switch(codepoint) 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(codepoint, bold); CharInstance instance = getInstance(codepoint, bold);
return instance == null ? 0F : instance.getXAdvance(); return instance == null ? 0F : instance.getXAdvance();
} }
} }
@Override @Override
public float width(String text, int flags) public float width(String text, int flags)
{ {
float result = 0.0F; float result = 0.0F;
float current = 0.0F; float current = 0.0F;
boolean bold = (flags & BOLD) != 0; boolean bold = (flags & BOLD) != 0;
for(int i = 0;i < text.length();i++) for(int i = 0;i < text.length();i++)
{ {
char character = text.charAt(i); char character = text.charAt(i);
if(LINE_SEPERATOR == character) if(LINE_SEPERATOR == character)
{ {
result = Math.max(result, current += provider.getSpaceWidth()); result = Math.max(result, current += provider.getSpaceWidth());
current = 0.0F; current = 0.0F;
continue; continue;
} }
if(character == '§' && (flags & SPECIAL) != 0 && i + 1 < text.length() && text.charAt(i + 1) == '<') if(character == '§' && (flags & SPECIAL) != 0 && i + 1 < text.length() && text.charAt(i + 1) == '<')
{ {
String search = TextUtil.searchUntil(text, i + 2, '>', INVALID_SEARCH); String search = TextUtil.searchUntil(text, i + 2, '>', INVALID_SEARCH);
if(search.length() > 0) if(search.length() > 0)
{ {
for(String entry : search.toLowerCase(Locale.ROOT).split(",")) for(String entry : search.toLowerCase(Locale.ROOT).split(","))
{ {
bold = TextUtil.findFlag(entry, "bold", bold); bold = TextUtil.findFlag(entry, "bold", bold);
} }
i += search.length() + 2; i += search.length() + 2;
continue; continue;
} }
} }
current += width(character, bold); current += width(character, bold);
} }
return Math.max(result, current); return Math.max(result, current);
} }
@Override @Override
public float[] widths(String text, int flags) public float[] widths(String text, int flags)
{ {
FloatList results = new FloatArrayList(); FloatList results = new FloatArrayList();
results.add(0F); results.add(0F);
float current = 0F; float current = 0F;
int chars = 0; int chars = 0;
boolean bold = (flags & BOLD) != 0; boolean bold = (flags & BOLD) != 0;
float max = 0F; float max = 0F;
for(int i = 0;i < text.length();i++) for(int i = 0;i < text.length();i++)
{ {
char character = text.charAt(i); char character = text.charAt(i);
if(LINE_SEPERATOR == character) if(LINE_SEPERATOR == character)
{ {
results.add(current); results.add(current);
max = Math.max(max, current); max = Math.max(max, current);
current = 0F; current = 0F;
chars = 0; chars = 0;
continue; continue;
} }
chars++; chars++;
if(character == '§' && (flags & SPECIAL) != 0 && i + 1 < text.length() && text.charAt(i + 1) == '<') if(character == '§' && (flags & SPECIAL) != 0 && i + 1 < text.length() && text.charAt(i + 1) == '<')
{ {
String result = TextUtil.searchUntil(text, i + 2, '>', INVALID_SEARCH); String result = TextUtil.searchUntil(text, i + 2, '>', INVALID_SEARCH);
if(result.length() > 0) if(result.length() > 0)
{ {
for(String entry : result.toLowerCase(Locale.ROOT).split(",")) for(String entry : result.toLowerCase(Locale.ROOT).split(","))
{ {
bold = TextUtil.findFlag(entry, "bold", bold); bold = TextUtil.findFlag(entry, "bold", bold);
} }
i += result.length() + 2; i += result.length() + 2;
continue; continue;
} }
} }
current += width(character, bold); current += width(character, bold);
} }
if(chars++ > 0) if(chars++ > 0)
{ {
results.add(current); results.add(current);
max = Math.max(max, current); max = Math.max(max, current);
} }
results.set(0, max); results.set(0, max);
return results.toFloatArray(); return results.toFloatArray();
} }
@Override @Override
public float height(String text, int flags) public float height(String text, int flags)
{ {
return widths(text, flags).length - 1 * height(); return widths(text, flags).length - 1 * height();
} }
@Override @Override
public boolean isCharValid(int codepoint) public boolean isCharValid(int codepoint)
{ {
return provider.isCharacterValid(codepoint); return provider.isCharacterValid(codepoint);
} }
@Override @Override
public String[] split(String text, float maxWidth, int flags) public String[] split(String text, float maxWidth, int flags)
{ {
TextContext context = new TextContext(1F, ((flags & IFontRenderer.SPECIAL) != 0 ? 16 : 0) | ((flags & IFontRenderer.BOLD) != 0 ? 1 : 0)); TextContext context = new TextContext(1F, ((flags & IFontRenderer.SPECIAL) != 0 ? 16 : 0) | ((flags & IFontRenderer.BOLD) != 0 ? 1 : 0));
List<Line> lines = lexer.evaluateLines(text, context, maxWidth); List<Line> lines = lexer.evaluateLines(text, context, maxWidth);
String[] array = new String[lines.size()]; String[] array = new String[lines.size()];
if(context.allowsSpecial()) if(context.allowsSpecial())
{ {
int index = 0; int index = 0;
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
WordContext wordContext = context.getEffect(); WordContext wordContext = context.getEffect();
while(wordContext.isNext(0)) while(wordContext.isNext(0))
{ {
builder.append(wordContext.getString(false)); builder.append(wordContext.getString(false));
wordContext = wordContext.next(); wordContext = wordContext.next();
} }
for(int i = 0,m=lines.size();i<m;i++) for(int i = 0,m=lines.size();i<m;i++)
{ {
if(i != 0) builder.append(wordContext.getString(true)); if(i != 0) builder.append(wordContext.getString(true));
for(CharInstance letter : lines.get(i).letterIterator()) for(CharInstance letter : lines.get(i).letterIterator())
{ {
builder.append(letter.getCharacter()); builder.append(letter.getCharacter());
if(wordContext.isNext(++index)) if(wordContext.isNext(++index))
{ {
wordContext = wordContext.next(); wordContext = wordContext.next();
builder.append(wordContext.getString(false)); builder.append(wordContext.getString(false));
} }
} }
array[i] = builder.toString(); array[i] = builder.toString();
builder.setLength(0); builder.setLength(0);
} }
} }
else else
{ {
for(int i = 0,m=lines.size();i<m;i++) array[i] = lines.get(i).getText(); for(int i = 0,m=lines.size();i<m;i++) array[i] = lines.get(i).getText();
} }
return array; return array;
} }
} }

View File

@ -1,143 +1,143 @@
package speiger.src.coreengine.rendering.guiOld.renderer.provider; package speiger.src.coreengine.rendering.guiOld.renderer.provider;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.util.List; import java.util.List;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import speiger.src.collections.ints.maps.impl.hash.Int2ObjectOpenHashMap; import speiger.src.collections.ints.maps.impl.hash.Int2ObjectOpenHashMap;
import speiger.src.collections.ints.maps.interfaces.Int2ObjectMap; import speiger.src.collections.ints.maps.interfaces.Int2ObjectMap;
import speiger.src.collections.ints.utils.maps.Int2ObjectMaps; 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;
import speiger.src.coreengine.assets.base.IAsset; import speiger.src.coreengine.assets.base.IAsset;
import speiger.src.coreengine.math.vector.ints.Vec2i; import speiger.src.coreengine.math.vector.ints.Vec2i;
import speiger.src.coreengine.rendering.guiOld.helper.FontBuilder; import speiger.src.coreengine.rendering.guiOld.helper.FontBuilder;
import speiger.src.coreengine.rendering.guiOld.helper.FontBuilder.WrittenChar; import speiger.src.coreengine.rendering.guiOld.helper.FontBuilder.WrittenChar;
import speiger.src.coreengine.rendering.guiOld.renderer.IFontRenderer.CharInstance; import speiger.src.coreengine.rendering.guiOld.renderer.IFontRenderer.CharInstance;
import speiger.src.coreengine.rendering.texturesOld.base.ITexture; import speiger.src.coreengine.rendering.texturesOld.base.ITexture;
import speiger.src.coreengine.rendering.texturesOld.base.TextureManager; import speiger.src.coreengine.rendering.texturesOld.base.TextureManager;
import speiger.src.coreengine.utils.helpers.JsonUtil; import speiger.src.coreengine.utils.helpers.JsonUtil;
public class BitmapFontProvider implements IFontProvider public class BitmapFontProvider implements IFontProvider
{ {
FontInfo info; FontInfo info;
ITexture texture; ITexture texture;
Int2ObjectMap<CharInstance>[] instances; Int2ObjectMap<CharInstance>[] instances;
float space; float space;
public BitmapFontProvider(FontInfo info, ITexture texture, Int2ObjectMap<CharInstance>[] instances) public BitmapFontProvider(FontInfo info, ITexture texture, Int2ObjectMap<CharInstance>[] instances)
{ {
this.info = info; this.info = info;
this.texture = texture; this.texture = texture;
this.instances = instances; this.instances = instances;
if(instances[0].containsKey(' ')) space = instances[0].get(' ').getXAdvance(); if(instances[0].containsKey(' ')) space = instances[0].get(' ').getXAdvance();
else if(instances[1].containsKey(' ')) space = instances[1].get(' ').getXAdvance(); else if(instances[1].containsKey(' ')) space = instances[1].get(' ').getXAdvance();
} }
@Override @Override
public void destroy() public void destroy()
{ {
if(texture != null) if(texture != null)
{ {
texture.destroy(); texture.destroy();
texture = null; texture = null;
} }
} }
@Override @Override
public ITexture getTexture() public ITexture getTexture()
{ {
return texture; return texture;
} }
@Override @Override
public boolean isCharacterValid(int codepoint) public boolean isCharacterValid(int codepoint)
{ {
return instances[0].containsKey(codepoint) || instances[1].containsKey(codepoint); return instances[0].containsKey(codepoint) || instances[1].containsKey(codepoint);
} }
@Override @Override
public CharInstance getCharacter(int codepoint, boolean bold) public CharInstance getCharacter(int codepoint, boolean bold)
{ {
Int2ObjectMap<CharInstance> map = instances[bold ? 1 : 0]; Int2ObjectMap<CharInstance> map = instances[bold ? 1 : 0];
return (map.isEmpty() ? instances[bold ? 0 : 1] : map).get(codepoint); return (map.isEmpty() ? instances[bold ? 0 : 1] : map).get(codepoint);
} }
@Override @Override
public float height() public float height()
{ {
return info.fontHeight; return info.fontHeight;
} }
@Override @Override
public float baseLine() public float baseLine()
{ {
return info.fontBase; return info.fontBase;
} }
@Override @Override
public float getSpaceWidth() public float getSpaceWidth()
{ {
return space; return space;
} }
@Override @Override
public float getTabWidth() public float getTabWidth()
{ {
return space * info.tabs; return space * info.tabs;
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static BitmapFontProvider load(JsonObject object, float desiredSize, AssetManager manager) public static BitmapFontProvider load(JsonObject object, float desiredSize, AssetManager manager)
{ {
FontInfo info = new FontInfo(object.getAsJsonObject("info")); FontInfo info = new FontInfo(object.getAsJsonObject("info"));
float multiplier = info.setDesiredHeight(desiredSize); float multiplier = info.setDesiredHeight(desiredSize);
Int2ObjectMap<CharInstance>[] maps = new Int2ObjectMap[]{new Int2ObjectOpenHashMap<>(), new Int2ObjectOpenHashMap<>()}; Int2ObjectMap<CharInstance>[] maps = new Int2ObjectMap[]{new Int2ObjectOpenHashMap<>(), new Int2ObjectOpenHashMap<>()};
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] = Int2ObjectMaps.empty(); if(maps[0].isEmpty()) maps[0] = Int2ObjectMaps.empty();
if(maps[1].isEmpty()) maps[1] = Int2ObjectMaps.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);
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static IFontProvider create(JsonObject object, float desiredSize, AssetManager manager) public static IFontProvider create(JsonObject object, float desiredSize, AssetManager manager)
{ {
try(IAsset asset = TextureManager.INSTANCE.getManager().getAsset(AssetLocation.of(object.get("file").getAsString()))) try(IAsset asset = TextureManager.INSTANCE.getManager().getAsset(AssetLocation.of(object.get("file").getAsString())))
{ {
JsonObject info = object.getAsJsonObject("info"); JsonObject info = object.getAsJsonObject("info");
int tabs = JsonUtil.getOrDefault(info, "tabs", 4); int tabs = JsonUtil.getOrDefault(info, "tabs", 4);
boolean literal = JsonUtil.getOrDefault(info, "literal", false); boolean literal = JsonUtil.getOrDefault(info, "literal", false);
boolean plain = JsonUtil.getOrDefault(info, "plain", true); boolean plain = JsonUtil.getOrDefault(info, "plain", true);
boolean bold = JsonUtil.getOrDefault(info, "bold", true); boolean bold = JsonUtil.getOrDefault(info, "bold", true);
if(!plain && !bold) throw new IllegalStateException("You need a plain or bold font at the very least"); if(!plain && !bold) throw new IllegalStateException("You need a plain or bold font at the very least");
int flags = (literal ? FontBuilder.LITERAL : 0) | (plain ? FontBuilder.PLAIN : 0) | (bold ? FontBuilder.BOLD : 0); int flags = (literal ? FontBuilder.LITERAL : 0) | (plain ? FontBuilder.PLAIN : 0) | (bold ? FontBuilder.BOLD : 0);
ObjectObjectPair<ObjectObjectPair<Vec2i, BufferedImage>, List<WrittenChar>> written = FontBuilder.createBitmapFont(asset.stream(), info.get("charset").getAsString(), flags, info.get("size").getAsFloat()); ObjectObjectPair<ObjectObjectPair<Vec2i, BufferedImage>, List<WrittenChar>> written = FontBuilder.createBitmapFont(asset.stream(), info.get("charset").getAsString(), flags, info.get("size").getAsFloat());
BufferedImage image = written.getKey().getValue(); BufferedImage image = written.getKey().getValue();
Vec2i size = written.getKey().getKey(); Vec2i size = written.getKey().getKey();
FontInfo fontInfo = new FontInfo(image.getWidth(), image.getHeight(), size.y(), size.x(), tabs); FontInfo fontInfo = new FontInfo(image.getWidth(), image.getHeight(), size.y(), size.x(), tabs);
float mulitplier = fontInfo.setDesiredHeight(desiredSize); float mulitplier = fontInfo.setDesiredHeight(desiredSize);
Int2ObjectMap<CharInstance>[] maps = new Int2ObjectMap[]{new Int2ObjectOpenHashMap<CharInstance>(), new Int2ObjectOpenHashMap<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] = Int2ObjectMaps.empty(); if(maps[0].isEmpty()) maps[0] = Int2ObjectMaps.empty();
if(maps[1].isEmpty()) maps[1] = Int2ObjectMaps.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)
{ {
e.printStackTrace(); e.printStackTrace();
} }
return null; return null;
} }
} }

View File

@ -1,100 +1,100 @@
package speiger.src.coreengine.rendering.guiOld.renderer.provider; package speiger.src.coreengine.rendering.guiOld.renderer.provider;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import speiger.src.collections.objects.lists.ObjectArrayList; import speiger.src.collections.objects.lists.ObjectArrayList;
import speiger.src.collections.objects.maps.impl.hash.Object2FloatLinkedOpenHashMap; import speiger.src.collections.objects.maps.impl.hash.Object2FloatLinkedOpenHashMap;
import speiger.src.collections.objects.maps.impl.hash.Object2ObjectLinkedOpenHashMap; import speiger.src.collections.objects.maps.impl.hash.Object2ObjectLinkedOpenHashMap;
import speiger.src.collections.objects.maps.impl.hash.Object2ObjectOpenHashMap; import speiger.src.collections.objects.maps.impl.hash.Object2ObjectOpenHashMap;
import speiger.src.collections.objects.maps.interfaces.Object2FloatMap; import speiger.src.collections.objects.maps.interfaces.Object2FloatMap;
import speiger.src.collections.objects.maps.interfaces.Object2FloatMap.Entry; import speiger.src.collections.objects.maps.interfaces.Object2FloatMap.Entry;
import speiger.src.collections.objects.utils.maps.Object2FloatMaps; import speiger.src.collections.objects.utils.maps.Object2FloatMaps;
import speiger.src.coreengine.assets.AssetLocation; import speiger.src.coreengine.assets.AssetLocation;
import speiger.src.coreengine.assets.AssetManager; import speiger.src.coreengine.assets.AssetManager;
import speiger.src.coreengine.assets.base.IAsset; import speiger.src.coreengine.assets.base.IAsset;
import speiger.src.coreengine.assets.reloader.IReloadableResource; import speiger.src.coreengine.assets.reloader.IReloadableResource;
import speiger.src.coreengine.rendering.guiOld.renderer.FontRenderer; import speiger.src.coreengine.rendering.guiOld.renderer.FontRenderer;
public class FontManager implements IReloadableResource public class FontManager implements IReloadableResource
{ {
Map<AssetLocation, FontRenderer> fontRenders = new Object2ObjectLinkedOpenHashMap<>(); Map<AssetLocation, FontRenderer> fontRenders = new Object2ObjectLinkedOpenHashMap<>();
Object2FloatMap<AssetLocation> fontSizes = new Object2FloatLinkedOpenHashMap<>(); Object2FloatMap<AssetLocation> fontSizes = new Object2FloatLinkedOpenHashMap<>();
Map<String, IFontLoader> loaders = new Object2ObjectOpenHashMap<>(); Map<String, IFontLoader> loaders = new Object2ObjectOpenHashMap<>();
AssetManager manager; AssetManager manager;
public FontManager() public FontManager()
{ {
registerFontLoader("bitmap", BitmapFontProvider::load); registerFontLoader("bitmap", BitmapFontProvider::load);
registerFontLoader("java-ttf", BitmapFontProvider::create); registerFontLoader("java-ttf", BitmapFontProvider::create);
} }
public void setAssetManager(AssetManager manager) public void setAssetManager(AssetManager manager)
{ {
this.manager = manager; this.manager = manager;
} }
public void registerFontLoader(String id, IFontLoader provider) public void registerFontLoader(String id, IFontLoader provider)
{ {
loaders.put(id, provider); loaders.put(id, provider);
} }
public FontRenderer loadFont(AssetLocation location, float desiredSize) public FontRenderer loadFont(AssetLocation location, float desiredSize)
{ {
FontRenderer render = fontRenders.get(location); FontRenderer render = fontRenders.get(location);
if(render == null) if(render == null)
{ {
IFontProvider provider = loadProvider(location, desiredSize); IFontProvider provider = loadProvider(location, desiredSize);
if(provider != null) if(provider != null)
{ {
render = new FontRenderer(); render = new FontRenderer();
render.setProvider(provider); render.setProvider(provider);
fontRenders.put(location, render); fontRenders.put(location, render);
fontSizes.putIfAbsent(location, desiredSize); fontSizes.putIfAbsent(location, desiredSize);
} }
} }
return render; return render;
} }
private IFontProvider loadProvider(AssetLocation location, float desiredSize) private IFontProvider loadProvider(AssetLocation location, float desiredSize)
{ {
try(IAsset asset = manager.getAsset(location)) try(IAsset asset = manager.getAsset(location))
{ {
JsonObject obj = asset.json(); JsonObject obj = asset.json();
IFontLoader loader = loaders.get(obj.get("type").getAsString()); IFontLoader loader = loaders.get(obj.get("type").getAsString());
if(loader == null) return null; if(loader == null) return null;
return loader.create(obj, desiredSize, manager); return loader.create(obj, desiredSize, manager);
} }
catch(Exception e) { e.printStackTrace(); } catch(Exception e) { e.printStackTrace(); }
return null; return null;
} }
public static interface IFontLoader public static interface IFontLoader
{ {
public IFontProvider create(JsonObject obj, float desiredSize, AssetManager loader); public IFontProvider create(JsonObject obj, float desiredSize, AssetManager loader);
} }
@Override @Override
public void reload() public void reload()
{ {
List<IFontProvider> providers = new ObjectArrayList<>(); List<IFontProvider> providers = new ObjectArrayList<>();
for(Entry<AssetLocation> entry : Object2FloatMaps.fastIterable(fontSizes)) for(Entry<AssetLocation> entry : Object2FloatMaps.fastIterable(fontSizes))
{ {
AssetLocation location = entry.getKey(); AssetLocation location = entry.getKey();
FontRenderer font = fontRenders.get(location); FontRenderer font = fontRenders.get(location);
providers.add(font.getProvider()); providers.add(font.getProvider());
font.setProvider(loadProvider(location, entry.getFloatValue())); font.setProvider(loadProvider(location, entry.getFloatValue()));
} }
for(int i = 0,m=providers.size();i<m;providers.get(i++).destroy()); for(int i = 0,m=providers.size();i<m;providers.get(i++).destroy());
} }
@Override @Override
public void destroy() public void destroy()
{ {
fontRenders.values().forEach(FontRenderer::destory); fontRenders.values().forEach(FontRenderer::destory);
fontRenders.clear(); fontRenders.clear();
} }
} }

View File

@ -66,10 +66,10 @@ public class Window
protected void initWindowListeners() { protected void initWindowListeners() {
addCallback(T -> GLFW.glfwSetFramebufferSizeCallback(T, this::onResize)); addCallback(T -> GLFW.glfwSetFramebufferSizeCallback(T, this::onResize));
addCallback(T -> GLFW.glfwSetWindowMaximizeCallback(T, (K, V) -> flags.setFlag(FLAG_WINDOW_CHANGE))); addCallback(T -> GLFW.glfwSetWindowMaximizeCallback(T, (_, _) -> flags.setFlag(FLAG_WINDOW_CHANGE)));
addCallback(T -> GLFW.glfwSetWindowPosCallback(T, (W, X, Y) -> setPosition(X, Y))); addCallback(T -> GLFW.glfwSetWindowPosCallback(T, (_, X, Y) -> setPosition(X, Y)));
addCallback(T -> GLFW.glfwSetWindowFocusCallback(T, (K, V) -> flags.setFlag(FLAG_FOCUS, V))); addCallback(T -> GLFW.glfwSetWindowFocusCallback(T, (_, V) -> flags.setFlag(FLAG_FOCUS, V)));
addCallback(T -> GLFW.glfwSetErrorCallback(this::error)); addCallback(_ -> GLFW.glfwSetErrorCallback(this::error));
} }
private void error(int error, long text) { private void error(int error, long text) {

View File

@ -1,103 +1,103 @@
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.nio.ByteOrder;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import speiger.src.collections.objects.lists.ObjectArrayList; import speiger.src.collections.objects.lists.ObjectArrayList;
import speiger.src.collections.objects.utils.ObjectLists; import speiger.src.collections.objects.utils.ObjectLists;
import speiger.src.coreengine.assets.AssetLocation; import speiger.src.coreengine.assets.AssetLocation;
import speiger.src.coreengine.assets.AssetManager; import speiger.src.coreengine.assets.AssetManager;
import speiger.src.coreengine.assets.base.IAsset; import speiger.src.coreengine.assets.base.IAsset;
import speiger.src.coreengine.math.misc.ColorUtils; import speiger.src.coreengine.math.misc.ColorUtils;
import speiger.src.coreengine.utils.collections.iterators.IterableWrapper; import speiger.src.coreengine.utils.collections.iterators.IterableWrapper;
import speiger.src.coreengine.utils.helpers.JsonUtil; import speiger.src.coreengine.utils.helpers.JsonUtil;
public class ModelLoader public class ModelLoader
{ {
public static List<SimpleModelData> readModelData(AssetLocation location, AssetManager manager) public static List<SimpleModelData> readModelData(AssetLocation location, AssetManager manager)
{ {
try(IAsset asset = manager.getAsset(location)) try(IAsset asset = manager.getAsset(location))
{ {
List<SimpleModelData> result = new ObjectArrayList<>(); List<SimpleModelData> result = new ObjectArrayList<>();
JsonObject obj = asset.json(); JsonObject obj = asset.json();
JsonUtil.iterate(obj.get("models"), T -> { JsonUtil.iterate(obj.get("models"), T -> {
JsonObject info = T.getAsJsonObject("info"); JsonObject info = T.getAsJsonObject("info");
JsonObject format = T.getAsJsonObject("format"); JsonObject format = T.getAsJsonObject("format");
JsonObject data = T.getAsJsonObject("data"); JsonObject data = T.getAsJsonObject("data");
List<VertexEntry> entries = VertexLoader.loadVertexFormat(format); List<VertexEntry> entries = VertexLoader.loadVertexFormat(format);
ByteBuffer buffer = VertexLoader.parseVertexData(data, info.get("vertecies").getAsInt(), entries, true); 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")))); result.add(new SimpleModelData(info.get("name").getAsString(), UUID.fromString(info.get("id").getAsString()), buffer.array(), JsonUtil.parseIntArray(data.getAsJsonArray("indecies"))));
}); });
return result; return result;
} }
catch(Exception e) catch(Exception e)
{ {
e.printStackTrace(); e.printStackTrace();
} }
return ObjectLists.empty(); return ObjectLists.empty();
} }
public static List<SimpleModelData> readLegacyModelData(AssetLocation location, AssetManager manager) public static List<SimpleModelData> readLegacyModelData(AssetLocation location, AssetManager manager)
{ {
List<SimpleModelData> resultModels = new ObjectArrayList<SimpleModelData>(); List<SimpleModelData> resultModels = new ObjectArrayList<SimpleModelData>();
ByteBuffer buffer = null; ByteBuffer buffer = null;
int[] indexes = null; int[] indexes = null;
String currentName = null; String currentName = null;
try(IAsset asset = manager.getAsset(location)) try(IAsset asset = manager.getAsset(location))
{ {
boolean flag = false; boolean flag = false;
for(String line : IterableWrapper.wrap(asset.reader())) for(String line : IterableWrapper.wrap(asset.reader()))
{ {
if(line.startsWith("{")) if(line.startsWith("{"))
{ {
if(currentName != null) if(currentName != null)
{ {
resultModels.add(new SimpleModelData(currentName, null, buffer.array(), indexes)); resultModels.add(new SimpleModelData(currentName, null, buffer.array(), indexes));
currentName = null; currentName = null;
} }
currentName = line.substring(1, line.length() - 1); currentName = line.substring(1, line.length() - 1);
flag = true; flag = true;
} }
else if(flag) else if(flag)
{ {
flag = false; flag = false;
String[] bounds = line.split(";"); String[] bounds = line.split(";");
buffer = ByteBuffer.allocate(Integer.parseInt(bounds[0]) * 28).order(ByteOrder.nativeOrder()); buffer = ByteBuffer.allocate(Integer.parseInt(bounds[0]) * 28).order(ByteOrder.nativeOrder());
indexes = new int[Integer.parseInt(bounds[1])]; indexes = new int[Integer.parseInt(bounds[1])];
} }
else if(line.startsWith("<")) else if(line.startsWith("<"))
{ {
String[] data = line.substring(1, line.length() - 1).split(" "); String[] data = line.substring(1, line.length() - 1).split(" ");
String[] position = data[0].split(";"); String[] position = data[0].split(";");
String[] normal = data[2].split(";"); String[] normal = data[2].split(";");
buffer.putFloat(Float.parseFloat(position[0])).putFloat(Float.parseFloat(position[1])).putFloat(Float.parseFloat(position[2])); buffer.putFloat(Float.parseFloat(position[0])).putFloat(Float.parseFloat(position[1])).putFloat(Float.parseFloat(position[2]));
ColorUtils.write(Integer.parseInt(data[1]), true, buffer); ColorUtils.write(Integer.parseInt(data[1]), true, buffer);
buffer.putFloat(Float.parseFloat(normal[0])).putFloat(Float.parseFloat(normal[1])).putFloat(Float.parseFloat(normal[2])); buffer.putFloat(Float.parseFloat(normal[0])).putFloat(Float.parseFloat(normal[1])).putFloat(Float.parseFloat(normal[2]));
} }
else if(line.startsWith("[")) else if(line.startsWith("["))
{ {
String[] data = line.substring(1, line.length() - 1).split(";"); String[] data = line.substring(1, line.length() - 1).split(";");
for(int j = 0;j<data.length;j++) for(int j = 0;j<data.length;j++)
{ {
indexes[j] = Integer.parseInt(data[j]); indexes[j] = Integer.parseInt(data[j]);
} }
} }
} }
if(currentName != null) if(currentName != null)
{ {
resultModels.add(new SimpleModelData(currentName, null, buffer.array(), indexes)); resultModels.add(new SimpleModelData(currentName, null, buffer.array(), indexes));
currentName = null; currentName = null;
} }
} }
catch(Exception e) catch(Exception e)
{ {
e.printStackTrace(); e.printStackTrace();
} }
return resultModels; return resultModels;
} }
} }

View File

@ -1,137 +1,137 @@
package speiger.src.coreengine.rendering.shader; package speiger.src.coreengine.rendering.shader;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.file.attribute.FileTime; import java.nio.file.attribute.FileTime;
import java.util.Map; import java.util.Map;
import java.util.function.IntPredicate; import java.util.function.IntPredicate;
import org.lwjgl.opengl.GL20; import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL41; import org.lwjgl.opengl.GL41;
import org.lwjgl.opengl.GL45; import org.lwjgl.opengl.GL45;
import org.lwjgl.opengl.GL46; import org.lwjgl.opengl.GL46;
import org.lwjgl.system.MemoryUtil; import org.lwjgl.system.MemoryUtil;
import speiger.src.collections.objects.maps.interfaces.Object2ObjectMap; import speiger.src.collections.objects.maps.interfaces.Object2ObjectMap;
import speiger.src.coreengine.assets.AssetLocation; import speiger.src.coreengine.assets.AssetLocation;
import speiger.src.coreengine.assets.base.IAsset; import speiger.src.coreengine.assets.base.IAsset;
import speiger.src.coreengine.assets.base.IAssetProvider; import speiger.src.coreengine.assets.base.IAssetProvider;
import speiger.src.coreengine.math.ArrayUtil; import speiger.src.coreengine.math.ArrayUtil;
import speiger.src.coreengine.rendering.shader.uniform.UniformManager; import speiger.src.coreengine.rendering.shader.uniform.UniformManager;
import speiger.src.coreengine.rendering.utils.GLStateTracker; import speiger.src.coreengine.rendering.utils.GLStateTracker;
import speiger.src.coreengine.rendering.utils.values.IGLValue.IShaderType; import speiger.src.coreengine.rendering.utils.values.IGLValue.IShaderType;
import speiger.src.coreengine.utils.io.GameLog; import speiger.src.coreengine.utils.io.GameLog;
public abstract class ShaderProgram { public abstract class ShaderProgram {
static final Map<AssetLocation, String> IMPORTS = Object2ObjectMap.builder().<AssetLocation, String>map().synchronize(); static final Map<AssetLocation, String> IMPORTS = Object2ObjectMap.builder().<AssetLocation, String>map().synchronize();
protected final UniformManager uniforms = new UniformManager(this); protected final UniformManager uniforms = new UniformManager(this);
private int id; private int id;
public boolean isValid() { return id != 0; } public boolean isValid() { return id != 0; }
public boolean isActive() { return GLStateTracker.instance().shaders.isShaderActive(this); } public boolean isActive() { return GLStateTracker.instance().shaders.isShaderActive(this); }
public int id() { return id; } public int id() { return id; }
public UniformManager getUniforms() { return uniforms; } public UniformManager getUniforms() { return uniforms; }
protected void setId(int id) { protected void setId(int id) {
this.id = id; this.id = id;
} }
public void bind() { public void bind() {
GLStateTracker.instance().shaders.bind(this); GLStateTracker.instance().shaders.bind(this);
uniforms.bind(); uniforms.bind();
} }
public void remove() { public void remove() {
if(id == 0) return; if(id == 0) return;
uniforms.remove(); uniforms.remove();
GL20.glDeleteProgram(id); GL20.glDeleteProgram(id);
id = 0; id = 0;
} }
public void validateProgram() { public void validateProgram() {
if(id == 0) return; if(id == 0) return;
uniforms.validate(); uniforms.validate();
GL46.glValidateProgram(id); GL46.glValidateProgram(id);
} }
public static int loadOrGenerateCache(String location, FileTime newestResource, IntPredicate callback) { public static int loadOrGenerateCache(String location, FileTime newestResource, IntPredicate callback) {
int id = GL20.glCreateProgram(); int id = GL20.glCreateProgram();
boolean fail = true; boolean fail = true;
if((fail = !loadFromBinary(id, location, newestResource)) && callback.test(id)) { if((fail = !loadFromBinary(id, location, newestResource)) && callback.test(id)) {
if(GL46.glGetProgrami(id, GL46.GL_LINK_STATUS) == GL46.GL_TRUE) { if(GL46.glGetProgrami(id, GL46.GL_LINK_STATUS) == GL46.GL_TRUE) {
if(ShaderCache.INSTANCE.hasCache()) ShaderCache.INSTANCE.storeInCache(location, getProgramBytes(id)); if(ShaderCache.INSTANCE.hasCache()) ShaderCache.INSTANCE.storeInCache(location, getProgramBytes(id));
fail = false; fail = false;
} }
} }
if(fail) { if(fail) {
GL20.glDeleteProgram(id); GL20.glDeleteProgram(id);
return 0; return 0;
} }
String error = GL45.glGetProgramInfoLog(id); String error = GL45.glGetProgramInfoLog(id);
if(!error.isBlank()) { if(!error.isBlank()) {
System.out.println("Error: "+error); System.out.println("Error: "+error);
} }
return id; return id;
} }
private static boolean loadFromBinary(int programId, String location, FileTime newestResource) { private static boolean loadFromBinary(int programId, String location, FileTime newestResource) {
ByteBuffer buffer = ShaderCache.INSTANCE.readFromCache(location, newestResource); ByteBuffer buffer = ShaderCache.INSTANCE.readFromCache(location, newestResource);
if(buffer != null) { if(buffer != null) {
GL41.glProgramBinary(programId, buffer.getInt(), buffer); GL41.glProgramBinary(programId, buffer.getInt(), buffer);
MemoryUtil.memFree(buffer); MemoryUtil.memFree(buffer);
if(GL46.glGetProgrami(programId, GL46.GL_LINK_STATUS) == GL46.GL_TRUE) return true; if(GL46.glGetProgrami(programId, GL46.GL_LINK_STATUS) == GL46.GL_TRUE) return true;
} }
return false; return false;
} }
private static byte[] getProgramBytes(int programId) { private static byte[] getProgramBytes(int programId) {
ByteBuffer buffer = MemoryUtil.memAlloc(GL20.glGetProgrami(programId, GL41.GL_PROGRAM_BINARY_LENGTH) + 4); ByteBuffer buffer = MemoryUtil.memAlloc(GL20.glGetProgrami(programId, GL41.GL_PROGRAM_BINARY_LENGTH) + 4);
int[] format = new int[1]; int[] format = new int[1];
GL41.glGetProgramBinary(programId, null, format, buffer.position(4)); GL41.glGetProgramBinary(programId, null, format, buffer.position(4));
return ArrayUtil.toArray(buffer.putInt(0, format[0]).flip(), MemoryUtil::memFree); return ArrayUtil.toArray(buffer.putInt(0, format[0]).flip(), MemoryUtil::memFree);
} }
public static int loadShader(IAssetProvider provider, AssetLocation location, IShaderType type) { public static int loadShader(IAssetProvider provider, AssetLocation location, IShaderType type) {
StringBuilder builder = new StringBuilder(2048); StringBuilder builder = new StringBuilder(2048);
try(IAsset asset = provider.getAsset(location)) { try(IAsset asset = provider.getAsset(location)) {
for(String line : asset.lines()) { for(String line : asset.lines()) {
if(line.startsWith("//")) continue; if(line.startsWith("//")) continue;
if(line.startsWith("#import<") && line.endsWith(">")) { if(line.startsWith("#import<") && line.endsWith(">")) {
builder.append(importLines(provider, AssetLocation.of(line.substring(8, line.length()-1)))).append("\n"); builder.append(importLines(provider, AssetLocation.of(line.substring(8, line.length()-1)))).append("\n");
continue; continue;
} }
builder.append(line).append("\n"); builder.append(line).append("\n");
} }
} }
catch(Exception e) { catch(Exception e) {
e.printStackTrace(); e.printStackTrace();
return -1; return -1;
} }
int shaderID = GL20.glCreateShader(type.glValue()); int shaderID = GL20.glCreateShader(type.glValue());
GL20.glShaderSource(shaderID, builder); GL20.glShaderSource(shaderID, builder);
GL20.glCompileShader(shaderID); GL20.glCompileShader(shaderID);
if(GL20.glGetShaderi(shaderID, GL20.GL_COMPILE_STATUS) == 0) { if(GL20.glGetShaderi(shaderID, GL20.GL_COMPILE_STATUS) == 0) {
GameLog.warn("Could not compile shader " + location); GameLog.warn("Could not compile shader " + location);
GameLog.error(GL20.glGetShaderInfoLog(shaderID, GL20.glGetShaderi(shaderID, GL20.GL_INFO_LOG_LENGTH))); GameLog.error(GL20.glGetShaderInfoLog(shaderID, GL20.glGetShaderi(shaderID, GL20.GL_INFO_LOG_LENGTH)));
GL20.glDeleteShader(shaderID); GL20.glDeleteShader(shaderID);
return -1; return -1;
} }
return shaderID; return shaderID;
} }
public static String importLines(IAssetProvider provider, AssetLocation location) { public static String importLines(IAssetProvider provider, AssetLocation location) {
return IMPORTS.computeIfAbsent(location, T -> { return IMPORTS.computeIfAbsent(location, T -> {
try(IAsset asset = provider.getAsset(T)) { try(IAsset asset = provider.getAsset(T)) {
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
for(String line : asset.lines()) { for(String line : asset.lines()) {
if(line.startsWith("//")) continue; if(line.startsWith("//")) continue;
builder.append(line).append("\n"); builder.append(line).append("\n");
} }
return builder.toString(); return builder.toString();
} }
catch(Exception e) { catch(Exception e) {
e.printStackTrace(); e.printStackTrace();
return ""; return "";
} }
}); });
} }
} }

View File

@ -1,109 +1,109 @@
package speiger.src.coreengine.rendering.shaderOld; package speiger.src.coreengine.rendering.shaderOld;
import java.util.List; import java.util.List;
import org.lwjgl.opengl.GL20; import org.lwjgl.opengl.GL20;
import speiger.src.collections.objects.lists.ObjectArrayList; import speiger.src.collections.objects.lists.ObjectArrayList;
import speiger.src.coreengine.assets.AssetLocation; import speiger.src.coreengine.assets.AssetLocation;
import speiger.src.coreengine.assets.base.IAsset; import speiger.src.coreengine.assets.base.IAsset;
import speiger.src.coreengine.rendering.shaderOld.ShaderTracker.ReloadReference; import speiger.src.coreengine.rendering.shaderOld.ShaderTracker.ReloadReference;
import speiger.src.coreengine.rendering.shaderOld.uniforms.Uniform; import speiger.src.coreengine.rendering.shaderOld.uniforms.Uniform;
import speiger.src.coreengine.utils.collections.iterators.IterableWrapper; import speiger.src.coreengine.utils.collections.iterators.IterableWrapper;
import speiger.src.coreengine.utils.io.GameLog; import speiger.src.coreengine.utils.io.GameLog;
public abstract class ShaderProgram public abstract class ShaderProgram
{ {
protected List<Uniform> localUniforms = new ObjectArrayList<>(); protected List<Uniform> localUniforms = new ObjectArrayList<>();
ReloadReference<?> reference; ReloadReference<?> reference;
private int shaderID; private int shaderID;
protected ShaderProgram(AssetLocation vertex, AssetLocation fragment, String[] attributes) { protected ShaderProgram(AssetLocation vertex, AssetLocation fragment, String[] attributes) {
int vertexID = loadShader(vertex, GL20.GL_VERTEX_SHADER); int vertexID = loadShader(vertex, GL20.GL_VERTEX_SHADER);
int fragmentID = loadShader(fragment, GL20.GL_FRAGMENT_SHADER); int fragmentID = loadShader(fragment, GL20.GL_FRAGMENT_SHADER);
if(vertexID == -1 || fragmentID == -1) { if(vertexID == -1 || fragmentID == -1) {
shaderID = 0; shaderID = 0;
return; return;
} }
shaderID = GL20.glCreateProgram(); shaderID = GL20.glCreateProgram();
GL20.glAttachShader(shaderID, vertexID); GL20.glAttachShader(shaderID, vertexID);
GL20.glAttachShader(shaderID, fragmentID); GL20.glAttachShader(shaderID, fragmentID);
for(int i = 0;i < attributes.length;i++) { for(int i = 0;i < attributes.length;i++) {
GL20.glBindAttribLocation(shaderID, i, attributes[i]); GL20.glBindAttribLocation(shaderID, i, attributes[i]);
} }
GL20.glLinkProgram(shaderID); GL20.glLinkProgram(shaderID);
GL20.glDetachShader(shaderID, vertexID); GL20.glDetachShader(shaderID, vertexID);
GL20.glDetachShader(shaderID, fragmentID); GL20.glDetachShader(shaderID, fragmentID);
GL20.glDeleteShader(vertexID); GL20.glDeleteShader(vertexID);
GL20.glDeleteShader(fragmentID); GL20.glDeleteShader(fragmentID);
} }
public void addUniforms(Uniform... uniforms) { public void addUniforms(Uniform... uniforms) {
for(Uniform uni : uniforms) { for(Uniform uni : uniforms) {
uni.loadUniform(this); uni.loadUniform(this);
localUniforms.add(uni); localUniforms.add(uni);
} }
GL20.glValidateProgram(shaderID); GL20.glValidateProgram(shaderID);
} }
void setReference(ReloadReference<?> ref) { void setReference(ReloadReference<?> ref) {
reference = ref; reference = ref;
} }
public abstract ShaderProgram init(); public abstract ShaderProgram init();
public boolean isShaderValid() { public boolean isShaderValid() {
return shaderID != 0; return shaderID != 0;
} }
public int getShaderID() { public int getShaderID() {
return shaderID; return shaderID;
} }
public void startShader() { public void startShader() {
ShaderTracker.INSTANCE.startNextShader(this); ShaderTracker.INSTANCE.startNextShader(this);
} }
public void stopShader() { public void stopShader() {
ShaderTracker.INSTANCE.stopShader(this); ShaderTracker.INSTANCE.stopShader(this);
} }
public boolean isShaderRunning() { public boolean isShaderRunning() {
return ShaderTracker.INSTANCE.activeShader == getShaderID(); return ShaderTracker.INSTANCE.activeShader == getShaderID();
} }
public void removeShader() { public void removeShader() {
if(shaderID == 0) return; if(shaderID == 0) return;
stopShader(); stopShader();
GL20.glDeleteProgram(shaderID); GL20.glDeleteProgram(shaderID);
shaderID = 0; shaderID = 0;
reference.removeReference(); reference.removeReference();
reference = null; reference = null;
} }
private int loadShader(AssetLocation location, int type) { private int loadShader(AssetLocation location, int type) {
StringBuilder shaderSource = new StringBuilder(); StringBuilder shaderSource = new StringBuilder();
try(IAsset asset = ShaderTracker.INSTANCE.getAssets().getAsset(location)) { try(IAsset asset = ShaderTracker.INSTANCE.getAssets().getAsset(location)) {
for(String s : IterableWrapper.wrap(asset.reader())) for(String s : IterableWrapper.wrap(asset.reader()))
{ {
if(s.startsWith("//")) continue; if(s.startsWith("//")) continue;
shaderSource.append(s).append("\n"); shaderSource.append(s).append("\n");
} }
} }
catch(Exception e) { catch(Exception e) {
e.printStackTrace(); e.printStackTrace();
return -1; return -1;
} }
int shaderID = GL20.glCreateShader(type); int shaderID = GL20.glCreateShader(type);
GL20.glShaderSource(shaderID, shaderSource); GL20.glShaderSource(shaderID, shaderSource);
GL20.glCompileShader(shaderID); GL20.glCompileShader(shaderID);
if(GL20.glGetShaderi(shaderID, GL20.GL_COMPILE_STATUS) == 0) { if(GL20.glGetShaderi(shaderID, GL20.GL_COMPILE_STATUS) == 0) {
GameLog.warn("Could not compile shader " + location); GameLog.warn("Could not compile shader " + location);
int[] length = new int[1]; int[] length = new int[1];
GL20.glGetShaderiv(shaderID, GL20.GL_INFO_LOG_LENGTH, length); GL20.glGetShaderiv(shaderID, GL20.GL_INFO_LOG_LENGTH, length);
GameLog.error(GL20.glGetShaderInfoLog(shaderID, length[0])); GameLog.error(GL20.glGetShaderInfoLog(shaderID, length[0]));
return -1; return -1;
} }
return shaderID; return shaderID;
} }
} }

View File

@ -6,8 +6,8 @@ import speiger.src.coreengine.math.vector.floats.Vec2f;
import speiger.src.coreengine.math.vector.floats.Vec3f; import speiger.src.coreengine.math.vector.floats.Vec3f;
import speiger.src.coreengine.rendering.models.DrawCall; import speiger.src.coreengine.rendering.models.DrawCall;
import speiger.src.coreengine.rendering.tesselation.format.VertexElement; import speiger.src.coreengine.rendering.tesselation.format.VertexElement;
import speiger.src.coreengine.rendering.tesselation.format.VertexFormat;
import speiger.src.coreengine.rendering.tesselation.format.VertexElement.Usage; import speiger.src.coreengine.rendering.tesselation.format.VertexElement.Usage;
import speiger.src.coreengine.rendering.tesselation.format.VertexFormat;
import speiger.src.coreengine.rendering.utils.values.GLMode; import speiger.src.coreengine.rendering.utils.values.GLMode;
public class Tesselator implements IVertexBuilder public class Tesselator implements IVertexBuilder

View File

@ -1,8 +1,8 @@
package speiger.src.coreengine.rendering.tesselationOld; package speiger.src.coreengine.rendering.tesselationOld;
import speiger.src.coreengine.rendering.tesselation.format.VertexElement; import speiger.src.coreengine.rendering.tesselation.format.VertexElement;
import speiger.src.coreengine.rendering.tesselation.format.VertexFormat;
import speiger.src.coreengine.rendering.tesselation.format.VertexElement.Usage; import speiger.src.coreengine.rendering.tesselation.format.VertexElement.Usage;
import speiger.src.coreengine.rendering.tesselation.format.VertexFormat;
public class VertexType public class VertexType
{ {

View File

@ -1,76 +1,76 @@
package speiger.src.coreengine.rendering.textures.simple; package speiger.src.coreengine.rendering.textures.simple;
import java.io.IOException; import java.io.IOException;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL11;
import org.lwjgl.stb.STBImage; import org.lwjgl.stb.STBImage;
import org.lwjgl.system.MemoryUtil; import org.lwjgl.system.MemoryUtil;
import speiger.src.coreengine.assets.AssetLocation; import speiger.src.coreengine.assets.AssetLocation;
import speiger.src.coreengine.assets.base.IAsset; import speiger.src.coreengine.assets.base.IAsset;
import speiger.src.coreengine.assets.base.IAssetProvider; import speiger.src.coreengine.assets.base.IAssetProvider;
import speiger.src.coreengine.assets.parsers.NativeMemoryParser; import speiger.src.coreengine.assets.parsers.NativeMemoryParser;
import speiger.src.coreengine.rendering.textures.base.BaseTexture; import speiger.src.coreengine.rendering.textures.base.BaseTexture;
import speiger.src.coreengine.rendering.textures.base.TextureMetadata; import speiger.src.coreengine.rendering.textures.base.TextureMetadata;
import speiger.src.coreengine.rendering.utils.GLFunctions; import speiger.src.coreengine.rendering.utils.GLFunctions;
import speiger.src.coreengine.rendering.utils.values.GLDataType; import speiger.src.coreengine.rendering.utils.values.GLDataType;
import speiger.src.coreengine.rendering.utils.values.textures.GLTextureFormat; import speiger.src.coreengine.rendering.utils.values.textures.GLTextureFormat;
import speiger.src.coreengine.rendering.utils.values.textures.GLTextureParameter; import speiger.src.coreengine.rendering.utils.values.textures.GLTextureParameter;
import speiger.src.coreengine.rendering.utils.values.textures.GLTextureValue; import speiger.src.coreengine.rendering.utils.values.textures.GLTextureValue;
public class SimpleTexture extends BaseTexture { public class SimpleTexture extends BaseTexture {
public static final TextureMetadata DEFAULT_DATA = TextureMetadata.builder() public static final TextureMetadata DEFAULT_DATA = TextureMetadata.builder()
.externalFormat(GLTextureFormat.RGBA).internalFormat(GLTextureFormat.RGBAI).dataFormat(GLDataType.UNSIGNED_BYTE).mipmapping(false) .externalFormat(GLTextureFormat.RGBA).internalFormat(GLTextureFormat.RGBAI).dataFormat(GLDataType.UNSIGNED_BYTE).mipmapping(false)
.arguement(GLTextureParameter.MIN_FILTER, GLTextureValue.NEAREST).arguement(GLTextureParameter.MAG_FILTER, GLTextureValue.NEAREST) .arguement(GLTextureParameter.MIN_FILTER, GLTextureValue.NEAREST).arguement(GLTextureParameter.MAG_FILTER, GLTextureValue.NEAREST)
.arguement(GLTextureParameter.WRAP_S, GLTextureValue.CLAMP_TO_EDGE).arguement(GLTextureParameter.WRAP_T, GLTextureValue.CLAMP_TO_EDGE).build(); .arguement(GLTextureParameter.WRAP_S, GLTextureValue.CLAMP_TO_EDGE).arguement(GLTextureParameter.WRAP_T, GLTextureValue.CLAMP_TO_EDGE).build();
AssetLocation location; AssetLocation location;
TextureMetadata metadata; TextureMetadata metadata;
int width; int width;
int height; int height;
public SimpleTexture(AssetLocation location, TextureMetadata metadata) { public SimpleTexture(AssetLocation location, TextureMetadata metadata) {
this.location = location; this.location = location;
this.metadata = metadata; this.metadata = metadata;
track(); track();
} }
@Override @Override
public void load(IAssetProvider provider) { public void load(IAssetProvider provider) {
long address = 0L; long address = 0L;
int channel = GLTextureFormat.stbComponents(GL11.GL_RGBA); int channel = GLTextureFormat.stbComponents(GL11.GL_RGBA);
try(IAsset asset = provider.getAsset(location)) { try(IAsset asset = provider.getAsset(location)) {
ByteBuffer buffer = asset.custom(NativeMemoryParser.INSTANCE); ByteBuffer buffer = asset.custom(NativeMemoryParser.INSTANCE);
int[] width = new int[1]; int[] width = new int[1];
int[] height = new int[1]; int[] height = new int[1];
int[] fileChannels = new int[1]; int[] fileChannels = new int[1];
address = STBImage.nstbi_load_from_memory(MemoryUtil.memAddress(buffer), buffer.remaining(), width, height, fileChannels, channel); address = STBImage.nstbi_load_from_memory(MemoryUtil.memAddress(buffer), buffer.remaining(), width, height, fileChannels, channel);
MemoryUtil.memFree(buffer); MemoryUtil.memFree(buffer);
if(address == 0) { if(address == 0) {
throw new IllegalArgumentException("Couldn't load texture ["+location+"]"); throw new IllegalArgumentException("Couldn't load texture ["+location+"]");
} }
this.width = width[0]; this.width = width[0];
this.height = height[0]; this.height = height[0];
if(channel == 0) channel = fileChannels[0]; if(channel == 0) channel = fileChannels[0];
} }
catch(IOException e) { catch(IOException e) {
e.printStackTrace(); e.printStackTrace();
} }
if(address == 0L) return; if(address == 0L) return;
createTexture(); createTexture();
metadata.applyArguments(id()); metadata.applyArguments(id());
GLFunctions.upload2DImage(id(), 0, metadata, width, height, 0, address); GLFunctions.upload2DImage(id(), 0, metadata, width, height, 0, address);
if(metadata.generateMipMappings()) GLFunctions.generateMipMaps(textureType()); if(metadata.generateMipMappings()) GLFunctions.generateMipMaps(textureType());
STBImage.nstbi_image_free(address); STBImage.nstbi_image_free(address);
} }
@Override @Override
public int width() { public int width() {
return width; return width;
} }
@Override @Override
public int height() { public int height() {
return height; return height;
} }
} }

View File

@ -1,144 +1,144 @@
package speiger.src.coreengine.rendering.texturesOld.base; package speiger.src.coreengine.rendering.texturesOld.base;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import org.lwjgl.glfw.GLFWImage; import org.lwjgl.glfw.GLFWImage;
import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL13; import org.lwjgl.opengl.GL13;
import org.lwjgl.system.MemoryUtil; import org.lwjgl.system.MemoryUtil;
import speiger.src.coreengine.assets.AssetLocation; import speiger.src.coreengine.assets.AssetLocation;
import speiger.src.coreengine.assets.AssetManager; import speiger.src.coreengine.assets.AssetManager;
import speiger.src.coreengine.assets.base.IAsset; import speiger.src.coreengine.assets.base.IAsset;
import speiger.src.coreengine.assets.reloader.IReloadableResource; import speiger.src.coreengine.assets.reloader.IReloadableResource;
import speiger.src.coreengine.assets.reloader.ResourceReloader; import speiger.src.coreengine.assets.reloader.ResourceReloader;
import speiger.src.coreengine.rendering.utils.GLStateTracker; import speiger.src.coreengine.rendering.utils.GLStateTracker;
import speiger.src.coreengine.rendering.utils.states.GLState; import speiger.src.coreengine.rendering.utils.states.GLState;
import speiger.src.coreengine.utils.io.GameLog; import speiger.src.coreengine.utils.io.GameLog;
import speiger.src.coreengine.utils.io.GameLog.LogLevel; import speiger.src.coreengine.utils.io.GameLog.LogLevel;
public class TextureManager implements IReloadableResource public class TextureManager implements IReloadableResource
{ {
public static final TextureManager INSTANCE = new TextureManager(); public static final TextureManager INSTANCE = new TextureManager();
public static final GLState TEXTURE = GLStateTracker.instance().addState(new GLState(GL11.GL_TEXTURE_2D, false)); public static final GLState TEXTURE = GLStateTracker.instance().addState(new GLState(GL11.GL_TEXTURE_2D, false));
AssetManager manager; AssetManager manager;
ResourceReloader reloader = new ResourceReloader(); ResourceReloader reloader = new ResourceReloader();
int[] textureBanks = new int[GL13.GL_TEXTURE31 - GL13.GL_TEXTURE0]; int[] textureBanks = new int[GL13.GL_TEXTURE31 - GL13.GL_TEXTURE0];
int activeBank = 0; int activeBank = 0;
public void init(AssetManager manager) public void init(AssetManager manager)
{ {
this.manager = manager; this.manager = manager;
} }
public ResourceReloader getReloader() public ResourceReloader getReloader()
{ {
return reloader; return reloader;
} }
public void addTexture(ITexture texture) public void addTexture(ITexture texture)
{ {
if(texture != null) if(texture != null)
{ {
reloader.addReloadableResource(texture); reloader.addReloadableResource(texture);
} }
} }
public void removeTexture(ITexture texture) public void removeTexture(ITexture texture)
{ {
if(texture != null) if(texture != null)
{ {
GL11.glDeleteTextures(texture.getTextureId()); GL11.glDeleteTextures(texture.getTextureId());
reloader.removeReloadableResource(texture); reloader.removeReloadableResource(texture);
} }
} }
public void removeTexture(int id) public void removeTexture(int id)
{ {
GL11.glDeleteTextures(id); GL11.glDeleteTextures(id);
} }
public static void bindTexture(int texture) public static void bindTexture(int texture)
{ {
INSTANCE.setActiveTexture(texture); INSTANCE.setActiveTexture(texture);
} }
public static void bindTexture(int texture, int bank) public static void bindTexture(int texture, int bank)
{ {
INSTANCE.setActiveTexture(texture, bank); INSTANCE.setActiveTexture(texture, bank);
} }
public static void unbindTexture() public static void unbindTexture()
{ {
INSTANCE.setActiveTexture(0); INSTANCE.setActiveTexture(0);
} }
public void setActiveTexture(int texture) public void setActiveTexture(int texture)
{ {
if(textureBanks[activeBank] != texture) if(textureBanks[activeBank] != texture)
{ {
textureBanks[activeBank] = texture; textureBanks[activeBank] = texture;
GL11.glBindTexture(GL11.GL_TEXTURE_2D, texture); GL11.glBindTexture(GL11.GL_TEXTURE_2D, texture);
} }
} }
public void setActiveTexture(int texture, int bank) public void setActiveTexture(int texture, int bank)
{ {
if(activeBank != bank) if(activeBank != bank)
{ {
activeBank = bank; activeBank = bank;
GL13.glActiveTexture(GL13.GL_TEXTURE0 + activeBank); GL13.glActiveTexture(GL13.GL_TEXTURE0 + activeBank);
} }
bindTexture(texture); bindTexture(texture);
} }
@Override @Override
public void reload() public void reload()
{ {
reloader.reloadResources(); reloader.reloadResources();
} }
@Override @Override
public void destroy() public void destroy()
{ {
reloader.deleteResources(); reloader.deleteResources();
} }
public AssetManager getManager() public AssetManager getManager()
{ {
return manager; return manager;
} }
public static GLFWImage create(AssetLocation location) public static GLFWImage create(AssetLocation location)
{ {
try(IAsset asset = INSTANCE.manager.getAsset(location)) try(IAsset asset = INSTANCE.manager.getAsset(location))
{ {
BufferedImage image = asset.texture(); BufferedImage image = asset.texture();
int width = image.getWidth(); int width = image.getWidth();
int height = image.getHeight(); int height = image.getHeight();
int[] pixelData = new int[width * height]; int[] pixelData = new int[width * height];
image.getRGB(0, 0, width, height, pixelData, 0, width); image.getRGB(0, 0, width, height, pixelData, 0, width);
ByteBuffer buffer = MemoryUtil.memAlloc(pixelData.length * 4); ByteBuffer buffer = MemoryUtil.memAlloc(pixelData.length * 4);
for(int y = 0;y<height;y++) for(int y = 0;y<height;y++)
{ {
for(int x = 0;x<width;x++) for(int x = 0;x<width;x++)
{ {
int pixel = pixelData[(y * width) + x]; int pixel = pixelData[(y * width) + x];
buffer.put((byte)((pixel >> 16) & 0xFF)); buffer.put((byte)((pixel >> 16) & 0xFF));
buffer.put((byte)((pixel >> 8) & 0xFF)); buffer.put((byte)((pixel >> 8) & 0xFF));
buffer.put((byte)(pixel & 0xFF)); buffer.put((byte)(pixel & 0xFF));
buffer.put((byte)((pixel >> 24) & 0xFF)); buffer.put((byte)((pixel >> 24) & 0xFF));
} }
} }
GLFWImage glfw = GLFWImage.malloc(); GLFWImage glfw = GLFWImage.malloc();
glfw.set(width, height, buffer); glfw.set(width, height, buffer);
return glfw; return glfw;
} }
catch(Exception e) catch(Exception e)
{ {
GameLog.error("Couldn't Load Texture ["+location.toString()+"]", e, LogLevel.ERROR); GameLog.error("Couldn't Load Texture ["+location.toString()+"]", e, LogLevel.ERROR);
return null; return null;
} }
} }
} }

View File

@ -1,87 +1,87 @@
package speiger.src.coreengine.rendering.texturesOld.normal; package speiger.src.coreengine.rendering.texturesOld.normal;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL13; import org.lwjgl.opengl.GL13;
import org.lwjgl.opengl.GL30; import org.lwjgl.opengl.GL30;
import org.lwjgl.system.MemoryUtil; import org.lwjgl.system.MemoryUtil;
import speiger.src.coreengine.assets.AssetLocation; import speiger.src.coreengine.assets.AssetLocation;
import speiger.src.coreengine.assets.base.IAsset; import speiger.src.coreengine.assets.base.IAsset;
import speiger.src.coreengine.rendering.texturesOld.base.AbstractTexture; import speiger.src.coreengine.rendering.texturesOld.base.AbstractTexture;
import speiger.src.coreengine.rendering.texturesOld.base.TextureManager; import speiger.src.coreengine.rendering.texturesOld.base.TextureManager;
public class SimpleTexture extends AbstractTexture public class SimpleTexture extends AbstractTexture
{ {
AssetLocation location; AssetLocation location;
int width; int width;
int height; int height;
public SimpleTexture(AssetLocation location) public SimpleTexture(AssetLocation location)
{ {
super(); super();
this.location = location; this.location = location;
loadTexture(); loadTexture();
} }
public void loadTexture() public void loadTexture()
{ {
try(IAsset asset = TextureManager.INSTANCE.getManager().getAsset(location)) try(IAsset asset = TextureManager.INSTANCE.getManager().getAsset(location))
{ {
BufferedImage image = asset.texture(); BufferedImage image = asset.texture();
width = image.getWidth(); width = image.getWidth();
height = image.getHeight(); height = image.getHeight();
int[] pixelData = new int[width * height]; int[] pixelData = new int[width * height];
image.getRGB(0, 0, width, height, pixelData, 0, width); image.getRGB(0, 0, width, height, pixelData, 0, width);
ByteBuffer buffer = MemoryUtil.memAlloc(pixelData.length * 4); ByteBuffer buffer = MemoryUtil.memAlloc(pixelData.length * 4);
for(int y = 0;y<height;y++) for(int y = 0;y<height;y++)
{ {
for(int x = 0;x<width;x++) for(int x = 0;x<width;x++)
{ {
int pixel = pixelData[(y * width) + x]; int pixel = pixelData[(y * width) + x];
buffer.put((byte)((pixel >> 16) & 0xFF)); buffer.put((byte)((pixel >> 16) & 0xFF));
buffer.put((byte)((pixel >> 8) & 0xFF)); buffer.put((byte)((pixel >> 8) & 0xFF));
buffer.put((byte)(pixel & 0xFF)); buffer.put((byte)(pixel & 0xFF));
buffer.put((byte)((pixel >> 24) & 0xFF)); buffer.put((byte)((pixel >> 24) & 0xFF));
} }
} }
buffer.flip(); buffer.flip();
setTextureID(GL11.glGenTextures()); setTextureID(GL11.glGenTextures());
bindTexture(); bindTexture();
GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR); GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR); GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL13.GL_CLAMP_TO_BORDER); GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL13.GL_CLAMP_TO_BORDER);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL13.GL_CLAMP_TO_BORDER); GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL13.GL_CLAMP_TO_BORDER);
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);
GL30.glGenerateMipmap(GL11.GL_TEXTURE_2D); GL30.glGenerateMipmap(GL11.GL_TEXTURE_2D);
MemoryUtil.memFree(buffer); MemoryUtil.memFree(buffer);
} }
catch(Exception e) catch(Exception e)
{ {
e.printStackTrace(); e.printStackTrace();
} }
} }
@Override @Override
public void reload() public void reload()
{ {
int old = textureID; int old = textureID;
loadTexture(); loadTexture();
TextureManager.INSTANCE.removeTexture(old); TextureManager.INSTANCE.removeTexture(old);
} }
@Override @Override
public int getWidth() public int getWidth()
{ {
return width; return width;
} }
@Override @Override
public int getHeight() public int getHeight()
{ {
return height; return height;
} }
} }

View File

@ -1,99 +1,99 @@
package speiger.src.coreengine.rendering.texturesOld.stb; package speiger.src.coreengine.rendering.texturesOld.stb;
import java.io.IOException; import java.io.IOException;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL13; import org.lwjgl.opengl.GL13;
import org.lwjgl.opengl.GL30; import org.lwjgl.opengl.GL30;
import org.lwjgl.stb.STBImage; import org.lwjgl.stb.STBImage;
import org.lwjgl.system.MemoryUtil; import org.lwjgl.system.MemoryUtil;
import speiger.src.coreengine.assets.AssetLocation; import speiger.src.coreengine.assets.AssetLocation;
import speiger.src.coreengine.assets.base.IAsset; import speiger.src.coreengine.assets.base.IAsset;
import speiger.src.coreengine.assets.parsers.NativeMemoryParser; import speiger.src.coreengine.assets.parsers.NativeMemoryParser;
import speiger.src.coreengine.rendering.texturesOld.base.AbstractTexture; import speiger.src.coreengine.rendering.texturesOld.base.AbstractTexture;
import speiger.src.coreengine.rendering.texturesOld.base.TextureManager; import speiger.src.coreengine.rendering.texturesOld.base.TextureManager;
public class STBTexture extends AbstractTexture public class STBTexture extends AbstractTexture
{ {
AssetLocation location; AssetLocation location;
long imageData; long imageData;
int width; int width;
int height; int height;
public STBTexture(AssetLocation location) public STBTexture(AssetLocation location)
{ {
this.location = location; this.location = location;
// loadTexture(); // loadTexture();
} }
private void loadTexture() private void loadTexture()
{ {
try(IAsset asset = TextureManager.INSTANCE.getManager().getAsset(location)) try(IAsset asset = TextureManager.INSTANCE.getManager().getAsset(location))
{ {
ByteBuffer buffer = asset.custom(NativeMemoryParser.INSTANCE); ByteBuffer buffer = asset.custom(NativeMemoryParser.INSTANCE);
int[] width = new int[1]; int[] width = new int[1];
int[] height = new int[1]; int[] height = new int[1];
int[] fileChannels = new int[1]; int[] fileChannels = new int[1];
ByteBuffer image = STBImage.stbi_load_from_memory(buffer, width, height, fileChannels, 4); ByteBuffer image = STBImage.stbi_load_from_memory(buffer, width, height, fileChannels, 4);
if(image == null) { if(image == null) {
MemoryUtil.memFree(buffer); MemoryUtil.memFree(buffer);
throw new IOException("Could not load image: " + STBImage.stbi_failure_reason()); throw new IOException("Could not load image: " + STBImage.stbi_failure_reason());
} }
imageData = MemoryUtil.memAddress(image); imageData = MemoryUtil.memAddress(image);
this.width = width[0]; this.width = width[0];
this.height = height[0]; this.height = height[0];
MemoryUtil.memFree(buffer); MemoryUtil.memFree(buffer);
} }
catch(Exception e) catch(Exception e)
{ {
e.printStackTrace(); e.printStackTrace();
return; return;
} }
setTextureID(GL11.glGenTextures()); setTextureID(GL11.glGenTextures());
bindTexture(); bindTexture();
GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR); GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR); GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL13.GL_CLAMP_TO_BORDER); GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL13.GL_CLAMP_TO_BORDER);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL13.GL_CLAMP_TO_BORDER); GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL13.GL_CLAMP_TO_BORDER);
GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, width, height, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, imageData); GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, width, height, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, imageData);
GL30.glGenerateMipmap(GL11.GL_TEXTURE_2D); GL30.glGenerateMipmap(GL11.GL_TEXTURE_2D);
} }
@Override @Override
public int getWidth() public int getWidth()
{ {
return width; return width;
} }
@Override @Override
public int getHeight() public int getHeight()
{ {
return height; return height;
} }
@Override @Override
public void reload() public void reload()
{ {
if(imageData != 0) if(imageData != 0)
{ {
STBImage.nstbi_image_free(imageData); STBImage.nstbi_image_free(imageData);
imageData = 0; imageData = 0;
} }
int old = textureID; int old = textureID;
loadTexture(); loadTexture();
TextureManager.INSTANCE.removeTexture(old); TextureManager.INSTANCE.removeTexture(old);
} }
@Override @Override
public void deleteTexture() public void deleteTexture()
{ {
super.deleteTexture(); super.deleteTexture();
if(imageData != 0) if(imageData != 0)
{ {
STBImage.nstbi_image_free(imageData); STBImage.nstbi_image_free(imageData);
imageData = 0; imageData = 0;
} }
} }
} }

View File

@ -1,25 +1,25 @@
package speiger.src.coreengine.utils.functions; package speiger.src.coreengine.utils.functions;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Predicate; import java.util.function.Predicate;
public class Functions public class Functions
{ {
static final Predicate<Object> ALWAYS_TRUE = (T) -> true; static final Predicate<Object> ALWAYS_TRUE = _ -> true;
static final Consumer<Object> EMPTY_CONSUMER = (T) -> {}; static final Consumer<Object> EMPTY_CONSUMER = _ -> {};
public static final Predicate<String> NUMBERS_ONLY = T -> { public static final Predicate<String> NUMBERS_ONLY = T -> {
if(T.isEmpty() || T.equals("#") || T.equals("0x")) return true; if(T.isEmpty() || T.equals("#") || T.equals("0x")) return true;
try { return Long.decode(T) != null; } try { return Long.decode(T) != null; }
catch(Exception e){ return false; } catch(Exception e){ return false; }
}; };
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static <T> Predicate<T> getAlwaysTrue() { public static <T> Predicate<T> getAlwaysTrue() {
return (Predicate<T>)ALWAYS_TRUE; return (Predicate<T>)ALWAYS_TRUE;
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static <T> Consumer<T> getVoidConsumer() { public static <T> Consumer<T> getVoidConsumer() {
return (Consumer<T>)EMPTY_CONSUMER; return (Consumer<T>)EMPTY_CONSUMER;
} }
} }

View File

@ -1,28 +1,28 @@
package speiger.src.coreengine.utils.io.dataTag.compression; package speiger.src.coreengine.utils.io.dataTag.compression;
import java.io.IOException; import java.io.IOException;
public interface DataTagLimiter { public interface DataTagLimiter {
public static final DataTagLimiter INFINTE = T -> {}; public static final DataTagLimiter INFINTE = _ -> {};
public static DataTagLimiter limit(int byteLimit) { public static DataTagLimiter limit(int byteLimit) {
return new Instance(byteLimit); return new Instance(byteLimit);
} }
public void countBytes(int amount) throws IOException; public void countBytes(int amount) throws IOException;
public static class Instance implements DataTagLimiter { public static class Instance implements DataTagLimiter {
final int max; final int max;
int read = 0; int read = 0;
public Instance(int max) { public Instance(int max) {
this.max = max; this.max = max;
} }
@Override @Override
public void countBytes(int amount) throws IOException { public void countBytes(int amount) throws IOException {
read += amount; read += amount;
if(read > amount) throw new IllegalStateException("To many Bytes Read"); if(read > amount) throw new IllegalStateException("To many Bytes Read");
} }
} }
} }

View File

@ -1,146 +1,146 @@
package speiger.src.coreengine.math; package speiger.src.coreengine.math;
public class MathUtils { public class MathUtils {
private static final float[] SIN_TABLE; private static final float[] SIN_TABLE;
private static final float[] COS_TABLE; private static final float[] COS_TABLE;
private static final float TABLE_MASK; private static final float TABLE_MASK;
private static final int SIN_MASK; private static final int SIN_MASK;
public static final double HALF_PI = Math.PI * 0.5D; public static final double HALF_PI = Math.PI * 0.5D;
public static final double PI_INVERSION = 180D / Math.PI; public static final double PI_INVERSION = 180D / Math.PI;
public static float sin(float a) { public static float sin(float a) {
return SIN_TABLE[(int)(a * TABLE_MASK) & SIN_MASK]; return SIN_TABLE[(int)(a * TABLE_MASK) & SIN_MASK];
} }
public static float sin(double a) { public static float sin(double a) {
return SIN_TABLE[(int)(a * TABLE_MASK) & SIN_MASK]; return SIN_TABLE[(int)(a * TABLE_MASK) & SIN_MASK];
} }
public static float cos(float a) { public static float cos(float a) {
return COS_TABLE[(int)(a * TABLE_MASK) & SIN_MASK]; return COS_TABLE[(int)(a * TABLE_MASK) & SIN_MASK];
} }
public static float cos(double a) { public static float cos(double a) {
return COS_TABLE[(int)(a * TABLE_MASK) & SIN_MASK]; return COS_TABLE[(int)(a * TABLE_MASK) & SIN_MASK];
} }
public static byte clamp(byte min, byte max, byte current) { public static byte clamp(byte min, byte max, byte current) {
return current < min ? min : (current > max ? max : current); return current < min ? min : (current > max ? max : current);
} }
public static short clamp(short min, short max, short current) { public static short clamp(short min, short max, short current) {
return current < min ? min : (current > max ? max : current); return current < min ? min : (current > max ? max : current);
} }
public static int clamp(int min, int max, int current) { public static int clamp(int min, int max, int current) {
return current < min ? min : (current > max ? max : current); return current < min ? min : (current > max ? max : current);
} }
public static float clamp(float min, float max, float current) { public static float clamp(float min, float max, float current) {
return current < min ? min : (current > max ? max : current); return current < min ? min : (current > max ? max : current);
} }
public static double clamp(double min, double max, double current) { public static double clamp(double min, double max, double current) {
return current < min ? min : (current > max ? max : current); return current < min ? min : (current > max ? max : current);
} }
public static long clamp(long min, long max, long current) { public static long clamp(long min, long max, long current) {
return current < min ? min : (current > max ? max : current); return current < min ? min : (current > max ? max : current);
} }
public static byte sign(byte value) { public static byte sign(byte value) {
return (byte)Integer.signum(value); return (byte)Integer.signum(value);
} }
public static short sign(short value) { public static short sign(short value) {
return (short)Integer.signum(value); return (short)Integer.signum(value);
} }
public static int sign(int value) { public static int sign(int value) {
return Integer.signum(value); return Integer.signum(value);
} }
public static long sign(long value) { public static long sign(long value) {
return Long.signum(value); return Long.signum(value);
} }
public static float sign(float value) { public static float sign(float value) {
return Math.signum(value); return Math.signum(value);
} }
public static double sign(double value) { public static double sign(double value) {
return Math.signum(value); return Math.signum(value);
} }
public static int sub(int key, int value) { public static int sub(int key, int value) {
return key - value; return key - value;
} }
public static int ceil(double value) { public static int ceil(double value) {
int i = (int)value; int i = (int)value;
return value > i ? i + 1 : i; return value > i ? i + 1 : i;
} }
public static int ceil(float value) { public static int ceil(float value) {
int i = (int)value; int i = (int)value;
return value > i ? i + 1 : i; return value > i ? i + 1 : i;
} }
public static int floor(float value) { public static int floor(float value) {
int i = (int)value; int i = (int)value;
return value < i ? i - 1 : i; return value < i ? i - 1 : i;
} }
public static int floor(double value) { public static int floor(double value) {
int i = (int)value; int i = (int)value;
return value < i ? i - 1 : i; return value < i ? i - 1 : i;
} }
public static int pow(int base, int exp) { public static int pow(int base, int exp) {
return (int)Math.pow(base, exp); return (int)Math.pow(base, exp);
} }
public static float lerp(float start, float end, float progress) { public static float lerp(float start, float end, float progress) {
return start + ((end - start) * progress); return start + ((end - start) * progress);
} }
public static double lerp(double start, double end, float progress) { public static double lerp(double start, double end, float progress) {
return start + ((end - start) * progress); return start + ((end - start) * progress);
} }
public static float smoothLerp(float start, float end, float progress) { public static float smoothLerp(float start, float end, float progress) {
float cosProgress = (1F - MathUtils.cos(progress * Math.PI)) * 0.5F; float cosProgress = (1F - MathUtils.cos(progress * Math.PI)) * 0.5F;
return start * (1F - cosProgress) + end * cosProgress; return start * (1F - cosProgress) + end * cosProgress;
} }
public static float quadraticCurve(float start, float median, float end, float progress) { public static float quadraticCurve(float start, float median, float end, float progress) {
return lerp(lerp(start, median, progress), lerp(median, end, progress), progress); return lerp(lerp(start, median, progress), lerp(median, end, progress), progress);
} }
public static float smoothQuadraticCurve(float start, float median, float end, float progress) { public static float smoothQuadraticCurve(float start, float median, float end, float progress) {
return smoothLerp(smoothLerp(start, median, progress), smoothLerp(median, end, progress), progress); return smoothLerp(smoothLerp(start, median, progress), smoothLerp(median, end, progress), progress);
} }
static { static {
SIN_MASK = ~(-1 << 12); SIN_MASK = ~(-1 << 12);
int SIN_COUNT = SIN_MASK + 1; int SIN_COUNT = SIN_MASK + 1;
float radFull = (float)(Math.PI * 2D); float radFull = (float)(Math.PI * 2D);
float degFull = (float)(360.0); float degFull = (float)(360.0);
float radToIndex = SIN_COUNT / radFull; float radToIndex = SIN_COUNT / radFull;
float degToIndex = SIN_COUNT / degFull; float degToIndex = SIN_COUNT / degFull;
TABLE_MASK = radToIndex; TABLE_MASK = radToIndex;
SIN_TABLE = new float[SIN_COUNT]; SIN_TABLE = new float[SIN_COUNT];
COS_TABLE = new float[SIN_COUNT]; COS_TABLE = new float[SIN_COUNT];
for(int i = 0;i < SIN_COUNT;i++) { for(int i = 0;i < SIN_COUNT;i++) {
SIN_TABLE[i] = (float)Math.sin((i + 0.5f) / SIN_COUNT * radFull); SIN_TABLE[i] = (float)Math.sin((i + 0.5f) / SIN_COUNT * radFull);
COS_TABLE[i] = (float)Math.cos((i + 0.5f) / SIN_COUNT * radFull); COS_TABLE[i] = (float)Math.cos((i + 0.5f) / SIN_COUNT * radFull);
} }
for(int i = 0;i < 360;i += 90) { for(int i = 0;i < 360;i += 90) {
SIN_TABLE[(int)(i * degToIndex) & SIN_MASK] = (float)Math.sin(i * Math.PI / 180D); SIN_TABLE[(int)(i * degToIndex) & SIN_MASK] = (float)Math.sin(i * Math.PI / 180D);
COS_TABLE[(int)(i * degToIndex) & SIN_MASK] = (float)Math.cos(i * Math.PI / 180D); COS_TABLE[(int)(i * degToIndex) & SIN_MASK] = (float)Math.cos(i * Math.PI / 180D);
} }
} }
} }

View File

@ -0,0 +1,23 @@
package speiger.src.coreengine.math.vector.bytes;
public record Vec2bImmutable(byte x, byte y) implements Vec2b {
public Vec2bImmutable() {
this((byte)0, (byte)0);
}
public Vec2bImmutable(byte value) {
this(value, value);
}
@Override
public boolean isMutable() { return false; }
@Override
public Vec2b x(byte x) { return this.x == x ? this : Vec2b.of(x, y); }
@Override
public Vec2b y(byte y) { return this.y == y ? this : Vec2b.of(x, y); }
@Override
public Vec2b copy() { return Vec2b.of(this); }
@Override
public Vec2b set(byte x, byte y) { return this.x == x && this.y == y ? this : Vec2b.of(x, y); }
}

View File

@ -0,0 +1,25 @@
package speiger.src.coreengine.math.vector.bytes;
public record Vec3bImmutable(byte x, byte y, byte z) implements Vec3b {
public Vec3bImmutable() {
this((byte)0, (byte)0, (byte)0);
}
public Vec3bImmutable(byte value) {
this(value, value, value);
}
@Override
public boolean isMutable() { return false; }
@Override
public Vec3b x(byte x) { return this.x == x ? this : Vec3b.of(x, y, z); }
@Override
public Vec3b y(byte y) { return this.y == y ? this : Vec3b.of(x, y, z); }
@Override
public Vec3b z(byte z) { return this.z == z ? this : Vec3b.of(x, y, z); }
@Override
public Vec3b copy() { return Vec3b.of(this); }
@Override
public Vec3b set(byte x, byte y, byte z) { return this.x == x && this.y == y && this.z == z ? this : Vec3b.of(x, y, z); }
}

View File

@ -0,0 +1,27 @@
package speiger.src.coreengine.math.vector.bytes;
public record Vec4bImmutable(byte x, byte y, byte z, byte w) implements Vec4b {
public Vec4bImmutable() {
this((byte)0, (byte)0, (byte)0, (byte)0);
}
public Vec4bImmutable(byte value) {
this(value, value, value, value);
}
@Override
public boolean isMutable() { return false; }
@Override
public Vec4b x(byte x) { return this.x == x ? this : Vec4b.of(x, y, z, w); }
@Override
public Vec4b y(byte y) { return this.y == y ? this : Vec4b.of(x, y, z, w); }
@Override
public Vec4b z(byte z) { return this.z == z ? this : Vec4b.of(x, y, z, w); }
@Override
public Vec4b w(byte w) { return this.w == w ? this : Vec4b.of(x, y, z, w); }
@Override
public Vec4b copy() { return Vec4b.of(this); }
@Override
public Vec4b set(byte x, byte y, byte z, byte w) { return this.x == x && this.y == y && this.z == z && this.w == w ? this : Vec4b.of(x, y, z, w); }
}

Some files were not shown because too many files have changed in this diff Show More