Coord and rect views and freezing; Fixed font glitches.
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
+62
-47
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
+4
-28
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
+3
-17
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user