diff --git a/src/mightypork/gamecore/backends/lwjgl/BufferHelper.java b/src/mightypork/gamecore/backends/lwjgl/BufferHelper.java index af75f80..76b7535 100644 --- a/src/mightypork/gamecore/backends/lwjgl/BufferHelper.java +++ b/src/mightypork/gamecore/backends/lwjgl/BufferHelper.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); } - + } diff --git a/src/mightypork/gamecore/backends/lwjgl/InitTaskRedirectSlickLog.java b/src/mightypork/gamecore/backends/lwjgl/InitTaskRedirectSlickLog.java index ee2ed9e..3d52ad6 100644 --- a/src/mightypork/gamecore/backends/lwjgl/InitTaskRedirectSlickLog.java +++ b/src/mightypork/gamecore/backends/lwjgl/InitTaskRedirectSlickLog.java @@ -35,4 +35,11 @@ public class InitTaskRedirectSlickLog extends InitTask { { return new String[] { "log" }; } + + + @Override + public int getPriority() + { + return PRIO_FIRST; + } } diff --git a/src/mightypork/gamecore/backends/lwjgl/LwjglBackend.java b/src/mightypork/gamecore/backends/lwjgl/LwjglBackend.java index 4a6bd5e..08ba9f9 100644 --- a/src/mightypork/gamecore/backends/lwjgl/LwjglBackend.java +++ b/src/mightypork/gamecore/backends/lwjgl/LwjglBackend.java @@ -31,7 +31,12 @@ public class LwjglBackend extends AppBackend { graphics.init(); audio.init(); input.init(); + } + + @Override + public void addInitTasks() + { app.addInitTask(new InitTaskRedirectSlickLog()); } diff --git a/src/mightypork/gamecore/backends/lwjgl/LwjglInputModule.java b/src/mightypork/gamecore/backends/lwjgl/LwjglInputModule.java index 517587e..6e26559 100644 --- a/src/mightypork/gamecore/backends/lwjgl/LwjglInputModule.java +++ b/src/mightypork/gamecore/backends/lwjgl/LwjglInputModule.java @@ -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) { diff --git a/src/mightypork/gamecore/backends/lwjgl/SlickLogRedirector.java b/src/mightypork/gamecore/backends/lwjgl/SlickLogRedirector.java index b2165e2..93985ab 100644 --- a/src/mightypork/gamecore/backends/lwjgl/SlickLogRedirector.java +++ b/src/mightypork/gamecore/backends/lwjgl/SlickLogRedirector.java @@ -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); } - + } diff --git a/src/mightypork/gamecore/backends/lwjgl/audio/SlickAudio.java b/src/mightypork/gamecore/backends/lwjgl/audio/SlickAudio.java index 5ba8460..5bbe7e3 100644 --- a/src/mightypork/gamecore/backends/lwjgl/audio/SlickAudio.java +++ b/src/mightypork/gamecore/backends/lwjgl/audio/SlickAudio.java @@ -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; } diff --git a/src/mightypork/gamecore/backends/lwjgl/audio/SlickAudioModule.java b/src/mightypork/gamecore/backends/lwjgl/audio/SlickAudioModule.java index 3516170..b3cf696 100644 --- a/src/mightypork/gamecore/backends/lwjgl/audio/SlickAudioModule.java +++ b/src/mightypork/gamecore/backends/lwjgl/audio/SlickAudioModule.java @@ -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); } - + } diff --git a/src/mightypork/gamecore/backends/lwjgl/graphics/AwtScreenshot.java b/src/mightypork/gamecore/backends/lwjgl/graphics/AwtScreenshot.java index 8cfdc29..bdd41f4 100644 --- a/src/mightypork/gamecore/backends/lwjgl/graphics/AwtScreenshot.java +++ b/src/mightypork/gamecore/backends/lwjgl/graphics/AwtScreenshot.java @@ -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.
* 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.
* Cached value is used if any. diff --git a/src/mightypork/gamecore/backends/lwjgl/graphics/LwjglGraphicsModule.java b/src/mightypork/gamecore/backends/lwjgl/graphics/LwjglGraphicsModule.java index ba931f0..5f41ca5 100644 --- a/src/mightypork/gamecore/backends/lwjgl/graphics/LwjglGraphicsModule.java +++ b/src/mightypork/gamecore/backends/lwjgl/graphics/LwjglGraphicsModule.java @@ -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 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; } - + } diff --git a/src/mightypork/gamecore/backends/lwjgl/graphics/SlickTexture.java b/src/mightypork/gamecore/backends/lwjgl/graphics/SlickTexture.java index d13636d..c066003 100644 --- a/src/mightypork/gamecore/backends/lwjgl/graphics/SlickTexture.java +++ b/src/mightypork/gamecore/backends/lwjgl/graphics/SlickTexture.java @@ -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.
* @@ -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.
* @@ -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(); } } diff --git a/src/mightypork/gamecore/backends/lwjgl/graphics/font/LwjglFont.java b/src/mightypork/gamecore/backends/lwjgl/graphics/font/LwjglFont.java index 43691ef..ae7ccb4 100644 --- a/src/mightypork/gamecore/backends/lwjgl/graphics/font/LwjglFont.java +++ b/src/mightypork/gamecore/backends/lwjgl/graphics/font/LwjglFont.java @@ -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() { diff --git a/src/mightypork/gamecore/backends/lwjgl/graphics/font/LwjglTextureBackedFontImpl.java b/src/mightypork/gamecore/backends/lwjgl/graphics/font/LwjglTextureBackedFontImpl.java index 6944f35..b3a8707 100644 --- a/src/mightypork/gamecore/backends/lwjgl/graphics/font/LwjglTextureBackedFontImpl.java +++ b/src/mightypork/gamecore/backends/lwjgl/graphics/font/LwjglTextureBackedFontImpl.java @@ -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 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 glyphs = new ArrayList<>(); final List 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() {