Reflecting changes in GameCore and MightyUtils

master
Ondřej Hruška 11 years ago
parent d2fe36f745
commit 2377b653cf
  1. 12
      src/mightypork/gamecore/backends/lwjgl/BufferHelper.java
  2. 7
      src/mightypork/gamecore/backends/lwjgl/InitTaskRedirectSlickLog.java
  3. 5
      src/mightypork/gamecore/backends/lwjgl/LwjglBackend.java
  4. 116
      src/mightypork/gamecore/backends/lwjgl/LwjglInputModule.java
  5. 36
      src/mightypork/gamecore/backends/lwjgl/SlickLogRedirector.java
  6. 80
      src/mightypork/gamecore/backends/lwjgl/audio/SlickAudio.java
  7. 24
      src/mightypork/gamecore/backends/lwjgl/audio/SlickAudioModule.java
  8. 20
      src/mightypork/gamecore/backends/lwjgl/graphics/AwtScreenshot.java
  9. 312
      src/mightypork/gamecore/backends/lwjgl/graphics/LwjglGraphicsModule.java
  10. 82
      src/mightypork/gamecore/backends/lwjgl/graphics/SlickTexture.java
  11. 54
      src/mightypork/gamecore/backends/lwjgl/graphics/font/LwjglFont.java
  12. 232
      src/mightypork/gamecore/backends/lwjgl/graphics/font/LwjglTextureBackedFontImpl.java

