Reflecting changes in GameCore and MightyUtils
This commit is contained in:
@@ -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;
|
||||
|
||||
|
||||
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()
|
||||
{
|
||||
|
||||
+116
-116
@@ -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()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user