parent
6892f5006b
commit
22e5a8a12e
@ -0,0 +1,13 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<classpath> |
||||
<classpathentry kind="src" path="src"/> |
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/> |
||||
<classpathentry combineaccessrules="false" kind="src" path="/GameCore"/> |
||||
<classpathentry combineaccessrules="false" kind="src" path="/MightyUtils"/> |
||||
<classpathentry kind="lib" path="lib/jogg-0.0.7.jar" sourcepath="lib/lwjgl-source-2.8.4.zip"/> |
||||
<classpathentry kind="lib" path="lib/jorbis-0.0.15.jar" sourcepath="lib/lwjgl-source-2.8.4.zip"/> |
||||
<classpathentry kind="lib" path="lib/lwjgl_util.jar" sourcepath="lib/lwjgl-source-2.8.4.zip"/> |
||||
<classpathentry kind="lib" path="lib/lwjgl.jar" sourcepath="lib/lwjgl-source-2.8.4.zip"/> |
||||
<classpathentry kind="lib" path="lib/slick-util.jar" sourcepath="lib/slick-util-src.zip"/> |
||||
<classpathentry kind="output" path="bin"/> |
||||
</classpath> |
@ -0,0 +1,17 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<projectDescription> |
||||
<name>GameCore-LWJGL</name> |
||||
<comment></comment> |
||||
<projects> |
||||
</projects> |
||||
<buildSpec> |
||||
<buildCommand> |
||||
<name>org.eclipse.jdt.core.javabuilder</name> |
||||
<arguments> |
||||
</arguments> |
||||
</buildCommand> |
||||
</buildSpec> |
||||
<natures> |
||||
<nature>org.eclipse.jdt.core.javanature</nature> |
||||
</natures> |
||||
</projectDescription> |
@ -0,0 +1,11 @@ |
||||
eclipse.preferences.version=1 |
||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled |
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 |
||||
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve |
||||
org.eclipse.jdt.core.compiler.compliance=1.7 |
||||
org.eclipse.jdt.core.compiler.debug.lineNumber=generate |
||||
org.eclipse.jdt.core.compiler.debug.localVariable=generate |
||||
org.eclipse.jdt.core.compiler.debug.sourceFile=generate |
||||
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error |
||||
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error |
||||
org.eclipse.jdt.core.compiler.source=1.7 |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,52 @@ |
||||
package mightypork.gamecore.backends.lwjgl; |
||||
|
||||
|
||||
import java.nio.FloatBuffer; |
||||
|
||||
import org.lwjgl.BufferUtils; |
||||
|
||||
|
||||
/** |
||||
* Calc subclass with buffer utils. |
||||
* |
||||
* @author Ondřej Hruška (MightyPork) |
||||
*/ |
||||
public class BufferHelper { |
||||
|
||||
/** |
||||
* Create java.nio.FloatBuffer of given floats, and flip it. |
||||
* |
||||
* @param obj floats or float array |
||||
* @return float buffer |
||||
*/ |
||||
public static FloatBuffer mkFillBuff(float... obj) |
||||
{ |
||||
return (FloatBuffer) BufferUtils.createFloatBuffer(obj.length).put(obj).flip(); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Fill java.nio.FloatBuffer with floats or float array |
||||
* |
||||
* @param buff |
||||
* @param obj |
||||
*/ |
||||
public static void fill(FloatBuffer buff, float... obj) |
||||
{ |
||||
buff.put(obj); |
||||
buff.flip(); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Create new java.nio.FloatBuffer of given length |
||||
* |
||||
* @param count elements |
||||
* @return the new java.nio.FloatBuffer |
||||
*/ |
||||
public static FloatBuffer alloc(int count) |
||||
{ |
||||
return BufferUtils.createFloatBuffer(count); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,38 @@ |
||||
package mightypork.gamecore.backends.lwjgl; |
||||
|
||||
|
||||
import mightypork.gamecore.core.InitTask; |
||||
import mightypork.gamecore.core.OptionalInitTask; |
||||
import mightypork.utils.logging.writers.LogWriter; |
||||
|
||||
|
||||
/** |
||||
* Initializer that redirects slick logging to main logger. |
||||
* |
||||
* @author Ondřej Hruška (MightyPork) |
||||
*/ |
||||
@OptionalInitTask |
||||
public class InitTaskRedirectSlickLog extends InitTask { |
||||
|
||||
@Override |
||||
public void run() |
||||
{ |
||||
LogWriter ml = mightypork.utils.logging.Log.getMainLogger(); |
||||
SlickLogRedirector slr = new SlickLogRedirector(ml); |
||||
org.newdawn.slick.util.Log.setLogSystem(slr); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public String getName() |
||||
{ |
||||
return "slick_log"; |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public String[] getDependencies() |
||||
{ |
||||
return new String[] { "log" }; |
||||
} |
||||
} |
@ -0,0 +1,58 @@ |
||||
package mightypork.gamecore.backends.lwjgl; |
||||
|
||||
|
||||
import mightypork.gamecore.audio.AudioModule; |
||||
import mightypork.gamecore.backends.lwjgl.audio.SlickAudioModule; |
||||
import mightypork.gamecore.backends.lwjgl.graphics.LwjglGraphicsModule; |
||||
import mightypork.gamecore.core.AppBackend; |
||||
import mightypork.gamecore.graphics.GraphicsModule; |
||||
import mightypork.gamecore.input.InputModule; |
||||
|
||||
|
||||
/** |
||||
* Game backend using LWJGL and SlickUtil |
||||
* |
||||
* @author MightyPork |
||||
*/ |
||||
public class LwjglBackend extends AppBackend { |
||||
|
||||
private LwjglGraphicsModule graphics; |
||||
private SlickAudioModule audio; |
||||
private LwjglInputModule input; |
||||
|
||||
|
||||
@Override |
||||
public void initialize() |
||||
{ |
||||
addChildClient(graphics = new LwjglGraphicsModule()); |
||||
addChildClient(audio = new SlickAudioModule()); |
||||
addChildClient(input = new LwjglInputModule()); |
||||
|
||||
graphics.init(); |
||||
audio.init(); |
||||
input.init(); |
||||
|
||||
app.addInitTask(new InitTaskRedirectSlickLog()); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public GraphicsModule getGraphics() |
||||
{ |
||||
return graphics; |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public AudioModule getAudio() |
||||
{ |
||||
return audio; |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public InputModule getInput() |
||||
{ |
||||
return input; |
||||
} |
||||
} |
@ -0,0 +1,302 @@ |
||||
package mightypork.gamecore.backends.lwjgl; |
||||
|
||||
|
||||
import mightypork.gamecore.core.App; |
||||
import mightypork.gamecore.input.InputModule; |
||||
import mightypork.gamecore.input.Key; |
||||
import mightypork.gamecore.input.Keys; |
||||
import mightypork.gamecore.input.events.KeyEvent; |
||||
import mightypork.gamecore.input.events.MouseButtonEvent; |
||||
import mightypork.gamecore.input.events.MouseMotionEvent; |
||||
import mightypork.utils.interfaces.Updateable; |
||||
import mightypork.utils.math.constraints.vect.Vect; |
||||
import mightypork.utils.math.constraints.vect.var.VectVar; |
||||
|
||||
import org.lwjgl.LWJGLException; |
||||
import org.lwjgl.input.Keyboard; |
||||
import org.lwjgl.input.Mouse; |
||||
import org.lwjgl.opengl.Display; |
||||
|
||||
|
||||
/** |
||||
* Lwjgl Input Module. |
||||
* |
||||
* @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() |
||||
{ |
||||
if (!Mouse.isInsideWindow()) return Integer.MIN_VALUE; |
||||
// flip Y axis
|
||||
return Display.getHeight() - Mouse.getY(); |
||||
} |
||||
}; |
||||
|
||||
|
||||
@Override |
||||
protected void initDevices() |
||||
{ |
||||
try { |
||||
Mouse.create(); |
||||
Keyboard.create(); |
||||
Keyboard.enableRepeatEvents(false); |
||||
} catch (final LWJGLException e) { |
||||
throw new RuntimeException("Failed to initialize input devices.", e); |
||||
} |
||||
} |
||||
|
||||
|
||||
@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); |
||||
Keys.NUM_4.setCode(Keyboard.KEY_4); |
||||
Keys.NUM_5.setCode(Keyboard.KEY_5); |
||||
Keys.NUM_6.setCode(Keyboard.KEY_6); |
||||
Keys.NUM_7.setCode(Keyboard.KEY_7); |
||||
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); |
||||
Keys.R.setCode(Keyboard.KEY_R); |
||||
Keys.T.setCode(Keyboard.KEY_T); |
||||
Keys.Y.setCode(Keyboard.KEY_Y); |
||||
Keys.U.setCode(Keyboard.KEY_U); |
||||
Keys.I.setCode(Keyboard.KEY_I); |
||||
Keys.O.setCode(Keyboard.KEY_O); |
||||
Keys.P.setCode(Keyboard.KEY_P); |
||||
Keys.A.setCode(Keyboard.KEY_A); |
||||
Keys.S.setCode(Keyboard.KEY_S); |
||||
Keys.D.setCode(Keyboard.KEY_D); |
||||
Keys.F.setCode(Keyboard.KEY_F); |
||||
Keys.G.setCode(Keyboard.KEY_G); |
||||
Keys.H.setCode(Keyboard.KEY_H); |
||||
Keys.J.setCode(Keyboard.KEY_J); |
||||
Keys.K.setCode(Keyboard.KEY_K); |
||||
Keys.L.setCode(Keyboard.KEY_L); |
||||
Keys.Z.setCode(Keyboard.KEY_Z); |
||||
Keys.X.setCode(Keyboard.KEY_X); |
||||
Keys.C.setCode(Keyboard.KEY_C); |
||||
Keys.V.setCode(Keyboard.KEY_V); |
||||
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); |
||||
Keys.BACKSLASH.setCode(Keyboard.KEY_BACKSLASH); |
||||
Keys.BRACKET_LEFT.setCode(Keyboard.KEY_LBRACKET); |
||||
Keys.BRACKET_RIGHT.setCode(Keyboard.KEY_RBRACKET); |
||||
Keys.SEMICOLON.setCode(Keyboard.KEY_SEMICOLON); |
||||
Keys.APOSTROPHE.setCode(Keyboard.KEY_APOSTROPHE); |
||||
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); |
||||
Keys.F4.setCode(Keyboard.KEY_F4); |
||||
Keys.F5.setCode(Keyboard.KEY_F5); |
||||
Keys.F6.setCode(Keyboard.KEY_F6); |
||||
Keys.F7.setCode(Keyboard.KEY_F7); |
||||
Keys.F8.setCode(Keyboard.KEY_F8); |
||||
Keys.F9.setCode(Keyboard.KEY_F9); |
||||
Keys.F10.setCode(Keyboard.KEY_F10); |
||||
Keys.F11.setCode(Keyboard.KEY_F11); |
||||
Keys.F12.setCode(Keyboard.KEY_F12); |
||||
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); |
||||
Keys.NUMPAD_1.setCode(Keyboard.KEY_NUMPAD1); |
||||
Keys.NUMPAD_2.setCode(Keyboard.KEY_NUMPAD2); |
||||
Keys.NUMPAD_3.setCode(Keyboard.KEY_NUMPAD3); |
||||
Keys.NUMPAD_4.setCode(Keyboard.KEY_NUMPAD4); |
||||
Keys.NUMPAD_5.setCode(Keyboard.KEY_NUMPAD5); |
||||
Keys.NUMPAD_6.setCode(Keyboard.KEY_NUMPAD6); |
||||
Keys.NUMPAD_7.setCode(Keyboard.KEY_NUMPAD7); |
||||
Keys.NUMPAD_8.setCode(Keyboard.KEY_NUMPAD8); |
||||
Keys.NUMPAD_9.setCode(Keyboard.KEY_NUMPAD9); |
||||
Keys.NUMPAD_DECIMAL.setCode(Keyboard.KEY_DECIMAL); |
||||
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); |
||||
Keys.ALT_RIGHT.setCode(Keyboard.KEY_RMENU); |
||||
Keys.SHIFT_LEFT.setCode(Keyboard.KEY_LSHIFT); |
||||
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()) return; |
||||
if (!Keyboard.isCreated()) return; |
||||
|
||||
Display.processMessages(); |
||||
|
||||
// sum the moves
|
||||
mouseMove.reset(); |
||||
mouseLastPos.reset(); |
||||
boolean wasMouse = false; |
||||
while (Mouse.next()) { |
||||
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) |
||||
{ |
||||
return Mouse.isButtonDown(button); |
||||
} |
||||
} |
@ -0,0 +1,75 @@ |
||||
package mightypork.gamecore.backends.lwjgl; |
||||
|
||||
|
||||
import java.util.logging.Level; |
||||
|
||||
import mightypork.utils.logging.writers.LogWriter; |
||||
|
||||
|
||||
/** |
||||
* Used to redirect slick log into main logger. |
||||
* |
||||
* @author Ondřej Hruška (MightyPork) |
||||
*/ |
||||
class SlickLogRedirector implements org.newdawn.slick.util.LogSystem { |
||||
|
||||
LogWriter writer; |
||||
|
||||
|
||||
/** |
||||
* @param log log to redirect into |
||||
*/ |
||||
public SlickLogRedirector(LogWriter log) { |
||||
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); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,146 @@ |
||||
package mightypork.gamecore.backends.lwjgl.audio; |
||||
|
||||
|
||||
import java.io.IOException; |
||||
import java.io.InputStream; |
||||
|
||||
import mightypork.gamecore.audio.DeferredAudio; |
||||
import mightypork.utils.files.FileUtil; |
||||
|
||||
import org.lwjgl.openal.AL10; |
||||
import org.newdawn.slick.openal.Audio; |
||||
import org.newdawn.slick.openal.SoundStore; |
||||
|
||||
|
||||
/** |
||||
* SlickUtil-based deferred audio resource. |
||||
* |
||||
* @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; |
||||
|
||||
|
||||
public SlickAudio(String resourceName) { |
||||
super(resourceName); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
protected void loadResource(String resource) throws IOException |
||||
{ |
||||
final String ext = FileUtil.getExtension(resource); |
||||
|
||||
try (final InputStream stream = FileUtil.getResource(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 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; |
||||
} |
||||
} |
@ -0,0 +1,75 @@ |
||||
package mightypork.gamecore.backends.lwjgl.audio; |
||||
|
||||
|
||||
import java.nio.FloatBuffer; |
||||
|
||||
import mightypork.gamecore.audio.AudioModule; |
||||
import mightypork.gamecore.audio.DeferredAudio; |
||||
import mightypork.gamecore.backends.lwjgl.BufferHelper; |
||||
import mightypork.utils.math.constraints.vect.Vect; |
||||
import mightypork.utils.math.constraints.vect.var.VectVar; |
||||
|
||||
import org.lwjgl.openal.AL; |
||||
import org.lwjgl.openal.AL10; |
||||
import org.newdawn.slick.openal.SoundStore; |
||||
|
||||
|
||||
/** |
||||
* SlickUtil-based audio module |
||||
* |
||||
* @author Ondřej Hruška (MightyPork) |
||||
*/ |
||||
public class SlickAudioModule extends AudioModule { |
||||
|
||||
private final VectVar listenerPos = Vect.makeVar(); |
||||
|
||||
|
||||
@Override |
||||
public void init() |
||||
{ |
||||
SoundStore.get().setMaxSources(256); |
||||
SoundStore.get().init(); |
||||
setListenerPos(Vect.ZERO); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void setListenerPos(Vect pos) |
||||
{ |
||||
listenerPos.setTo(pos); |
||||
final FloatBuffer buf3 = BufferHelper.alloc(3); |
||||
final FloatBuffer buf6 = BufferHelper.alloc(6); |
||||
buf3.clear(); |
||||
BufferHelper.fill(buf3, (float) pos.x(), (float) pos.y(), (float) pos.z()); |
||||
AL10.alListener(AL10.AL_POSITION, buf3); |
||||
buf3.clear(); |
||||
BufferHelper.fill(buf3, 0, 0, 0); |
||||
AL10.alListener(AL10.AL_VELOCITY, buf3); |
||||
buf6.clear(); |
||||
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); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,84 @@ |
||||
package mightypork.gamecore.backends.lwjgl.graphics; |
||||
|
||||
|
||||
import java.awt.image.BufferedImage; |
||||
import java.io.File; |
||||
import java.io.IOException; |
||||
import java.nio.ByteBuffer; |
||||
|
||||
import javax.imageio.ImageIO; |
||||
|
||||
import mightypork.gamecore.graphics.Screenshot; |
||||
|
||||
|
||||
/** |
||||
* Screenshot object, can be used to extract image or write to file.<br> |
||||
* Screenshot, once taken, can be safely processed in separate thread.<br> |
||||
* Based on {@link BufferedImage} and {@link ImageIO}. |
||||
* |
||||
* @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 |
||||
* @param bpp bits per pixel (typically 4) |
||||
* @param buffer |
||||
*/ |
||||
public AwtScreenshot(int width, int height, int bpp, ByteBuffer buffer) { |
||||
this.width = width; |
||||
this.height = height; |
||||
this.bpp = bpp; |
||||
this.bytes = buffer; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Extract to an image.<br> |
||||
* Subsequent calls will use a cached value. |
||||
* |
||||
* @return image |
||||
*/ |
||||
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++) { |
||||
final int i = (x + (this.width * y)) * this.bpp; |
||||
final int r = this.bytes.get(i) & 0xFF; |
||||
final int g = this.bytes.get(i + 1) & 0xFF; |
||||
final int b = this.bytes.get(i + 2) & 0xFF; |
||||
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. |
||||
* |
||||
* @param file target file |
||||
* @throws IOException on error writing to file |
||||
*/ |
||||
@Override |
||||
public void save(File file) throws IOException |
||||
{ |
||||
file.getParentFile().mkdirs(); |
||||
ImageIO.write(getImage(), "PNG", file); |
||||
} |
||||
} |
@ -0,0 +1,620 @@ |
||||
package mightypork.gamecore.backends.lwjgl.graphics; |
||||
|
||||
|
||||
import static org.lwjgl.opengl.GL11.*; |
||||
|
||||
import java.nio.ByteBuffer; |
||||
import java.util.Stack; |
||||
|
||||
import mightypork.gamecore.core.App; |
||||
import mightypork.gamecore.graphics.GraphicsModule; |
||||
import mightypork.gamecore.graphics.Screenshot; |
||||
import mightypork.gamecore.graphics.textures.DeferredTexture; |
||||
import mightypork.gamecore.graphics.textures.TxQuad; |
||||
import mightypork.gamecore.gui.events.ViewportChangeEvent; |
||||
import mightypork.utils.logging.Log; |
||||
import mightypork.utils.math.color.Color; |
||||
import mightypork.utils.math.color.Grad; |
||||
import mightypork.utils.math.color.pal.RGB; |
||||
import mightypork.utils.math.constraints.rect.Rect; |
||||
import mightypork.utils.math.constraints.rect.caching.RectDigest; |
||||
import mightypork.utils.math.constraints.vect.Vect; |
||||
import mightypork.utils.math.timing.FpsMeter; |
||||
|
||||
import org.lwjgl.BufferUtils; |
||||
import org.lwjgl.LWJGLException; |
||||
import org.lwjgl.opengl.Display; |
||||
import org.lwjgl.opengl.DisplayMode; |
||||
import org.lwjgl.opengl.GL11; |
||||
|
||||
|
||||
/** |
||||
* LWJGL rendering module |
||||
* |
||||
* @author MightyPork |
||||
*/ |
||||
public class LwjglGraphicsModule extends GraphicsModule { |
||||
|
||||
/** Currently binded color */ |
||||
private Color activeColor = null; |
||||
/** Currently binded color's alpha multiplier */ |
||||
private double activeColorAlpha = 1; |
||||
/** Stack of pushed colors */ |
||||
private 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 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() |
||||
{ |
||||
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() |
||||
{ |
||||
GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS); |
||||
GL11.glPushClientAttrib(GL11.GL_ALL_CLIENT_ATTRIB_BITS); |
||||
GL11.glPushMatrix(); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void popState() |
||||
{ |
||||
GL11.glPopMatrix(); |
||||
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); |
||||
glVertex2d(q.right, q.bottom); |
||||
glVertex2d(q.right, q.top); |
||||
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) |
||||
{ |
||||
// texture is loaded uniquely -> can compare with ==
|
||||
if (activeTexture != txquad.tx) { |
||||
glEnable(GL_TEXTURE_2D); |
||||
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(); |
||||
|
||||
int w = Display.getWidth(); |
||||
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 getLazyTexture(String path) |
||||
{ |
||||
return new SlickTexture(path); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void destroy() |
||||
{ |
||||
Display.destroy(); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void setTargetFps(int fps) |
||||
{ |
||||
this.targetFps = fps; |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void setFullscreen(boolean fs) |
||||
{ |
||||
fullscreenSetRequested = true; |
||||