@ -12,7 +12,7 @@ import org.lwjgl.BufferUtils;
* @author Ondřej Hruška (MightyPork)
*/
public class BufferHelper {
/**
* Create java.nio.FloatBuffer of given floats, and flip it.
*
@ -23,8 +23,8 @@ public class BufferHelper {
{
return (FloatBuffer) BufferUtils.createFloatBuffer(obj.length).put(obj).flip();
}
/**
* Fill java.nio.FloatBuffer with floats or float array
*
@ -36,8 +36,8 @@ public class BufferHelper {
buff.put(obj);
buff.flip();
}
/**
* Create new java.nio.FloatBuffer of given length
*
@ -48,5 +48,5 @@ public class BufferHelper {
{
return BufferUtils.createFloatBuffer(count);
}
}

@ -35,4 +35,11 @@ public class InitTaskRedirectSlickLog extends InitTask {
{
return new String[] { "log" };
}
@Override
public int getPriority()
{
return PRIO_FIRST;
}
}

@ -31,7 +31,12 @@ public class LwjglBackend extends AppBackend {
graphics.init();
audio.init();
input.init();
}
@Override
public void addInitTasks()
{
app.addInitTask(new InitTaskRedirectSlickLog());
}

@ -25,19 +25,19 @@ import org.lwjgl.opengl.Display;
* @author Ondřej Hruška (MightyPork)
*/
public class LwjglInputModule extends InputModule implements Updateable {
/** Current mouse position */
private static final Vect mousePos = new Vect() {
@Override
public double x()
{
if (!Mouse.isInsideWindow()) return Integer.MIN_VALUE;
return Mouse.getX();
}
@Override
public double y()
{
@ -46,22 +46,22 @@ public class LwjglInputModule extends InputModule implements Updateable {
return Display.getHeight() - Mouse.getY();
}
};
@Override
protected void initDevices()
{
try {
tryCreate();
Keyboard.enableRepeatEvents(false);
} catch (final LWJGLException e) {
throw new RuntimeException("Failed to initialize input devices.", e);
}
}
private void tryCreate() throws LWJGLException
{
if (Display.isCreated()) {
@ -69,13 +69,13 @@ public class LwjglInputModule extends InputModule implements Updateable {
Keyboard.create();
}
}
@Override
protected void initKeyCodes()
{
Keys.NONE.setCode(Keyboard.KEY_NONE);
Keys.NUM_1.setCode(Keyboard.KEY_1);
Keys.NUM_2.setCode(Keyboard.KEY_2);
Keys.NUM_3.setCode(Keyboard.KEY_3);
@ -86,7 +86,7 @@ public class LwjglInputModule extends InputModule implements Updateable {
Keys.NUM_8.setCode(Keyboard.KEY_8);
Keys.NUM_9.setCode(Keyboard.KEY_9);
Keys.NUM_0.setCode(Keyboard.KEY_0);
Keys.Q.setCode(Keyboard.KEY_Q);
Keys.W.setCode(Keyboard.KEY_W);
Keys.E.setCode(Keyboard.KEY_E);
@ -113,7 +113,7 @@ public class LwjglInputModule extends InputModule implements Updateable {
Keys.B.setCode(Keyboard.KEY_B);
Keys.N.setCode(Keyboard.KEY_N);
Keys.M.setCode(Keyboard.KEY_M);
Keys.MINUS.setCode(Keyboard.KEY_MINUS);
Keys.EQUALS.setCode(Keyboard.KEY_EQUALS);
Keys.SLASH.setCode(Keyboard.KEY_SLASH);
@ -125,17 +125,17 @@ public class LwjglInputModule extends InputModule implements Updateable {
Keys.GRAVE.setCode(Keyboard.KEY_GRAVE);
Keys.COMMA.setCode(Keyboard.KEY_COMMA);
Keys.PERIOD.setCode(Keyboard.KEY_PERIOD);
Keys.SPACE.setCode(Keyboard.KEY_SPACE);
Keys.BACKSPACE.setCode(Keyboard.KEY_BACK);
Keys.TAB.setCode(Keyboard.KEY_TAB);
Keys.ESCAPE.setCode(Keyboard.KEY_ESCAPE);
Keys.APPS.setCode(Keyboard.KEY_APPS);
Keys.POWER.setCode(Keyboard.KEY_POWER);
Keys.SLEEP.setCode(Keyboard.KEY_SLEEP);
//Keys.MENU.setCode(Keyboard.KEY_MENU); // not defined
Keys.F1.setCode(Keyboard.KEY_F1);
Keys.F2.setCode(Keyboard.KEY_F2);
Keys.F3.setCode(Keyboard.KEY_F3);
@ -151,11 +151,11 @@ public class LwjglInputModule extends InputModule implements Updateable {
Keys.F13.setCode(Keyboard.KEY_F13);
Keys.F14.setCode(Keyboard.KEY_F14);
Keys.F15.setCode(Keyboard.KEY_F15);
Keys.CAPS_LOCK.setCode(Keyboard.KEY_CAPITAL);
Keys.SCROLL_LOCK.setCode(Keyboard.KEY_SCROLL);
Keys.NUM_LOCK.setCode(Keyboard.KEY_NUMLOCK);
Keys.NUMPAD_MINUS.setCode(Keyboard.KEY_SUBTRACT);
Keys.NUMPAD_PLUSS.setCode(Keyboard.KEY_ADD);
Keys.NUMPAD_0.setCode(Keyboard.KEY_NUMPAD0);
@ -172,7 +172,7 @@ public class LwjglInputModule extends InputModule implements Updateable {
Keys.NUMPAD_ENTER.setCode(Keyboard.KEY_NUMPADENTER);
Keys.NUMPAD_DIVIDE.setCode(Keyboard.KEY_DIVIDE);
Keys.NUMPAD_MULTIPLY.setCode(Keyboard.KEY_MULTIPLY);
Keys.CONTROL_LEFT.setCode(Keyboard.KEY_LCONTROL);
Keys.CONTROL_RIGHT.setCode(Keyboard.KEY_RCONTROL);
Keys.ALT_LEFT.setCode(Keyboard.KEY_LMENU);
@ -181,43 +181,43 @@ public class LwjglInputModule extends InputModule implements Updateable {
Keys.SHIFT_RIGHT.setCode(Keyboard.KEY_RSHIFT);
Keys.META_LEFT.setCode(Keyboard.KEY_LMETA);
Keys.META_RIGHT.setCode(Keyboard.KEY_RMETA);
Keys.UP.setCode(Keyboard.KEY_UP);
Keys.DOWN.setCode(Keyboard.KEY_DOWN);
Keys.LEFT.setCode(Keyboard.KEY_LEFT);
Keys.RIGHT.setCode(Keyboard.KEY_RIGHT);
Keys.HOME.setCode(Keyboard.KEY_HOME);
Keys.END.setCode(Keyboard.KEY_END);
Keys.PAGE_UP.setCode(Keyboard.KEY_PRIOR);
Keys.PAGE_DOWN.setCode(Keyboard.KEY_NEXT);
Keys.RETURN.setCode(Keyboard.KEY_RETURN);
Keys.PAUSE.setCode(Keyboard.KEY_PAUSE);
Keys.INSERT.setCode(Keyboard.KEY_INSERT);
Keys.DELETE.setCode(Keyboard.KEY_DELETE);
Keys.SYSRQ.setCode(Keyboard.KEY_SYSRQ);
}
@Override
public void destroy()
{
Mouse.destroy();
Keyboard.destroy();
}
private final VectVar mouseMove = Vect.makeVar();
private final VectVar mouseLastPos = Vect.makeVar();
@Override
public synchronized void update(double delta)
{
// was destroyed or not initialized
if (!Display.isCreated()) return;
if (!Mouse.isCreated() || !Keyboard.isCreated()) {
try {
tryCreate();
@ -225,11 +225,11 @@ public class LwjglInputModule extends InputModule implements Updateable {
Log.e(e);
}
}
if (!Mouse.isCreated() || !Keyboard.isCreated()) return;
if (!Mouse.isCreated() || !Keyboard.isCreated()) return;
Display.processMessages();
// sum the moves
mouseMove.reset();
mouseLastPos.reset();
@ -238,81 +238,81 @@ public class LwjglInputModule extends InputModule implements Updateable {
onMouseEvent(mouseMove, mouseLastPos);
wasMouse = true;
}
if (wasMouse && !mouseMove.isZero()) {
App.bus().send(new MouseMotionEvent(mouseLastPos, mouseMove));
}
while (Keyboard.next()) {
onKeyEvent();
}
if (Display.isCloseRequested()) {
App.shutdown();
}
}
private void onMouseEvent(VectVar moveSum, VectVar lastPos)
{
final int button = Mouse.getEventButton();
final boolean down = Mouse.getEventButtonState();
final VectVar pos = Vect.makeVar(Mouse.getEventX(), Mouse.getEventY());
final VectVar move = Vect.makeVar(Mouse.getEventDX(), Mouse.getEventDY());
final int wheeld = Mouse.getEventDWheel();
// flip Y axis
pos.setY(Display.getHeight() - pos.y());
if (button != -1 || wheeld != 0) {
App.bus().send(new MouseButtonEvent(pos.freeze(), button, down, wheeld));
}
moveSum.setTo(moveSum.add(move));
lastPos.setTo(pos);
}
private void onKeyEvent()
{
final int key = Keyboard.getEventKey();
final boolean down = Keyboard.getEventKeyState();
final char c = Keyboard.getEventCharacter();
App.bus().send(new KeyEvent(key, c, down));
}
@Override
public Vect getMousePos()
{
return mousePos;
}
@Override
public boolean isMouseInside()
{
return Mouse.isInsideWindow();
}
@Override
public void grabMouse(boolean grab)
{
Mouse.setGrabbed(grab);
}
@Override
public boolean isKeyDown(Key key)
{
return key.isDefined() && Keyboard.isKeyDown(key.getCode());
}
@Override
public boolean isMouseButtonDown(int button)
{

@ -12,10 +12,10 @@ import mightypork.utils.logging.writers.LogWriter;
* @author Ondřej Hruška (MightyPork)
*/
class SlickLogRedirector implements org.newdawn.slick.util.LogSystem {
LogWriter writer;
/**
* @param log log to redirect into
*/
@ -23,54 +23,54 @@ class SlickLogRedirector implements org.newdawn.slick.util.LogSystem {
{
this.writer = log;
}
@Override
public void error(String msg, Throwable e)
{
writer.log(Level.SEVERE, msg, e);
}
@Override
public void error(Throwable e)
{
writer.log(Level.SEVERE, null, e);
}
@Override
public void error(String msg)
{
writer.log(Level.SEVERE, msg);
}
@Override
public void warn(String msg)
{
writer.log(Level.WARNING, msg);
}
@Override
public void warn(String msg, Throwable e)
{
writer.log(Level.WARNING, msg, e);
}
@Override
public void info(String msg)
{
writer.log(Level.INFO, msg);
}
@Override
public void debug(String msg)
{
writer.log(Level.FINEST, msg);
}
}

@ -18,18 +18,18 @@ import org.newdawn.slick.openal.SoundStore;
* @author Ondřej Hruška (MightyPork)
*/
public class SlickAudio extends DeferredAudio {
private double pauseLoopPosition = 0;
private boolean looping = false;
private boolean paused = false;
private double lastPlayPitch = 1;
private double lastPlayGain = 1;
/** Audio resource */
private Audio backingAudio = null;
private int sourceID;
/**
* Slick-util based sound resource
*
@ -39,124 +39,124 @@ public class SlickAudio extends DeferredAudio {
{
super(resourceName);
}
@Override
protected void loadResource(String resource) throws IOException
{
final String ext = FileUtil.getExtension(resource);
try(final InputStream stream = FileUtil.getResource(resource)) {
if (stream == null) throw new IOException("Not found: " + resource);
if (stream == null) throw new IOException("Not found: " + resource);
if (ext.equalsIgnoreCase("ogg")) {
backingAudio = SoundStore.get().getOgg(resource, stream);
} else if (ext.equalsIgnoreCase("wav")) {
backingAudio = SoundStore.get().getWAV(resource, stream);
} else if (ext.equalsIgnoreCase("aif")) {
backingAudio = SoundStore.get().getAIF(resource, stream);
} else if (ext.equalsIgnoreCase("mod")) {
backingAudio = SoundStore.get().getMOD(resource, stream);
} else {
throw new RuntimeException("Invalid audio file extension.");
}
}
}
@Override
public void pauseLoop()
{
if (!ensureLoaded()) return;
if (isPlaying() && looping) {
pauseLoopPosition = backingAudio.getPosition();
stop();
paused = true;
}
}
@Override
public void resumeLoop()
{
if (!ensureLoaded()) return;
if (looping && paused) {
sourceID = backingAudio.playAsSoundEffect((float) lastPlayPitch, (float) lastPlayGain, true);
backingAudio.setPosition((float) pauseLoopPosition);
paused = false;
}
}
@Override
public void adjustGain(double gain)
{
AL10.alSourcef(sourceID, AL10.AL_GAIN, (float) gain);
}
@Override
public void stop()
{
if (!isLoaded()) return;
backingAudio.stop();
paused = false;
}
@Override
public boolean isPlaying()
{
if (!isLoaded()) return false;
return backingAudio.isPlaying();
}
@Override
public boolean isPaused()
{
if (!isLoaded()) return false;
return backingAudio.isPaused();
}
@Override
public boolean isActive()
{
if (!isLoaded()) return false;
return sourceID != -1;
}
@Override
public void play(double pitch, double gain, boolean loop, double x, double y, double z)
{
if (!ensureLoaded()) return;
this.lastPlayPitch = pitch;
this.lastPlayGain = gain;
looping = loop;
sourceID = backingAudio.playAsSoundEffect((float) pitch, (float) gain, loop, (float) x, (float) y, (float) z);
}
@Override
public void destroy()
{
if (!isLoaded() || backingAudio == null) return;
backingAudio.release();
backingAudio = null;
}

@ -20,10 +20,10 @@ import org.newdawn.slick.openal.SoundStore;
* @author Ondřej Hruška (MightyPork)
*/
public class SlickAudioModule extends AudioModule {
private final VectVar listenerPos = Vect.makeVar();
@Override
public void init()
{
@ -31,8 +31,8 @@ public class SlickAudioModule extends AudioModule {
SoundStore.get().init();
setListenerPos(Vect.ZERO);
}
@Override
public void setListenerPos(Vect pos)
{
@ -49,27 +49,27 @@ public class SlickAudioModule extends AudioModule {
BufferHelper.fill(buf6, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f);
AL10.alListener(AL10.AL_ORIENTATION, buf6);
}
@Override
public Vect getListenerPos()
{
return listenerPos;
}
@Override
protected void deinitSoundSystem()
{
SoundStore.get().clear();
AL.destroy();
}
@Override
protected DeferredAudio doCreateResource(String res)
{
return new SlickAudio(res);
}
}

@ -19,14 +19,14 @@ import mightypork.gamecore.graphics.Screenshot;
* @author Ondřej Hruška (MightyPork)
*/
public class AwtScreenshot implements Screenshot {
private final int width;
private final int height;
private final int bpp;
private final ByteBuffer bytes;
private BufferedImage image;
/**
* @param width image width
* @param height image height
@ -40,8 +40,8 @@ public class AwtScreenshot implements Screenshot {
this.bpp = bpp;
this.bytes = buffer;
}
/**
* Extract to an image.<br>
* Subsequent calls will use a cached value.
@ -51,9 +51,9 @@ public class AwtScreenshot implements Screenshot {
public BufferedImage getImage()
{
if (image != null) return image;
image = new BufferedImage(this.width, this.height, BufferedImage.TYPE_INT_RGB);
// convert to a buffered image
for (int x = 0; x < this.width; x++) {
for (int y = 0; y < this.height; y++) {
@ -64,11 +64,11 @@ public class AwtScreenshot implements Screenshot {
image.setRGB(x, this.height - (y + 1), (0xFF << 24) | (r << 16) | (g << 8) | b);
}
}
return image;
}
/**
* Save to a file.<br>
* Cached value is used if any.

@ -36,7 +36,7 @@ import org.lwjgl.opengl.GL11;
* @author MightyPork
*/
public class LwjglGraphicsModule extends GraphicsModule {
/** Currently binded color */
private Color activeColor = null;
/** Currently binded color's alpha multiplier */
@ -45,187 +45,187 @@ public class LwjglGraphicsModule extends GraphicsModule {
private final Stack<Color> colorPushStack = new Stack<>();
/** Currently binded texture */
private SlickTexture activeTexture;
/** Display mode used currently for the window */
private DisplayMode windowDisplayMode;
/** FPS the user wants */
private int targetFps;
/** FPS meter used for measuring actual FPS */
private final FpsMeter fpsMeter = new FpsMeter();
/** Flag that at the end of frame, fullscreen should be toggled. */
private boolean fullscreenToggleRequested;
/** Flag that at the end of frame, fullscreen should be set. */
private boolean fullscreenSetRequested;
/** State to which fullscreen should be set. */
private boolean fullscreenSetState;
/** Current screen size */
private static final Vect screenSize = new Vect() {
@Override
public double y()
{
return Display.getHeight();
}
@Override
public double x()
{
return Display.getWidth();
}
};
/** Current screen rectangle */
private static final Rect rect = Rect.make(screenSize);
@Override
public void init()
{
}
@Override
public void createDisplay()
{
try {
Display.create();
} catch (final Exception e) {
throw new RuntimeException("Could not initialize display.", e);
}
}
@Override
public void setColor(Color color)
{
setColor(color, 1);
}
@Override
public void setColor(Color color, double alpha)
{
if (color == null) color = RGB.WHITE;
// color components can change over time - must use equals()
if (activeColorAlpha == alpha && color.equals(activeColor)) return;
activeColor = color;
activeColorAlpha = alpha;
GL11.glColor4d(color.r(), color.g(), color.b(), alpha * color.a());
}
@Override
public void translate(double x, double y)
{
glTranslated(x, y, 0);
}
@Override
public void translate(double x, double y, double z)
{
glTranslated(x, y, z);
}
@Override
public void translate(Vect offset)
{
glTranslated(offset.x(), offset.y(), offset.z());
}
@Override
public void translateXY(Vect offset)
{
glTranslated(offset.x(), offset.y(), 0);
}
@Override
public void scale(double x, double y)
{
glScaled(x, y, 0);
}
@Override
public void scale(double x, double y, double z)
{
glScaled(x, y, z);
}
@Override
public void scale(Vect scale)
{
glScaled(scale.x(), scale.y(), scale.z());
}
@Override
public void scaleXY(double scale)
{
glScaled(scale, scale, 1);
}
@Override
public void scaleX(double scale)
{
glScaled(scale, 1, 1);
}
@Override
public void scaleY(double scale)
{
glScaled(1, scale, 1);
}
@Override
public void scaleZ(double scale)
{
glScaled(1, 1, scale);
}
@Override
public void rotateX(double angle)
{
rotate(angle, AXIS_X);
}
@Override
public void rotateY(double angle)
{
rotate(angle, AXIS_Y);
}
@Override
public void rotateZ(double angle)
{
rotate(angle, AXIS_Z);
}
@Override
public void rotate(double angle, Vect axis)
{
final Vect vec = axis.norm(1);
glRotated(angle, vec.x(), vec.y(), vec.z());
}
@Override
public void pushState()
{
@ -233,8 +233,8 @@ public class LwjglGraphicsModule extends GraphicsModule {
GL11.glPushClientAttrib(GL11.GL_ALL_CLIENT_ATTRIB_BITS);
GL11.glPushMatrix();
}
@Override
public void popState()
{
@ -242,47 +242,47 @@ public class LwjglGraphicsModule extends GraphicsModule {
GL11.glPopClientAttrib();
GL11.glPopAttrib();
}
@Override
public void pushGeometry()
{
GL11.glPushMatrix();
}
@Override
public void popGeometry()
{
GL11.glPopMatrix();
}
@Override
public void pushColor()
{
colorPushStack.push(activeColor);
}
@Override
public void popColor()
{
setColor(colorPushStack.pop());
}
@Override
public void quad(Rect rect)
{
final RectDigest q = rect.digest();
// disable texture
if (activeTexture != null) {
activeTexture = null;
glDisable(GL_TEXTURE_2D);
}
// quad
glBegin(GL_QUADS);
glVertex2d(q.left, q.bottom);
@ -291,51 +291,51 @@ public class LwjglGraphicsModule extends GraphicsModule {
glVertex2d(q.left, q.top);
glEnd();
}
@Override
public void quad(Rect rect, Color color)
{
setColor(color);
quad(rect);
}
@Override
public void quad(Rect rect, Grad grad)
{
final RectDigest r = rect.digest();
// disable texture
if (activeTexture != null) {
activeTexture = null;
glDisable(GL_TEXTURE_2D);
}
// quad
glBegin(GL_QUADS);
setColor(grad.leftBottom);
glVertex2d(r.left, r.bottom);
setColor(grad.rightBottom);
glVertex2d(r.right, r.bottom);
setColor(grad.rightTop);
glVertex2d(r.right, r.top);
setColor(grad.leftTop);
glVertex2d(r.left, r.top);
glEnd();
}
@Override
public void quad(Rect rect, TxQuad txquad)
{
quad(rect, txquad, RGB.WHITE);
}
@Override
public void quad(Rect rect, TxQuad txquad, Color color)
{
@ -345,150 +345,150 @@ public class LwjglGraphicsModule extends GraphicsModule {
activeTexture = (SlickTexture) txquad.tx;
activeTexture.bind();
}
glBegin(GL_QUADS);
setColor(color);
final RectDigest q = rect.digest();
final RectDigest u = txquad.uvs.digest();
final double offs = 0.0001;// hack to avoid white stitching
double tL = u.left + offs, tR = u.right - offs, tT = u.top + offs, tB = u.bottom - offs;
// handle flip
if (txquad.isFlippedY()) {
final double swap = tT;
tT = tB;
tB = swap;
}
if (txquad.isFlippedX()) {
final double swap = tL;
tL = tR;
tR = swap;
}
final double w = activeTexture.getWidth01();
final double h = activeTexture.getHeight01();
// quad with texture
glTexCoord2d(tL * w, tB * h);
glVertex2d(q.left, q.bottom);
glTexCoord2d(tR * w, tB * h);
glVertex2d(q.right, q.bottom);
glTexCoord2d(tR * w, tT * h);
glVertex2d(q.right, q.top);
glTexCoord2d(tL * w, tT * h);
glVertex2d(q.left, q.top);
glEnd();
}
@Override
public void setupProjection()
{
// fix projection for changed size
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
final int w = Display.getWidth();
final int h = Display.getHeight();
glViewport(0, 0, w, h);
glOrtho(0, w, h, 0, -1000, 1000);
// back to modelview
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glDisable(GL_LIGHTING);
glClearDepth(1f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glEnable(GL_NORMALIZE);
glShadeModel(GL_SMOOTH);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
@Override
public DeferredTexture createTextureResource(String path)
{
return new SlickTexture(path);
}
@Override
public DeferredFont createFontResource(String path)
{
return new LwjglFont(path);
}
@Override
public void destroy()
{
Display.destroy();
}
@Override
public void setTargetFps(int fps)
{
this.targetFps = fps;
}
@Override
public void setFullscreen(boolean fs)
{
fullscreenSetRequested = true;
fullscreenSetState = fs;
}
@Override
public void switchFullscreen()
{
fullscreenToggleRequested = true;
}
@Override
public boolean isFullscreen()
{
return Display.isFullscreen();
}
private void doToggleFullscreen()
{
doSetFullscreen(!Display.isFullscreen());
}
private void doSetFullscreen(boolean fs)
{
try {
if (Display.isFullscreen() == fs) return; // no work
if (Display.isFullscreen() == fs) return; // no work
if (fs) {
Log.f3("Entering fullscreen.");
// save window resize
windowDisplayMode = new DisplayMode(Display.getWidth(), Display.getHeight());
Display.setDisplayMode(Display.getDesktopDisplayMode());
Display.setFullscreen(true);
Display.update();
@ -497,9 +497,9 @@ public class LwjglGraphicsModule extends GraphicsModule {
Display.setDisplayMode(windowDisplayMode);
Display.update();
}
App.bus().send(new ViewportChangeEvent(getSize()));
} catch (final Throwable t) {
Log.e("Failed to change fullscreen mode.", t);
try {
@ -510,8 +510,8 @@ public class LwjglGraphicsModule extends GraphicsModule {
}
}
}
@Override
public Screenshot takeScreenshot()
{
@ -521,13 +521,13 @@ public class LwjglGraphicsModule extends GraphicsModule {
final int bpp = 4;
final ByteBuffer buffer = BufferUtils.createByteBuffer(width * height * bpp);
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
final AwtScreenshot sc = new AwtScreenshot(width, height, bpp, buffer);
return sc;
}
@Override
public void beginFrame()
{
@ -535,31 +535,31 @@ public class LwjglGraphicsModule extends GraphicsModule {
if (Display.wasResized()) {
App.bus().send(new ViewportChangeEvent(getSize()));
}
if (fullscreenToggleRequested) {
fullscreenToggleRequested = false;
doToggleFullscreen();
}
if (fullscreenSetRequested) {
fullscreenSetRequested = false;
doSetFullscreen(fullscreenSetState);
}
glLoadIdentity();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
fpsMeter.frame();
}
@Override
public void endFrame()
{
Display.update(false); // don't poll input devices
Display.sync(targetFps);
}
@Override
public void setSize(int width, int height)
{
@ -569,68 +569,68 @@ public class LwjglGraphicsModule extends GraphicsModule {
throw new RuntimeException(e);
}
}
@Override
public void setTitle(String title)
{
Display.setTitle(title);
}
@Override
public void setVSync(boolean vsync)
{
Display.setVSyncEnabled(vsync);
}
@Override
public void setResizable(boolean resizable)
{
Display.setResizable(resizable);
}
@Override
public Rect getRect()
{
return rect;
}
@Override
public long getFps()
{
return fpsMeter.getFPS();
}
@Override
public Vect getCenter()
{
return rect.center();
}
@Override
public int getWidth()
{
return Display.getWidth();
}
@Override
public int getHeight()
{
return Display.getHeight();
}
@Override
public Vect getSize()
{
return screenSize;
}
}

@ -23,12 +23,12 @@ import org.newdawn.slick.opengl.TextureLoader;
@Alias(name = "Texture")
@MustLoadInRenderingContext
public class SlickTexture extends DeferredTexture {
private org.newdawn.slick.opengl.Texture backingTexture;
private boolean alpha;
private boolean alphal;
/**
* @param resourcePath resource path
*/
@ -36,14 +36,14 @@ public class SlickTexture extends DeferredTexture {
{
super(resourcePath);
}
@Override
protected synchronized void loadResource(String path)
{
try {
final String ext = FileUtil.getExtension(path).toUpperCase();
final int filtering;
switch (filter) {
case NEAREST:
@ -55,49 +55,49 @@ public class SlickTexture extends DeferredTexture {
default:
throw new IllegalValueException("Unsupported filtering mode.");
}
final Texture texture = TextureLoader.getTexture(ext, FileUtil.getResource(path), false, filtering);
if (texture == null) {
Log.w("Texture " + path + " could not be loaded.");
}
backingTexture = texture;
} catch (final IOException e) {
Log.e("Loading of texture " + path + " failed.", e);
throw new RuntimeException("Could not load texture " + path + ".", e);
}
}
@Override
public boolean hasAlpha()
{
if (!ensureLoaded()) return false;
if (!alphal) {
alphal = true;
alpha = backingTexture.hasAlpha();
}
return alpha;
}
/**
* Bind to GL context, applying the filters prescribed.
*/
public void bind()
{
if (!ensureLoaded()) return;
//GL11.glEnable(GL11.GL_TEXTURE_2D);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, getTextureID());
GL11.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_TEXTURE_ENV_MODE, GL11.GL_MODULATE);
final int wrapping;
switch (wrap) {
case CLAMP:
@ -109,10 +109,10 @@ public class SlickTexture extends DeferredTexture {
default:
throw new IllegalValueException("Unsupported wrapping mode.");
}
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, wrapping);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, wrapping);
final int filtering;
switch (filter) {
case NEAREST:
@ -124,39 +124,39 @@ public class SlickTexture extends DeferredTexture {
default:
throw new IllegalValueException("Unsupported filtering mode.");
}
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, filtering);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, filtering);
}
@Override
public int getImageHeight()
{
if (!ensureLoaded()) return 0;
return backingTexture.getImageHeight();
}
@Override
public int getImageWidth()
{
if (!ensureLoaded()) return 0;
return backingTexture.getImageWidth();
}
@Override
public void destroy()
{
if (!isLoaded()) return;
backingTexture.release();
}
/**
* Get the height of the texture, 0..1.<br>
*
@ -165,11 +165,11 @@ public class SlickTexture extends DeferredTexture {
public float getHeight01()
{
if (!ensureLoaded()) return 0;
return backingTexture.getHeight();
}
/**
* Get the width of the texture, 0..1.<br>
*
@ -178,18 +178,18 @@ public class SlickTexture extends DeferredTexture {
public float getWidth01()
{
if (!ensureLoaded()) return 0;
return backingTexture.getWidth();
}
/**
* @return OpenGL texture ID
*/
public int getTextureID()
{
if (!ensureLoaded()) return -1;
return backingTexture.getTextureID();
}
}

@ -23,10 +23,10 @@ import mightypork.utils.math.constraints.vect.Vect;
@MustLoadInRenderingContext
@Alias(name = "Font")
public class LwjglFont extends DeferredFont {
private IFont font = null;
/**
* A font from resource
*
@ -36,18 +36,18 @@ public class LwjglFont extends DeferredFont {
{
super(resourcePath);
}
@Override
protected synchronized final void loadResource(String path) throws IOException
{
final Font awtFont = getAwtFont(path, (float) size, style.numval);
font = new LwjglTextureBackedFontImpl(awtFont, antialias, filter, chars);
font.setDiscardRatio(discardTop, discardBottom);
}
/**
* Get a font for a resource path / name
*
@ -60,9 +60,9 @@ public class LwjglFont extends DeferredFont {
protected Font getAwtFont(String resource, float size, int style) throws IOException
{
try(InputStream in = FileUtil.getResource(resource)) {
Font awtFont = null;
Font awtFont = null;
if (in != null) {
awtFont = Font.createFont(Font.TRUETYPE_FONT, in);
awtFont = awtFont.deriveFont(size);
@ -70,14 +70,14 @@ public class LwjglFont extends DeferredFont {
} else {
awtFont = new Font(/* font name */resource, style, (int) size);
}
return awtFont;
} catch (final FontFormatException e) {
throw new IOException("Could not load font, bad format.", e);
}
}
/**
* Draw string
*
@ -88,11 +88,11 @@ public class LwjglFont extends DeferredFont {
public void draw(String str, Color color)
{
if (!ensureLoaded()) return;
font.draw(str, color);
}
/**
* Get size needed to render give string
*
@ -103,11 +103,11 @@ public class LwjglFont extends DeferredFont {
public Vect getNeededSpace(String text)
{
if (!ensureLoaded()) return Vect.ZERO;
return font.getNeededSpace(text);
}
/**
* @return font height
*/
@ -115,27 +115,27 @@ public class LwjglFont extends DeferredFont {
public int getLineHeight()
{
if (!ensureLoaded()) return 0;
return font.getLineHeight();
}
@Override
public int getFontSize()
{
if (!ensureLoaded()) return 0;
return font.getFontSize();
}
@Override
public int getWidth(String text)
{
return font.getWidth(text);
}
@Override
public void destroy()
{

@ -42,46 +42,46 @@ import org.newdawn.slick.opengl.GLUtils;
* @author Ondřej Hruška (MightyPork)
*/
class LwjglTextureBackedFontImpl implements IFont {
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;
private double discardTop;
private double discardBottom;
/**
* Make a font
*
@ -94,8 +94,8 @@ class LwjglTextureBackedFontImpl implements IFont {
{
this(font, antialias, filter, (" " + chars).toCharArray());
}
/**
* Make a font
*
@ -107,16 +107,16 @@ class LwjglTextureBackedFontImpl implements IFont {
public LwjglTextureBackedFontImpl(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
*
@ -128,43 +128,43 @@ class LwjglTextureBackedFontImpl implements IFont {
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(java.awt.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;
@ -173,7 +173,7 @@ class LwjglTextureBackedFontImpl implements IFont {
this.height = image.getHeight();
}
}
final List<LoadedGlyph> glyphs = new ArrayList<>();
final List<Character> loaded = new ArrayList<>();
for (final char ch : charsToLoad) {
@ -182,38 +182,38 @@ class LwjglTextureBackedFontImpl implements IFont {
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;
@ -225,66 +225,66 @@ class LwjglTextureBackedFontImpl implements IFont {
break;
}
}
textureWidth = canvasW;
textureHeight = canvasH;
BufferedImage imag = new BufferedImage(textureWidth, textureHeight, BufferedImage.TYPE_INT_ARGB);
final Graphics2D g = (Graphics2D) imag.getGraphics();
g.setColor(new java.awt.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 Throwable t) {
Log.e("Failed to load font.", t);
}
}
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) {
@ -293,32 +293,32 @@ class LwjglTextureBackedFontImpl implements IFont {
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));
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
final int filtering;
switch (filter) {
case NEAREST:
@ -330,27 +330,27 @@ class LwjglTextureBackedFontImpl implements IFont {
default:
throw new IllegalValueException("Unsupported filtering mode.");
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering);
GLU.gluBuild2DMipmaps(GL_TEXTURE_2D, internalFormat, width, height, format, GL_UNSIGNED_BYTE, byteBuffer);
return textureId.get(0);
} catch (final Throwable t) {
Log.e("Failed to load font.", t);
}
return -1;
}
private static byte[] intToByteArray(int value)
{
return new byte[] { (byte) (value >>> 24), (byte) (value >>> 16), (byte) (value >>> 8), (byte) value };
}
/**
* Get size needed to draw given string
*
@ -363,46 +363,46 @@ class LwjglTextureBackedFontImpl implements IFont {
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 getLineHeight()
{
return (int) Math.round(fontHeight * ((1 - discardTop) - discardBottom));
}
@Override
public int getFontSize()
{
return fontSize;
}
@Override
public void draw(String text, Color color)
{
GLUtils.checkGLContext();
// PUSH
glPushAttrib(GL_ENABLE_BIT);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, textureID);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
final int filtering;
switch (filter) {
case NEAREST:
@ -414,82 +414,82 @@ class LwjglTextureBackedFontImpl implements IFont {
default:
throw new IllegalValueException("Unsupported filtering mode.");
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering);
glColor4d(color.r(), color.g(), color.b(), color.a());
glBegin(GL_QUADS);
CharTile chtx = null;
char charCurrent;
int minx = 0;
for (int i = 0; i < text.length(); i++) {
charCurrent = text.charAt(i);
chtx = chars.get(charCurrent);
if (chtx != null) {
// draw quad
final float txmin = chtx.texPosX;
final float tymin = chtx.texPosY;
final float draw_width = minx + chtx.width - minx;
final float draw_height = chtx.height;
final float drawy0 = (float) (0f - draw_height * discardTop);
final float txmin01 = txmin / textureWidth;
final float tymin01 = tymin / textureHeight;
final float twidth01 = ((chtx.texPosX + chtx.width - txmin) / textureWidth);
final float theight01 = ((chtx.texPosY + chtx.height - tymin) / textureHeight);
glTexCoord2f(txmin01, tymin01);
glVertex2f(minx, drawy0);
glTexCoord2f(txmin01, tymin01 + theight01);
glVertex2f(minx, drawy0 + draw_height);
glTexCoord2f(txmin01 + twidth01, tymin01 + theight01);
glVertex2f(minx + draw_width, drawy0 + draw_height);
glTexCoord2f(txmin01 + twidth01, tymin01);
glVertex2f(minx + draw_width, drawy0);
minx += chtx.width;
}
}
glEnd();
// POP
glPopAttrib();
}
@Override
public VectConst getNeededSpace(String text)
{
return Vect.make(getWidth(text), getLineHeight());
}
@Override
public void setDiscardRatio(double top, double bottom)
{
discardTop = top;
discardBottom = bottom;
}
@Override
public double getTopDiscardRatio()
{
return discardTop;
}
@Override
public double getBottomDiscardRatio()
{

Loading…
Cancel
Save