Coord and rect views and freezing; Fixed font glitches.

This commit is contained in:
Ondřej Hruška
2014-04-10 22:53:25 +02:00
parent ebac276ed2
commit e940c53dd6
41 changed files with 1574 additions and 896 deletions
@@ -3,7 +3,7 @@ package mightypork.gamecore.audio;
import java.io.IOException;
import mightypork.gamecore.loading.BaseDeferredResource;
import mightypork.gamecore.loading.DeferredResource;
import mightypork.utils.files.FileUtils;
import mightypork.utils.logging.LoggedName;
import mightypork.utils.math.coord.Coord;
@@ -18,7 +18,7 @@ import org.newdawn.slick.openal.SoundStore;
* @author MightyPork
*/
@LoggedName(name = "Audio")
public class DeferredAudio extends BaseDeferredResource {
public class DeferredAudio extends DeferredResource {
private enum PlayMode
{
@@ -168,7 +168,7 @@ public class DeferredAudio extends BaseDeferredResource {
*/
public int playAsEffect(double pitch, double gain, boolean loop, double x, double y)
{
return playAsEffect(pitch, gain, loop, x, y, SoundSystem.getListener().z);
return playAsEffect(pitch, gain, loop, x, y, SoundSystem.getListener().z());
}
@@ -208,7 +208,7 @@ public class DeferredAudio extends BaseDeferredResource {
{
if (!ensureLoaded()) return -1;
return playAsEffect(pitch, gain, loop, pos.x, pos.y, pos.z);
return playAsEffect(pitch, gain, loop, pos.x(), pos.y(), pos.z());
}
@@ -26,7 +26,7 @@ import org.newdawn.slick.openal.SoundStore;
*/
public class SoundSystem extends RootBusNode implements Updateable {
private static final Coord INITIAL_LISTENER_POS = new Coord(0, 0, 0);
private static final Coord INITIAL_LISTENER_POS = Coord.ZERO;
private static final int MAX_SOURCES = 256;
private static Coord listener = new Coord();
@@ -45,7 +45,7 @@ public class SoundSystem extends RootBusNode implements Updateable {
FloatBuffer buf3 = Buffers.alloc(3);
FloatBuffer buf6 = Buffers.alloc(6);
buf3.clear();
Buffers.fill(buf3, (float) pos.x, (float) pos.y, (float) pos.z);
Buffers.fill(buf3, pos.xf(), pos.yf(), pos.zf());
AL10.alListener(AL10.AL_POSITION, buf3);
buf3.clear();
Buffers.fill(buf3, 0, 0, 0);
@@ -64,7 +64,9 @@ public abstract class GameLoop extends AppModule implements MainLoopTaskRequest.
beforeRender();
if (rootRenderable != null) rootRenderable.render();
if (rootRenderable != null) {
rootRenderable.render();
}
afterRender();
@@ -2,7 +2,7 @@ package mightypork.gamecore.control.bus.events;
import mightypork.gamecore.control.bus.events.types.SingleReceiverEvent;
import mightypork.gamecore.loading.DeferredResource;
import mightypork.gamecore.loading.Deferred;
/**
@@ -13,13 +13,13 @@ import mightypork.gamecore.loading.DeferredResource;
@SingleReceiverEvent
public class ResourceLoadRequest implements Event<ResourceLoadRequest.Listener> {
private final DeferredResource resource;
private final Deferred resource;
/**
* @param resource resource to load
*/
public ResourceLoadRequest(DeferredResource resource) {
public ResourceLoadRequest(Deferred resource) {
this.resource = resource;
}
@@ -42,6 +42,6 @@ public class ResourceLoadRequest implements Event<ResourceLoadRequest.Listener>
*
* @param resource
*/
void loadResource(DeferredResource resource);
void loadResource(Deferred resource);
}
}
@@ -6,12 +6,16 @@ import mightypork.gamecore.render.fonts.FontRenderer;
import mightypork.gamecore.render.fonts.FontRenderer.Align;
import mightypork.gamecore.render.fonts.GLFont;
import mightypork.utils.math.color.RGB;
import mightypork.utils.math.coord.Coord;
import mightypork.utils.math.coord.Rect;
import mightypork.utils.string.StringProvider;
import mightypork.utils.string.StringProvider.StringWrapper;
/**
* Text painting component
* Text painting component.<br>
* Drawing values are obtained through getters, so overriding getters can be
* used to change parameters dynamically.
*
* @author MightyPork
*/
@@ -21,6 +25,10 @@ public class TextPainter extends PluggableRenderer {
private RGB color;
private Align align;
private StringProvider text;
private boolean shadow;
private RGB shadowColor = RGB.BLACK;
private Coord shadowOffset = Coord.one();
/**
@@ -70,110 +78,68 @@ public class TextPainter extends PluggableRenderer {
}
/**
* Use size specified during font init instead of size provided by
* {@link GLFont} instance (measured from tile heights.<br>
* This is better when the font is drawn in original size, but can cause
* weird artifacts if the font is scaled up.
*
* @param enable use it
*/
public void usePtSize(boolean enable)
{
font.usePtSize(enable);
}
@Override
public void render()
{
if (getText() == null) return;
if (text == null) return;
font.draw(getText(), getRect(), getAlign(), getColor());
final String str = text.getString();
final Rect rect = getRect();
if (shadow) {
font.draw(str, rect.add(shadowOffset), align, shadowColor);
}
font.draw(str, rect, align, color);
}
public void setShadow(RGB color, Coord offset)
{
setShadow(true);
setShadowColor(color);
setShadowOffset(offset);
}
public void setShadow(boolean shadow)
{
this.shadow = shadow;
}
public void setShadowColor(RGB shadowColor)
{
this.shadowColor = shadowColor;
}
public void setShadowOffset(Coord shadowOffset)
{
this.shadowOffset = shadowOffset;
}
/**
* Assign paint color
*
* @param color paint color
*/
public void setColor(RGB color)
{
this.color = color;
}
/**
* Set text align
*
* @param align text align
*/
public void setAlign(Align align)
{
this.align = align;
}
/**
* Set drawn text
*
* @param text text
*/
public void setText(String text)
{
this.text = new StringWrapper(text);
}
/**
* Set drawn text provider
*
* @param text text provider
*/
public void setText(StringProvider text)
{
this.text = text;
}
/**
* Get draw color.<br>
* <i>This getter is used for getting drawing color; so if it's overriden,
* the draw color can be adjusted in real time.</i>
*
* @return drawing color
*/
public RGB getColor()
{
return color;
}
/**
* Get text align.<br>
* <i>This getter is used for getting align; so if it's overidden, the align
* can be adjusted in real time.</i>
*
* @return text align
*/
public Align getAlign()
{
return align;
}
/**
* Get text to draw.<br>
* <i>This getter is used for getting text to draw; so if it's overidden,
* the text can be adjusted in real time. (alternative to using
* StringProvider)</i>
*
* @return text align
*/
public String getText()
{
return text.getString();
}
}
@@ -23,7 +23,7 @@ public class Constraints {
@Override
public double getValue()
{
return InputSystem.getMousePos().x;
return InputSystem.getMousePos().x();
}
};
@@ -32,7 +32,7 @@ public class Constraints {
@Override
public double getValue()
{
return InputSystem.getMousePos().y;
return InputSystem.getMousePos().y();
}
};
@@ -246,7 +246,7 @@ public class Constraints {
@Override
public double getValue()
{
return r.getRect().getSize().x;
return r.getRect().getSize().x();
}
};
}
@@ -259,7 +259,7 @@ public class Constraints {
@Override
public double getValue()
{
return r.getRect().getSize().y;
return r.getRect().getSize().y();
}
};
}
@@ -274,7 +274,7 @@ public class Constraints {
@Override
public Rect getRect()
{
final double height = r.getRect().getSize().y;
final double height = r.getRect().getSize().y();
final double perRow = height / rows;
final Coord origin = r.getRect().getOrigin().add(0, perRow * index);
@@ -293,7 +293,7 @@ public class Constraints {
@Override
public Rect getRect()
{
final double width = r.getRect().getSize().x;
final double width = r.getRect().getSize().x();
final double perCol = width / columns;
final Coord origin = r.getRect().getOrigin().add(perCol * index, 0);
@@ -312,8 +312,8 @@ public class Constraints {
@Override
public Rect getRect()
{
final double height = r.getRect().getSize().y;
final double width = r.getRect().getSize().y;
final double height = r.getRect().getSize().y();
final double width = r.getRect().getSize().y();
final double perRow = height / rows;
final double perCol = width / cols;
@@ -522,8 +522,8 @@ public class Constraints {
//@formatter:off
return Rect.fromSize(
origin.x,
origin.y,
origin.x(),
origin.y(),
_nv(width),
_nv(height)
);
@@ -544,8 +544,8 @@ public class Constraints {
//@formatter:off
return Rect.fromSize(
origin.x + _nv(x),
origin.y + _nv(y),
origin.x() + _nv(x),
origin.y() + _nv(y),
_nv(width),
_nv(height)
);
@@ -582,7 +582,7 @@ public class Constraints {
final Coord size = r.getRect().getSize();
final Coord center = centerTo.getRect().getCenter();
return Rect.fromSize(center.x - size.x / 2D, center.y - size.y / 2D, size.x, size.y);
return Rect.fromSize(center.x() - size.x() / 2D, center.y() - size.y() / 2D, size.x(), size.y());
}
};
}
@@ -605,7 +605,7 @@ public class Constraints {
{
final Coord size = r.getRect().getSize();
return Rect.fromSize(_nv(x) - size.x / 2D, _nv(y) - size.y / 2D, size.x, size.y);
return Rect.fromSize(_nv(x) - size.x() / 2D, _nv(y) - size.y() / 2D, size.x(), size.y());
}
};
}
@@ -5,7 +5,6 @@ import java.util.Collection;
import java.util.TreeSet;
import mightypork.gamecore.control.AppAccess;
import mightypork.gamecore.render.Render;
import mightypork.utils.math.coord.Coord;
@@ -31,9 +30,7 @@ public abstract class LayeredScreen extends Screen {
protected void renderScreen()
{
for (final ScreenLayer layer : layers) {
Render.pushState();
layer.render();
Render.popState();
}
}
@@ -129,10 +129,10 @@ public class InputSystem extends RootBusNode implements Updateable, KeyBinder {
}
if (button != -1 || wheeld != 0) {
getEventBus().send(new MouseButtonEvent(pos, button, down, wheeld));
getEventBus().send(new MouseButtonEvent(pos.freeze(), button, down, wheeld));
}
moveSum.add_ip(move);
moveSum.add_ip(move.freeze());
lastPos.setTo(pos);
}
@@ -149,7 +149,7 @@ public class InputSystem extends RootBusNode implements Updateable, KeyBinder {
private static void flipScrY(Coord c)
{
if (DisplaySystem.yAxisDown) c.setY_ip(DisplaySystem.getSize().y - c.y);
if (DisplaySystem.yAxisDown) c.setY_ip(DisplaySystem.getSize().y() - c.y());
}
@@ -162,7 +162,7 @@ public class InputSystem extends RootBusNode implements Updateable, KeyBinder {
{
final Coord pos = new Coord(Mouse.getX(), Mouse.getY());
flipScrY(pos);
return pos;
return pos.freeze();
}
@@ -6,7 +6,6 @@ import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import mightypork.gamecore.control.bus.BusAccess;
import mightypork.gamecore.control.bus.events.MainLoopTaskRequest;
import mightypork.gamecore.control.bus.events.ResourceLoadRequest;
import mightypork.gamecore.control.interf.Destroyable;
import mightypork.utils.logging.Log;
@@ -33,8 +32,9 @@ public class AsyncResourceLoader extends Thread implements ResourceLoadRequest.L
private final ExecutorService exs = Executors.newCachedThreadPool();
private final LinkedBlockingQueue<DeferredResource> toLoad = new LinkedBlockingQueue<>();
private final LinkedBlockingQueue<Deferred> toLoad = new LinkedBlockingQueue<>();
private volatile boolean stopped;
@SuppressWarnings("unused")
private final BusAccess app;
@@ -49,7 +49,7 @@ public class AsyncResourceLoader extends Thread implements ResourceLoadRequest.L
@Override
public void loadResource(final DeferredResource resource)
public void loadResource(final Deferred resource)
{
if (resource.isLoaded()) return;
if (resource instanceof NullResource) return;
@@ -57,7 +57,7 @@ public class AsyncResourceLoader extends Thread implements ResourceLoadRequest.L
// textures & fonts needs to be loaded in main thread
if (resource.getClass().isAnnotationPresent(MustLoadInMainThread.class)) {
// just ignore
Log.f3("<LOADER> Cannot load async: " + Log.str(resource));
// Log.f3("<LOADER> Delegating to main thread:\n " + Log.str(resource));
//
@@ -85,12 +85,12 @@ public class AsyncResourceLoader extends Thread implements ResourceLoadRequest.L
while (!stopped) {
try {
final DeferredResource def = toLoad.take();
final Deferred def = toLoad.take();
if (def == null) continue;
if (!def.isLoaded()) {
Log.f3("<LOADER> Loading async:\n " + Log.str(def));
Log.f3("<LOADER> Loading: " + Log.str(def));
exs.submit(new Runnable() {
@@ -1,144 +0,0 @@
package mightypork.gamecore.loading;
import mightypork.gamecore.control.interf.Destroyable;
import mightypork.utils.logging.Log;
import mightypork.utils.logging.LoggedName;
/**
* Deferred resource abstraction.<br>
* Resources implementing {@link NullResource} will be treated as fake and not
* attempted to load.
*
* @author MightyPork
*/
@LoggedName(name = "Resource")
public abstract class BaseDeferredResource implements DeferredResource, Destroyable {
private final String resource;
private volatile boolean loadFailed = false;
private volatile boolean loadAttempted = false;
/**
* @param resource resource path / name; this string is later used in
* loadResource()
*/
public BaseDeferredResource(String resource) {
this.resource = resource;
}
@Override
public synchronized final void load()
{
if(loadFailed) return;
if (loadAttempted) {
Log.w("<RES> Already loaded @ load():\n " + this);
(new IllegalStateException()).printStackTrace();
return;
}
loadAttempted = true;
loadFailed = false;
if (isNull()) return;
try {
if (resource == null) {
throw new NullPointerException("Resource string cannot be null for non-null resource.");
}
Log.f3("<RES> Loading:\n " + this);
loadResource(resource);
Log.f3("<RES> Loaded:\n " + this);
} catch (final Exception e) {
loadFailed = true;
Log.e("<RES> Failed to load:\n " + this, e);
}
}
@Override
public synchronized final boolean isLoaded()
{
if (isNull()) return false;
return loadAttempted && !loadFailed;
}
/**
* Check if the resource is loaded; if not, try to do so.
*
* @return true if it's loaded now.
*/
public synchronized final boolean ensureLoaded()
{
if (isNull()) return false;
if (isLoaded()) {
return true;
} else {
if(loadFailed) return false;
Log.f3("<RES> (!) First use, not loaded yet - loading directly\n " + this);
load();
}
return isLoaded();
}
/**
* Load the resource. Called from load() - once only.
*
* @param resource the path / name of a resource
* @throws Exception when some problem prevented the resource from being
* loaded.
*/
protected abstract void loadResource(String resource) throws Exception;
@Override
public abstract void destroy();
@Override
public String toString()
{
return Log.str(getClass()) + "(\"" + resource + "\")";
}
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + ((resource == null) ? 0 : resource.hashCode());
return result;
}
@Override
public boolean equals(Object obj)
{
if (this == obj) return true;
if (obj == null) return false;
if (!(obj instanceof BaseDeferredResource)) return false;
final BaseDeferredResource other = (BaseDeferredResource) obj;
if (resource == null) {
if (other.resource != null) return false;
} else if (!resource.equals(other.resource)) return false;
return true;
}
private boolean isNull()
{
return this instanceof NullResource;
}
}
@@ -0,0 +1,23 @@
package mightypork.gamecore.loading;
/**
* Deferred resource
*
* @author MightyPork
*/
public interface Deferred {
/**
* Load the actual resource, if not loaded yet.
*/
void load();
/**
* Check if resource was successfully loaded.
*
* @return true if already loaded
*/
boolean isLoaded();
}
@@ -1,23 +1,140 @@
package mightypork.gamecore.loading;
import mightypork.gamecore.control.interf.Destroyable;
import mightypork.utils.logging.Log;
import mightypork.utils.logging.LoggedName;
/**
* Deferred resource
* Deferred resource abstraction.<br>
* Resources implementing {@link NullResource} will be treated as fake and not
* attempted to load.
*
* @author MightyPork
*/
public interface DeferredResource {
@LoggedName(name = "Resource")
public abstract class DeferredResource implements Deferred, Destroyable {
private final String resource;
private volatile boolean loadFailed = false;
private volatile boolean loadAttempted = false;
/**
* Load the actual resource, if not loaded yet.
* @param resource resource path / name; this string is later used in
* loadResource()
*/
void load();
public DeferredResource(String resource) {
this.resource = resource;
}
@Override
public synchronized final void load()
{
if (loadFailed) return;
if (loadAttempted) return;
loadAttempted = true;
loadFailed = false;
if (isNull()) return;
try {
if (resource == null) {
throw new NullPointerException("Resource string cannot be null for non-null resource.");
}
Log.f3("<RES> Loading: " + this);
loadResource(resource);
Log.f3("<RES> Loaded: " + this);
} catch (final Exception e) {
loadFailed = true;
Log.e("<RES> Failed to load: " + this, e);
}
}
@Override
public synchronized final boolean isLoaded()
{
if (isNull()) return false;
return loadAttempted && !loadFailed;
}
/**
* Check if resource was successfully loaded.
* Check if the resource is loaded; if not, try to do so.
*
* @return true if already loaded
* @return true if it's loaded now.
*/
boolean isLoaded();
public synchronized final boolean ensureLoaded()
{
if (isNull()) return false;
if (isLoaded()) {
return true;
} else {
if (loadFailed) return false;
Log.f3("<RES> (!) Loading on access: " + this);
load();
}
return isLoaded();
}
/**
* Load the resource. Called from load() - once only.
*
* @param resource the path / name of a resource
* @throws Exception when some problem prevented the resource from being
* loaded.
*/
protected abstract void loadResource(String resource) throws Exception;
@Override
public abstract void destroy();
@Override
public String toString()
{
return Log.str(getClass()) + "(\"" + resource + "\")";
}
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + ((resource == null) ? 0 : resource.hashCode());
return result;
}
@Override
public boolean equals(Object obj)
{
if (this == obj) return true;
if (obj == null) return false;
if (!(obj instanceof DeferredResource)) return false;
final DeferredResource other = (DeferredResource) obj;
if (resource == null) {
if (other.resource != null) return false;
} else if (!resource.equals(other.resource)) return false;
return true;
}
private boolean isNull()
{
return this instanceof NullResource;
}
}
@@ -12,6 +12,7 @@ import mightypork.gamecore.control.timing.FpsMeter;
import mightypork.gamecore.gui.constraints.NumberConstraint;
import mightypork.gamecore.gui.constraints.RectConstraint;
import mightypork.utils.logging.Log;
import mightypork.utils.math.coord.ConstraintCoordView;
import mightypork.utils.math.coord.Coord;
import mightypork.utils.math.coord.Rect;
@@ -176,7 +177,7 @@ public class DisplaySystem extends AppModule implements RectConstraint {
*/
public static Coord getSize()
{
return new Coord(getWidth(), getHeight());
return size;
}
@@ -227,7 +228,7 @@ public class DisplaySystem extends AppModule implements RectConstraint {
@Override
public Rect getRect()
{
return new Rect(getSize());
return new Rect(Coord.ZERO, getSize());
}
@@ -240,7 +241,7 @@ public class DisplaySystem extends AppModule implements RectConstraint {
}
/** Screen width constraint */
public final NumberConstraint width = new NumberConstraint() {
public static final NumberConstraint width = new NumberConstraint() {
@Override
public double getValue()
@@ -250,7 +251,7 @@ public class DisplaySystem extends AppModule implements RectConstraint {
};
/** Screen height constaint */
public final NumberConstraint height = new NumberConstraint() {
public static final NumberConstraint height = new NumberConstraint() {
@Override
public double getValue()
@@ -258,4 +259,6 @@ public class DisplaySystem extends AppModule implements RectConstraint {
return getHeight();
}
};
public static final ConstraintCoordView size = new ConstraintCoordView(width, height, null);
}
+82 -40
View File
@@ -26,9 +26,9 @@ import org.newdawn.slick.util.ResourceLoader;
*/
public class Render {
private static final Coord AXIS_X = new Coord(1, 0, 0);
private static final Coord AXIS_Y = new Coord(0, 1, 0);
private static final Coord AXIS_Z = new Coord(0, 0, 1);
public static final Coord AXIS_X = new Coord(1, 0, 0).freeze();
public static final Coord AXIS_Y = new Coord(0, 1, 0).freeze();
public static final Coord AXIS_Z = new Coord(0, 0, 1).freeze();
/**
@@ -54,6 +54,31 @@ public class Render {
}
/**
* Translate
*
* @param x
* @param y
*/
public static void translate(double x, double y)
{
glTranslated(x, y, 0);
}
/**
* Translate
*
* @param x
* @param y
* @param z
*/
public static void translate(double x, double y, double z)
{
glTranslated(x, y, z);
}
/**
* Translate with coord
*
@@ -61,7 +86,32 @@ public class Render {
*/
public static void translate(Coord coord)
{
glTranslated(coord.x, coord.y, coord.z);
glTranslated(coord.x(), coord.y(), coord.z());
}
/**
* Scale
*
* @param x
* @param y
*/
public static void scale(double x, double y)
{
glScaled(x, y, 0);
}
/**
* Scale
*
* @param x
* @param y
* @param z
*/
public static void scale(double x, double y, double z)
{
glScaled(x, y, z);
}
@@ -72,7 +122,7 @@ public class Render {
*/
public static void scale(Coord factor)
{
glScaled(factor.x, factor.y, factor.z);
glScaled(factor.x(), factor.y(), factor.z());
}
@@ -162,7 +212,7 @@ public class Render {
public static void rotate(double angle, Coord axis)
{
final Coord vec = axis.norm(1);
glRotated(angle, vec.x, vec.y, vec.z);
glRotated(angle, vec.x(), vec.y(), vec.z());
}
private static int pushed = 0;
@@ -179,8 +229,6 @@ public class Render {
Log.w("Suspicious number of state pushes: " + pushed);
}
// Log.f3("push : "+pushed);
GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS);
GL11.glPushClientAttrib(GL11.GL_ALL_CLIENT_ATTRIB_BITS);
GL11.glMatrixMode(GL11.GL_MODELVIEW);
@@ -188,10 +236,6 @@ public class Render {
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glPushMatrix();
GL11.glMatrixMode(GL11.GL_MODELVIEW);
// GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS);
// GL11.glPushClientAttrib(GL11.GL_ALL_CLIENT_ATTRIB_BITS);
// GL11.glPushMatrix();
}
@@ -206,18 +250,30 @@ public class Render {
pushed--;
// Log.f3("pop : "+pushed);
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glPopMatrix();
GL11.glMatrixMode(GL11.GL_MODELVIEW);
GL11.glPopMatrix();
GL11.glPopClientAttrib();
GL11.glPopAttrib();
// GL11.glPopMatrix();
// GL11.glPopClientAttrib();
// GL11.glPopAttrib();
}
/**
* Store matrix
*/
public static void pushMatrix()
{
GL11.glPushMatrix();
}
/**
* Restore Gl state
*/
public static void popMatrix()
{
GL11.glPopMatrix();
}
@@ -254,24 +310,11 @@ public class Render {
* Bind texture
*
* @param texture the texture
* @param linear use linear interpolation for scaling
* @throws RuntimeException if not loaded yet
*/
private static void bindTexture(Texture texture, boolean linear) throws RuntimeException
{
texture.bind();
}
/**
* Bind texture with linear interpolation
*
* @param texture the texture
* @throws RuntimeException if not loaded yet
*/
private static void bindTexture(Texture texture) throws RuntimeException
{
bindTexture(texture, false);
texture.bind();
}
@@ -280,9 +323,9 @@ public class Render {
*/
private static void unbindTexture()
{
if (TextureImpl.getLastBind() != null) {
TextureImpl.bindNone();
}
//if (TextureImpl.getLastBind() != null) {
TextureImpl.bindNone();
//}
}
@@ -437,11 +480,10 @@ public class Render {
*/
public static void quadTextured(Rect quad, Rect uvs, Texture texture, RGB tint)
{
pushState();
bindTexture(texture);
setColor(tint);
quadUV(quad, uvs);
popState();
unbindTexture();
}
@@ -466,7 +508,7 @@ public class Render {
*/
public static void quadTextured(Rect quad, Texture texture)
{
quadTextured(quad, Rect.one(), texture, RGB.WHITE);
quadTextured(quad, Rect.ONE, texture, RGB.WHITE);
}
@@ -505,7 +547,7 @@ public class Render {
glLoadIdentity();
final Coord s = DisplaySystem.getSize();
glViewport(0, 0, s.xi(), s.yi());
glOrtho(0, s.x, (DisplaySystem.yAxisDown ? 1 : -1) * s.y, 0, -1000, 1000);
glOrtho(0, s.x(), (DisplaySystem.yAxisDown ? 1 : -1) * s.y(), 0, -1000, 1000);
// back to modelview
glMatrixMode(GL_MODELVIEW);
@@ -523,7 +565,7 @@ public class Render {
glShadeModel(GL_SMOOTH);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
}
@@ -6,6 +6,8 @@ import java.util.HashMap;
import mightypork.gamecore.control.AppAccess;
import mightypork.gamecore.control.AppAdapter;
import mightypork.gamecore.control.bus.events.ResourceLoadRequest;
import mightypork.gamecore.render.fonts.impl.DeferredFont;
import mightypork.gamecore.render.fonts.impl.NullFont;
import mightypork.utils.logging.Log;
import org.newdawn.slick.opengl.Texture;
@@ -6,8 +6,6 @@ import mightypork.utils.math.color.RGB;
import mightypork.utils.math.coord.Coord;
import mightypork.utils.math.coord.Rect;
import org.lwjgl.opengl.GL11;
/**
* Font renderer
@@ -17,7 +15,6 @@ import org.lwjgl.opengl.GL11;
public class FontRenderer {
private GLFont font;
private boolean nativeRes = false;
public static enum Align
{
@@ -45,20 +42,6 @@ public class FontRenderer {
}
/**
* Use size specified during font init instead of size provided by
* {@link GLFont} instance (measured from tile heights.<br>
* This is better when the font is drawn in original size, but can cause
* weird artifacts if the font is scaled up.
*
* @param use use it
*/
public void usePtSize(boolean use)
{
nativeRes = use;
}
/**
* Get region needed to draw text at size
*
@@ -81,13 +64,13 @@ public class FontRenderer {
*/
public double getWidth(String text, double height)
{
return getNeededSpace(text, height).x;
return getNeededSpace(text, height).x();
}
private double getScale(double height)
{
return height / (nativeRes ? font.getSize() : font.getGlyphHeight());
return height / font.getHeight();
}
@@ -123,15 +106,14 @@ public class FontRenderer {
*/
public void draw(String text, Coord pos, double height, RGB color)
{
//Render.pushState();
Render.pushMatrix();
//GL11.glEnable(GL11.GL_TEXTURE_2D);
Render.translate(pos.round());
Render.scaleXY(getScale(height));
font.draw(text, color);
//Render.popState();
Render.popMatrix();
}
@@ -1,7 +1,6 @@
package mightypork.gamecore.render.fonts;
import mightypork.gamecore.render.textures.FilterMode;
import mightypork.utils.math.color.RGB;
import mightypork.utils.math.coord.Coord;
@@ -14,9 +13,9 @@ import mightypork.utils.math.coord.Coord;
public interface GLFont {
/**
* Draw string at position
* Draw without scaling at (0, 0) in given color.
*
* @param text string to draw
* @param text text to draw
* @param color draw color
*/
void draw(String text, RGB color);
@@ -34,7 +33,7 @@ public interface GLFont {
/**
* @return font height
*/
int getGlyphHeight();
int getHeight();
/**
@@ -48,20 +47,4 @@ public interface GLFont {
* @return specified font size
*/
int getSize();
/**
* Set used filtering
*
* @param filter font filtering mode
*/
void setFiltering(FilterMode filter);
/**
* Get used filter mode
*
* @return filter mode
*/
FilterMode getFiltering();
}
@@ -1,134 +0,0 @@
package mightypork.gamecore.render.fonts;
import static org.lwjgl.opengl.GL11.*;
import java.awt.Font;
import mightypork.gamecore.render.Render;
import mightypork.gamecore.render.textures.FilterMode;
import mightypork.utils.math.color.RGB;
import mightypork.utils.math.coord.Coord;
import org.newdawn.slick.Color;
import org.newdawn.slick.TrueTypeFont;
/**
* Wrapper for slick font
*
* @author MightyPork
*/
public class SlickFont implements GLFont {
private final TrueTypeFont ttf;
private FilterMode filter;
private final int fsize;
/**
* A font with ASCII and extra chars
*
* @param font font to load
* @param filtering filtering mode
* @param extraChars extra chars to load
*/
public SlickFont(Font font, FilterMode filtering, String extraChars) {
this.filter = filtering;
this.fsize = font.getSize();
ttf = new TrueTypeFont(font, true, stripASCII(extraChars));
}
@Override
public void setFiltering(FilterMode filter)
{
this.filter = filter;
}
private static char[] stripASCII(String chars)
{
if (chars == null) return null;
final StringBuilder sb = new StringBuilder();
for (final char c : chars.toCharArray()) {
if (c <= 255) continue; // already included in default set
sb.append(c);
}
return sb.toString().toCharArray();
}
private void prepareForRender()
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter.num);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter.num);
}
/**
* Draw in color
*
* @param str string to draw
* @param color text color
*/
@Override
public void draw(String str, RGB color)
{
Render.pushState();
prepareForRender();
ttf.drawString(0, 0, str, rgbToSlickColor(color));
Render.popState();
}
private static Color rgbToSlickColor(RGB rgb)
{
return new Color((float) rgb.r, (float) rgb.g, (float) rgb.b, (float) rgb.a);
}
@Override
public Coord getNeededSpace(String text)
{
return new Coord(getWidth(text), getGlyphHeight());
}
@Override
public int getGlyphHeight()
{
return ttf.getHeight();
}
@Override
public int getWidth(String text)
{
return ttf.getWidth(text);
}
@Override
public int getSize()
{
return fsize;
}
@Override
public FilterMode getFiltering()
{
return filter;
}
}
@@ -0,0 +1,430 @@
package mightypork.gamecore.render.fonts.impl;
import static org.lwjgl.opengl.GL11.*;
import java.awt.Color;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.awt.image.DataBufferInt;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.IntBuffer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import mightypork.gamecore.render.fonts.GLFont;
import mightypork.gamecore.render.textures.FilterMode;
import mightypork.utils.logging.Log;
import mightypork.utils.math.color.RGB;
import mightypork.utils.math.coord.Coord;
import org.lwjgl.BufferUtils;
import org.lwjgl.util.glu.GLU;
import org.newdawn.slick.opengl.GLUtils;
/**
* A TrueType font renderer with backing texture.
*
* @author James Chambers (Jimmy)
* @author Jeremy Adams (elias4444)
* @author Kevin Glass (kevglass)
* @author Peter Korzuszek (genail)
* @author David Aaron Muhar (bobjob)
* @author MightyPork
*/
public class CachedFont implements GLFont {
private class CharTile {
public int width;
public int height;
public int texPosX;
public int texPosY;
}
/* char bank */
private final Map<Character, CharTile> chars = new HashMap<>(255);
/* use antialiasing for rendering */
private final boolean antiAlias;
/* loaded font size (requested) */
private final int fontSize;
/* actual height of drawn glyphs */
private int fontHeight;
/* texture id */
private int textureID;
/* texture width */
private int textureWidth;
/* texture height */
private int textureHeight;
/* AWT font source */
private final java.awt.Font font;
private final FilterMode filter;
/**
* Make a font
*
* @param font original awt font to load
* @param antialias use antialiasing when rendering to cache texture
* @param filter used Gl filter
* @param chars chars to load
*/
public CachedFont(java.awt.Font font, boolean antialias, FilterMode filter, String chars) {
this(font, antialias, filter, chars.toCharArray());
}
/**
* Make a font
*
* @param font original awt font to load
* @param antialias use antialiasing when rendering to cache texture
* @param filter used Gl filter
* @param chars chars to load
*/
public CachedFont(java.awt.Font font, boolean antialias, FilterMode filter, char[] chars) {
GLUtils.checkGLContext();
this.font = font;
this.filter = filter;
this.fontSize = font.getSize();
this.antiAlias = antialias;
createSet(chars);
}
/**
* Create a BufferedImage of the given character
*
* @param ch the character
* @return BufferedImage containing the drawn character
*/
private BufferedImage getFontImage(char ch)
{
FontMetrics metrics;
BufferedImage img;
Graphics2D g;
// Create a temporary image to extract the character's size
img = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
g = (Graphics2D) img.getGraphics();
if (antiAlias == true) g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.setFont(font);
metrics = g.getFontMetrics();
final int charwidth = Math.max(1, metrics.charWidth(ch));
final int charheight = Math.max(fontSize, metrics.getHeight());
// Create another image holding the character we are creating
final BufferedImage fontImage = new BufferedImage(charwidth, charheight, BufferedImage.TYPE_INT_ARGB);
g = (Graphics2D) fontImage.getGraphics();
if (antiAlias == true) g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.setFont(font);
g.setColor(Color.WHITE);
g.drawString(String.valueOf(ch), 0, metrics.getAscent());
return fontImage;
}
private void createSet(char[] charsToLoad)
{
try {
class LoadedGlyph {
public char c;
public BufferedImage image;
public int width;
public int height;
public LoadedGlyph(char c, BufferedImage image) {
this.image = image;
this.c = c;
this.width = image.getWidth();
this.height = image.getHeight();
}
}
final List<LoadedGlyph> glyphs = new ArrayList<>();
final List<Character> loaded = new ArrayList<>();
for (final char ch : charsToLoad) {
if (!loaded.contains(ch)) {
glyphs.add(new LoadedGlyph(ch, getFontImage(ch)));
loaded.add(ch);
}
}
int lineHeight = 0;
int beginX = 0, beginY = 0;
int canvasW = 128, canvasH = 128;
boolean needsLarger = false;
// find smallest 2^x size for texture
while (true) {
needsLarger = false;
for (final LoadedGlyph glyph : glyphs) {
if (beginX + glyph.width > canvasW) {
beginY += lineHeight;
lineHeight = 0;
beginX = 0;
}
if (lineHeight < glyph.height) {
lineHeight = glyph.height;
}
if (beginY + lineHeight > canvasH) {
needsLarger = true;
break;
}
// draw.
beginX += glyph.width;
}
if (needsLarger) {
canvasW *= 2;
canvasH *= 2;
beginX = 0;
beginY = 0;
lineHeight = 0;
} else {
Log.f3(String.format("Generating font texture: %d×%d", canvasW, canvasH));
break;
}
}
textureWidth = canvasW;
textureHeight = canvasH;
BufferedImage imag = new BufferedImage(textureWidth, textureHeight, BufferedImage.TYPE_INT_ARGB);
final Graphics2D g = (Graphics2D) imag.getGraphics();
g.setColor(new Color(0, 0, 0, 1));
g.fillRect(0, 0, textureWidth, textureHeight);
int rowHeight = 0, posX = 0, posY = 0;
for (final LoadedGlyph glyph : glyphs) {
final CharTile cht = new CharTile();
cht.width = glyph.width;
cht.height = glyph.height;
if (posX + cht.width >= textureWidth) {
posX = 0;
posY += rowHeight;
rowHeight = 0;
}
cht.texPosX = posX;
cht.texPosY = posY;
if (cht.height > fontHeight) {
fontHeight = cht.height;
}
if (cht.height > rowHeight) {
rowHeight = cht.height;
}
// Draw it here
g.drawImage(glyph.image, posX, posY, null);
posX += cht.width;
chars.put(glyph.c, cht);
}
textureID = loadImage(imag);
imag = null;
} catch (final Exception e) {
Log.e("Failed to load font.", e);
}
}
private int loadImage(BufferedImage bufferedImage)
{
try {
final short width = (short) bufferedImage.getWidth();
final short height = (short) bufferedImage.getHeight();
final int bpp = (byte) bufferedImage.getColorModel().getPixelSize();
ByteBuffer byteBuffer;
final DataBuffer db = bufferedImage.getData().getDataBuffer();
if (db instanceof DataBufferInt) {
final int intI[] = ((DataBufferInt) (bufferedImage.getData().getDataBuffer())).getData();
final byte newI[] = new byte[intI.length * 4];
for (int i = 0; i < intI.length; i++) {
final byte b[] = intToByteArray(intI[i]);
final int newIndex = i * 4;
newI[newIndex] = b[1];
newI[newIndex + 1] = b[2];
newI[newIndex + 2] = b[3];
newI[newIndex + 3] = b[0];
}
byteBuffer = ByteBuffer.allocateDirect(width * height * (bpp / 8)).order(ByteOrder.nativeOrder()).put(newI);
} else {
byteBuffer = ByteBuffer.allocateDirect(width * height * (bpp / 8)).order(ByteOrder.nativeOrder()).put(((DataBufferByte) (bufferedImage.getData().getDataBuffer())).getData());
}
byteBuffer.flip();
final int internalFormat = GL_RGBA8, format = GL_RGBA;
final IntBuffer textureId = BufferUtils.createIntBuffer(1);
glGenTextures(textureId);
glBindTexture(GL_TEXTURE_2D, textureId.get(0));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter.num);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
GLU.gluBuild2DMipmaps(GL_TEXTURE_2D, internalFormat, width, height, format, GL_UNSIGNED_BYTE, byteBuffer);
return textureId.get(0);
} catch (final Exception e) {
Log.e("Failed to load font.", e);
}
return -1;
}
private static byte[] intToByteArray(int value)
{
return new byte[] { (byte) (value >>> 24), (byte) (value >>> 16), (byte) (value >>> 8), (byte) value };
}
private void drawQuad(float xmin, float ymin, float xmax, float ymax, float txmin, float tymin, float txmax, float tymax)
{
final float draw_h = xmax - xmin;
final float draw_w = ymax - ymin;
final float txmin01 = txmin / textureWidth;
final float tymin01 = tymin / textureHeight;
final float twidth01 = ((txmax - txmin) / textureWidth);
final float theight01 = ((tymax - tymin) / textureHeight);
glTexCoord2f(txmin01, tymin01);
glVertex2f(xmin, ymin);
glTexCoord2f(txmin01, tymin01 + theight01);
glVertex2f(xmin, ymin + draw_w);
glTexCoord2f(txmin01 + twidth01, tymin01 + theight01);
glVertex2f(xmin + draw_h, ymin + draw_w);
glTexCoord2f(txmin01 + twidth01, tymin01);
glVertex2f(xmin + draw_h, ymin);
}
/**
* Get size needed to draw given string
*
* @param text drawn text
* @return needed width
*/
@Override
public int getWidth(String text)
{
int totalwidth = 0;
CharTile ch = null;
for (int i = 0; i < text.length(); i++) {
ch = chars.get(text.charAt(i));
if (ch != null) totalwidth += ch.width;
}
return totalwidth;
}
@Override
public int getHeight()
{
return fontHeight;
}
@Override
public int getSize()
{
return fontSize;
}
@Override
public void draw(String text, RGB color)
{
GLUtils.checkGLContext();
glPushAttrib(GL_ENABLE_BIT);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, textureID);
glColor4d(color.r, color.g, color.b, color.a);
glBegin(GL_QUADS);
CharTile chtx = null;
char charCurrent;
glBegin(GL_QUADS);
int totalwidth = 0;
for (int i = 0; i < text.length(); i++) {
charCurrent = text.charAt(i);
chtx = chars.get(charCurrent);
if (chtx != null) {
drawQuad((totalwidth), 0, (totalwidth + chtx.width), (chtx.height), chtx.texPosX, chtx.texPosY, chtx.texPosX + chtx.width, chtx.texPosY + chtx.height);
totalwidth += chtx.width;
}
}
glEnd();
glPopAttrib();
}
@Override
public Coord getNeededSpace(String text)
{
return new Coord(getWidth(text), getHeight());
}
}
@@ -1,15 +1,14 @@
package mightypork.gamecore.render.fonts;
package mightypork.gamecore.render.fonts.impl;
import static org.lwjgl.opengl.GL11.*;
import java.awt.Font;
import java.awt.FontFormatException;
import java.io.IOException;
import java.io.InputStream;
import mightypork.gamecore.loading.BaseDeferredResource;
import mightypork.gamecore.loading.DeferredResource;
import mightypork.gamecore.loading.MustLoadInMainThread;
import mightypork.gamecore.render.fonts.GLFont;
import mightypork.gamecore.render.textures.FilterMode;
import mightypork.utils.files.FileUtils;
import mightypork.utils.logging.LoggedName;
@@ -24,7 +23,7 @@ import mightypork.utils.math.coord.Coord;
*/
@MustLoadInMainThread
@LoggedName(name = "Font")
public class DeferredFont extends BaseDeferredResource implements GLFont {
public class DeferredFont extends DeferredResource implements GLFont {
public static enum FontStyle
{
@@ -38,22 +37,24 @@ public class DeferredFont extends BaseDeferredResource implements GLFont {
}
}
private SlickFont font = null;
private final double size;
private final FontStyle style;
private final String extraChars;
private GLFont font = null;
private double size;
private FontStyle style;
private String chars;
private FilterMode filter;
private boolean antialias;
/**
* A font from resource
* A font from resource; setters shall be used to specify parameters in
* greater detail.
*
* @param resourcePath resource to load
* @param extraChars extra chars (0-255 loaded by default)
* @param chars chars to load; null to load basic chars only
* @param size size (px)
*/
public DeferredFont(String resourcePath, String extraChars, double size) {
this(resourcePath, extraChars, size, FontStyle.PLAIN, FilterMode.NEAREST);
public DeferredFont(String resourcePath, String chars, double size) {
this(resourcePath, chars, size, FontStyle.PLAIN, true, FilterMode.LINEAR);
}
@@ -61,30 +62,55 @@ public class DeferredFont extends BaseDeferredResource implements GLFont {
* A font from resource
*
* @param resourcePath resource to load
* @param extraChars extra chars (0-255 loaded by default)
* @param size size (pt)
* @param style font style
*/
public DeferredFont(String resourcePath, String extraChars, double size, FontStyle style) {
this(resourcePath, extraChars, size, style, FilterMode.NEAREST);
}
/**
* A font from resource
*
* @param resourcePath resource to load
* @param extraChars extra chars (0-255 loaded by default)
* @param size size (pt)
* @param chars chars to load; null to load basic chars only
* @param size size (px)
* @param style font style
* @param antialias use antialiasing for caching texture
* @param filter gl filtering mode
*/
public DeferredFont(String resourcePath, String extraChars, double size, FontStyle style, FilterMode filter) {
public DeferredFont(String resourcePath, String chars, double size, FontStyle style, boolean antialias, FilterMode filter) {
super(resourcePath);
this.size = size;
this.style = style;
this.extraChars = extraChars;
this.chars = chars;
this.filter = filter;
this.antialias = antialias;
}
public void setFont(GLFont font)
{
this.font = font;
}
public void setSize(double size)
{
this.size = size;
}
public void setStyle(FontStyle style)
{
this.style = style;
}
public void setChars(String chars)
{
this.chars = chars;
}
public void setFilter(FilterMode filter)
{
this.filter = filter;
}
public void setAntialias(boolean antialias)
{
this.antialias = antialias;
}
@@ -92,8 +118,8 @@ public class DeferredFont extends BaseDeferredResource implements GLFont {
protected synchronized final void loadResource(String path) throws FontFormatException, IOException
{
final Font awtFont = getAwtFont(path, (float) size, style.numval);
font = new SlickFont(awtFont, filter, extraChars);
font = new CachedFont(awtFont, antialias, filter, chars);
}
@@ -109,7 +135,6 @@ public class DeferredFont extends BaseDeferredResource implements GLFont {
*/
protected Font getAwtFont(String resource, float size, int style) throws FontFormatException, IOException
{
try (InputStream in = FileUtils.getResource(resource)) {
Font awtFont = Font.createFont(Font.TRUETYPE_FONT, in);
@@ -119,7 +144,6 @@ public class DeferredFont extends BaseDeferredResource implements GLFont {
return awtFont;
}
}
@@ -157,11 +181,11 @@ public class DeferredFont extends BaseDeferredResource implements GLFont {
* @return font height
*/
@Override
public int getGlyphHeight()
public int getHeight()
{
if (!ensureLoaded()) return 0;
return font.getGlyphHeight();
return font.getHeight();
}
@@ -187,20 +211,11 @@ public class DeferredFont extends BaseDeferredResource implements GLFont {
// this will have to suffice
font = null;
}
@Override
public void setFiltering(FilterMode filter)
{
this.filter = filter;
if(isLoaded()) font.setFiltering(filter);
}
@Override
public FilterMode getFiltering()
{
return filter;
}
}
@@ -1,4 +1,4 @@
package mightypork.gamecore.render.fonts;
package mightypork.gamecore.render.fonts.impl;
import java.awt.Font;
@@ -17,31 +17,6 @@ import mightypork.utils.logging.LoggedName;
@LoggedName(name = "FontNative")
public class DeferredFontNative extends DeferredFont {
/**
* A font from OS, found by name
*
* @param fontName font family name
* @param extraChars extra chars (0-255 loaded by default)
* @param size size (pt)
*/
public DeferredFontNative(String fontName, String extraChars, double size) {
super(fontName, extraChars, size);
}
/**
* A font from OS, found by name
*
* @param fontName font family name
* @param extraChars extra chars (0-255 loaded by default)
* @param size size (pt)
* @param style font style
*/
public DeferredFontNative(String fontName, String extraChars, double size, FontStyle style) {
super(fontName, extraChars, size, style);
}
/**
* A font from OS, found by name
*
@@ -49,10 +24,11 @@ public class DeferredFontNative extends DeferredFont {
* @param extraChars extra chars (0-255 loaded by default)
* @param size size (pt)
* @param style font style
* @param antialias use antialiasing when drawn on the cache texture
* @param filter GL filtering mode
*/
public DeferredFontNative(String fontName, String extraChars, double size, FontStyle style, FilterMode filter) {
super(fontName, extraChars, size, style, filter);
public DeferredFontNative(String fontName, String extraChars, double size, FontStyle style, boolean antialias, FilterMode filter) {
super(fontName, extraChars, size, style, antialias, filter);
}
@@ -1,7 +1,7 @@
package mightypork.gamecore.render.fonts;
package mightypork.gamecore.render.fonts.impl;
import mightypork.gamecore.render.textures.FilterMode;
import mightypork.gamecore.render.fonts.GLFont;
import mightypork.utils.logging.Log;
import mightypork.utils.math.color.RGB;
import mightypork.utils.math.coord.Coord;
@@ -29,7 +29,7 @@ public class NullFont implements GLFont {
@Override
public int getGlyphHeight()
public int getHeight()
{
return 0;
}
@@ -47,19 +47,5 @@ public class NullFont implements GLFont {
{
return 0;
}
@Override
public void setFiltering(FilterMode filter)
{
// nope
}
@Override
public FilterMode getFiltering()
{
return null;
}
}
@@ -1,7 +1,7 @@
package mightypork.gamecore.render.textures;
import mightypork.gamecore.loading.BaseDeferredResource;
import mightypork.gamecore.loading.DeferredResource;
import mightypork.gamecore.loading.MustLoadInMainThread;
import mightypork.gamecore.render.Render;
import mightypork.utils.logging.LoggedName;
@@ -18,10 +18,10 @@ import org.newdawn.slick.opengl.Texture;
*/
@MustLoadInMainThread
@LoggedName(name = "Texture")
public class DeferredTexture extends BaseDeferredResource implements FilteredTexture {
public class DeferredTexture extends DeferredResource implements FilteredTexture {
private Texture backingTexture;
private FilterMode filter_min = FilterMode.NEAREST;
private FilterMode filter_min = FilterMode.LINEAR;
private FilterMode filter_mag = FilterMode.NEAREST;
private WrapMode wrap = WrapMode.CLAMP;
@@ -90,7 +90,6 @@ public class DeferredTexture extends BaseDeferredResource implements FilteredTex
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, filter_mag.num);
bindRaw();
}
@@ -33,14 +33,19 @@ public class TextureBank extends AppAdapter {
/**
* Load a {@link Texture} from resource, with filters LINEAR and wrap CLAMP
* Load a {@link Texture}
*
* @param key texture key
* @param resourcePath texture resource path
* @param texture texture to load
*/
public void loadTexture(String key, String resourcePath)
public void loadTexture(String key, DeferredTexture texture)
{
loadTexture(key, resourcePath, FilterMode.LINEAR, FilterMode.NEAREST, WrapMode.CLAMP);
getEventBus().send(new ResourceLoadRequest(texture));
textures.put(key, texture);
lastTx = texture;
makeQuad(key, Rect.ONE);
}
@@ -55,16 +60,11 @@ public class TextureBank extends AppAdapter {
*/
public void loadTexture(String key, String resourcePath, FilterMode filter_min, FilterMode filter_mag, WrapMode wrap)
{
final DeferredTexture tx = new DeferredTexture(resourcePath);
tx.setFilter(filter_min, filter_mag);
tx.setWrap(wrap);
final DeferredTexture texture = new DeferredTexture(resourcePath);
texture.setFilter(filter_min, filter_mag);
texture.setWrap(wrap);
getEventBus().send(new ResourceLoadRequest(tx));
textures.put(key, tx);
lastTx = tx;
makeQuad(key, Rect.one());
loadTexture(key, texture);
}
@@ -70,11 +70,11 @@ public class TxQuad {
/**
* @param tx Texture
* @param uvs Rect of texture UVs (0-1)
* @param uvs Rect of texture UVs (0-1); will be stored as is.
*/
public TxQuad(Texture tx, Rect uvs) {
this.tx = tx;
this.uvs = uvs.copy();
this.uvs = uvs.view();
}
@@ -85,7 +85,7 @@ public class TxQuad {
*/
public TxQuad(TxQuad txQuad) {
this.tx = txQuad.tx;
this.uvs = txQuad.uvs.copy();
this.uvs = txQuad.uvs.view();
}