parent
dda4aa171e
commit
da0737a4c6
@ -1,133 +0,0 @@ |
|||||||
package junk; |
|
||||||
|
|
||||||
|
|
||||||
import java.io.File; |
|
||||||
import java.util.ArrayList; |
|
||||||
import java.util.List; |
|
||||||
import java.util.logging.Level; |
|
||||||
|
|
||||||
import mightypork.gamecore.core.AppBackend; |
|
||||||
import mightypork.gamecore.resources.ResourceSetup; |
|
||||||
import mightypork.gamecore.resources.loading.AsyncResourceLoader; |
|
||||||
import mightypork.gamecore.resources.loading.ResourceLoader; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Init options holder class
|
|
||||||
*/ |
|
||||||
public class AppInitOptions { |
|
||||||
|
|
||||||
String logDir = "log"; |
|
||||||
String logFilePrefix = "runtime"; |
|
||||||
|
|
||||||
String screenshotDir = "screenshots"; |
|
||||||
|
|
||||||
boolean busLogging = false; |
|
||||||
|
|
||||||
String configFile = "settings.cfg"; |
|
||||||
String configComment = "Main config file"; |
|
||||||
|
|
||||||
final List<ResourceSetup> resourceLists = new ArrayList<>(); |
|
||||||
final List<KeySetup> keyLists = new ArrayList<>(); |
|
||||||
final List<ConfigSetup> configLists = new ArrayList<>(); |
|
||||||
|
|
||||||
ResourceLoader resourceLoader = new AsyncResourceLoader(); |
|
||||||
Level logLevel = Level.ALL; |
|
||||||
public boolean sigleInstance = true; |
|
||||||
Level logSoutLevel = Level.ALL; |
|
||||||
|
|
||||||
|
|
||||||
public void setConfigFile(String filename, String comment) |
|
||||||
{ |
|
||||||
configFile = filename; |
|
||||||
configComment = comment; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public void addConfig(ConfigSetup cfg) |
|
||||||
{ |
|
||||||
configLists.add(cfg); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public void addKeys(KeySetup keys) |
|
||||||
{ |
|
||||||
keyLists.add(keys); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public void addResources(ResourceSetup res) |
|
||||||
{ |
|
||||||
resourceLists.add(res); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public void setBackend(AppBackend backend) |
|
||||||
{ |
|
||||||
this.backend = backend; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Set whether to run in single instance mode, or allow multiple instances.<br> |
|
||||||
* Multiple instances running can cause various collisions (eg. when writing |
|
||||||
* config file or logging). |
|
||||||
* |
|
||||||
* @param sigleInstance true to allow only one instance |
|
||||||
*/ |
|
||||||
public void setSigleInstance(boolean sigleInstance) |
|
||||||
{ |
|
||||||
this.sigleInstance = sigleInstance; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Set working directory path. If not exists, it will be created. |
|
||||||
* |
|
||||||
* @param workdir work dir path |
|
||||||
*/ |
|
||||||
public void setWorkdir(File workdir) |
|
||||||
{ |
|
||||||
this.workdir = workdir; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public void setBusLogging(boolean yes) |
|
||||||
{ |
|
||||||
busLogging = yes; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public void setLogOptions(String logDir, String filePrefix, int archivedCount, Level logLevel) |
|
||||||
{ |
|
||||||
this.logDir = logDir; |
|
||||||
this.logFilePrefix = filePrefix; |
|
||||||
this.logArchiveCount = archivedCount; |
|
||||||
this.logLevel = logLevel; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public void setResourceLoader(ResourceLoader resLoader) |
|
||||||
{ |
|
||||||
resourceLoader = resLoader; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public void setScreenshotDir(String path) |
|
||||||
{ |
|
||||||
this.screenshotDir = path; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public void setLockFile(String lockFile) |
|
||||||
{ |
|
||||||
this.lockFile = lockFile; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public void setLogLevel(Level logLevel, Level soutLevel) |
|
||||||
{ |
|
||||||
this.logLevel = logLevel; |
|
||||||
this.logSoutLevel = soutLevel; |
|
||||||
} |
|
||||||
} |
|
@ -1,184 +0,0 @@ |
|||||||
package junk; |
|
||||||
|
|
||||||
|
|
||||||
import java.lang.Thread.UncaughtExceptionHandler; |
|
||||||
|
|
||||||
import mightypork.gamecore.backends.lwjgl.LwjglInputModule; |
|
||||||
import mightypork.gamecore.core.App; |
|
||||||
import mightypork.gamecore.core.AppBackend; |
|
||||||
import mightypork.gamecore.core.MainLoop; |
|
||||||
import mightypork.gamecore.core.WorkDir; |
|
||||||
import mightypork.gamecore.core.config.Config; |
|
||||||
import mightypork.gamecore.gui.screens.ScreenRegistry; |
|
||||||
import mightypork.gamecore.gui.screens.impl.CrossfadeOverlay; |
|
||||||
import mightypork.gamecore.resources.Res; |
|
||||||
import mightypork.gamecore.resources.ResourceSetup; |
|
||||||
import mightypork.utils.logging.Log; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Basic screen-based game with subsystems.<br> |
|
||||||
* This class takes care of the initialization sequence. |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public abstract class BaseApp extends App implements UncaughtExceptionHandler { |
|
||||||
|
|
||||||
// modules
|
|
||||||
private MainLoop gameLoop; |
|
||||||
private ScreenRegistry screenRegistry; |
|
||||||
|
|
||||||
private boolean started = false; |
|
||||||
private boolean lockObtained = false; |
|
||||||
|
|
||||||
// init opt holder
|
|
||||||
private final AppInitOptions opt = new AppInitOptions(); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Get init options |
|
||||||
* |
|
||||||
* @return opt holder |
|
||||||
*/ |
|
||||||
public AppInitOptions getInitOptions() |
|
||||||
{ |
|
||||||
if (started) { |
|
||||||
throw new IllegalStateException("Cannot alter init options after starting the App."); |
|
||||||
} |
|
||||||
|
|
||||||
return opt; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public BaseApp(AppBackend backend) { |
|
||||||
super(backend); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Start the application |
|
||||||
*/ |
|
||||||
@Override |
|
||||||
public final void start() |
|
||||||
{ |
|
||||||
initialize(); |
|
||||||
|
|
||||||
Log.i("Starting main loop..."); |
|
||||||
|
|
||||||
// open first screen !!!
|
|
||||||
started = true; |
|
||||||
gameLoop.start(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Init the app |
|
||||||
*/ |
|
||||||
protected void initialize() |
|
||||||
{ |
|
||||||
WorkDir.init(opt.workdir); |
|
||||||
|
|
||||||
if (opt.sigleInstance) initLock(); |
|
||||||
lockObtained = true; |
|
||||||
|
|
||||||
for (final RouteSetup rs : opt.routeLists) { |
|
||||||
WorkDir.registerRoutes(rs); |
|
||||||
} |
|
||||||
WorkDir.addPath("_screenshot_dir", opt.screenshotDir); |
|
||||||
|
|
||||||
// apply configurations
|
|
||||||
Config.init(WorkDir.getFile(opt.configFile), opt.configComment); |
|
||||||
|
|
||||||
// add keys to config
|
|
||||||
for (final KeySetup l : opt.keyLists) { |
|
||||||
Config.registerKeys(l); |
|
||||||
} |
|
||||||
|
|
||||||
// add options to config
|
|
||||||
for (final ConfigSetup c : opt.configLists) { |
|
||||||
Config.registerOptions(c); |
|
||||||
} |
|
||||||
Config.load(); |
|
||||||
|
|
||||||
/* |
|
||||||
* Display |
|
||||||
*/ |
|
||||||
Log.f2("Initializing Display System..."); |
|
||||||
initDisplay(gfx()); |
|
||||||
|
|
||||||
/* |
|
||||||
* Audio |
|
||||||
*/ |
|
||||||
Log.f2("Initializing Sound System..."); |
|
||||||
soundSystem = new SoundSystem(this); |
|
||||||
initSoundSystem(soundSystem); |
|
||||||
|
|
||||||
/* |
|
||||||
* Input |
|
||||||
*/ |
|
||||||
Log.f2("Initializing Input System..."); |
|
||||||
inputSystem = new LwjglInputModule(this); |
|
||||||
initInputSystem(inputSystem); |
|
||||||
|
|
||||||
/* |
|
||||||
* Prepare main loop |
|
||||||
*/ |
|
||||||
Log.f1("Creating Screen Registry and Game Loop..."); |
|
||||||
screenRegistry = new ScreenRegistry(this); |
|
||||||
gameLoop = createMainLoop(); |
|
||||||
gameLoop.setRootRenderable(screenRegistry); |
|
||||||
|
|
||||||
/* |
|
||||||
* Load resources |
|
||||||
* |
|
||||||
* Resources should be registered to registries, and AsyncResourceLoader will load them. |
|
||||||
*/ |
|
||||||
Log.f1("Loading resources..."); |
|
||||||
if (opt.resourceLoader != null) { |
|
||||||
opt.resourceLoader.init(this); |
|
||||||
} |
|
||||||
|
|
||||||
Res.init(this); |
|
||||||
|
|
||||||
for (final ResourceSetup rl : opt.resourceLists) { |
|
||||||
Res.load(rl); |
|
||||||
} |
|
||||||
|
|
||||||
/* |
|
||||||
* Screen registry |
|
||||||
* |
|
||||||
* Must be after resources, because screens can request them during instantiation. |
|
||||||
*/ |
|
||||||
Log.f2("Registering screens..."); |
|
||||||
initScreens(screenRegistry); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Register game screens to the registry. |
|
||||||
* |
|
||||||
* @param screens |
|
||||||
*/ |
|
||||||
protected void initScreens(ScreenRegistry screens) |
|
||||||
{ |
|
||||||
screens.addOverlay(new CrossfadeOverlay(this)); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Create game loop instance |
|
||||||
* |
|
||||||
* @return the game loop. |
|
||||||
*/ |
|
||||||
protected MainLoop createMainLoop() |
|
||||||
{ |
|
||||||
return new MainLoop(this); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
protected void beforeShutdown() |
|
||||||
{ |
|
||||||
// ???
|
|
||||||
if (lockObtained) Config.save(); |
|
||||||
} |
|
||||||
} |
|
@ -1,299 +0,0 @@ |
|||||||
//package junk;
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//import static org.lwjgl.opengl.GL11.*;
|
|
||||||
//
|
|
||||||
//import java.nio.ByteBuffer;
|
|
||||||
//
|
|
||||||
//import mightypork.gamecore.backend.lwjgl.AwtScreenshot;
|
|
||||||
//import mightypork.gamecore.core.modules.AppAccess;
|
|
||||||
//import mightypork.gamecore.core.modules.AppModule;
|
|
||||||
//import mightypork.gamecore.render.events.DisplayReadyEvent;
|
|
||||||
//import mightypork.gamecore.render.events.ViewportChangeEvent;
|
|
||||||
//import mightypork.utils.logging.Log;
|
|
||||||
//import mightypork.utils.math.constraints.rect.Rect;
|
|
||||||
//import mightypork.utils.math.constraints.rect.RectBound;
|
|
||||||
//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;
|
|
||||||
//
|
|
||||||
//
|
|
||||||
///**
|
|
||||||
// * Display system
|
|
||||||
// *
|
|
||||||
// * @author Ondřej Hruška (MightyPork)
|
|
||||||
// */
|
|
||||||
//@Deprecated
|
|
||||||
//public class DisplaySystem extends AppModule implements RectBound {
|
|
||||||
//
|
|
||||||
// private DisplayMode windowDisplayMode;
|
|
||||||
// private int targetFps;
|
|
||||||
// private FpsMeter fpsMeter;
|
|
||||||
// private boolean fullscreenSwitchRequested;
|
|
||||||
//
|
|
||||||
// /** Current screen size */
|
|
||||||
// private static final Vect screenSize = new Vect() {
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// public double y()
|
|
||||||
// {
|
|
||||||
// return Display.getHeight();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// public double x()
|
|
||||||
// {
|
|
||||||
// return Display.getWidth();
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
//
|
|
||||||
// private static final Rect rect = Rect.make(screenSize);
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * @param app app access
|
|
||||||
// */
|
|
||||||
// public DisplaySystem(AppAccess app) {
|
|
||||||
// super(app);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// protected void deinit()
|
|
||||||
// {
|
|
||||||
// Display.destroy();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Set target fps (for syncing in endFrame() call).<br>
|
|
||||||
// * With vsync enabled, the target fps may not be met.
|
|
||||||
// *
|
|
||||||
// * @param fps requested fps
|
|
||||||
// */
|
|
||||||
// public void setTargetFps(int fps)
|
|
||||||
// {
|
|
||||||
// this.targetFps = fps;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Create a main window
|
|
||||||
// *
|
|
||||||
// * @param width requested width
|
|
||||||
// * @param height requested height
|
|
||||||
// * @param resizable is resizable by the user
|
|
||||||
// * @param fullscreen is in fullscreen
|
|
||||||
// * @param title window title
|
|
||||||
// */
|
|
||||||
// public void createMainWindow(int width, int height, boolean resizable, boolean fullscreen, String title)
|
|
||||||
// {
|
|
||||||
// try {
|
|
||||||
// Display.setDisplayMode(windowDisplayMode = new DisplayMode(width, height));
|
|
||||||
// Display.setResizable(resizable);
|
|
||||||
// Display.setVSyncEnabled(true);
|
|
||||||
// Display.setTitle(title);
|
|
||||||
// Display.create();
|
|
||||||
//
|
|
||||||
// fpsMeter = new FpsMeter();
|
|
||||||
//
|
|
||||||
// if (fullscreen) {
|
|
||||||
// switchFullscreen();
|
|
||||||
// Display.update();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// getEventBus().send(new DisplayReadyEvent());
|
|
||||||
//
|
|
||||||
// } catch (final LWJGLException e) {
|
|
||||||
// throw new RuntimeException("Could not initialize screen", e);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Toggle FS if possible
|
|
||||||
// */
|
|
||||||
// public void switchFullscreen()
|
|
||||||
// {
|
|
||||||
// fullscreenSwitchRequested = true;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// private void doSwitchFullscreen()
|
|
||||||
// {
|
|
||||||
// try {
|
|
||||||
//
|
|
||||||
// if (!Display.isFullscreen()) {
|
|
||||||
// Log.f3("Entering fullscreen.");
|
|
||||||
// // save window resize
|
|
||||||
// windowDisplayMode = new DisplayMode(Display.getWidth(), Display.getHeight());
|
|
||||||
//
|
|
||||||
// Display.setDisplayMode(Display.getDesktopDisplayMode());
|
|
||||||
// Display.setFullscreen(true);
|
|
||||||
// Display.update();
|
|
||||||
// } else {
|
|
||||||
// Log.f3("Leaving fullscreen.");
|
|
||||||
// Display.setDisplayMode(windowDisplayMode);
|
|
||||||
// Display.update();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// getEventBus().send(new ViewportChangeEvent(getSize()));
|
|
||||||
//
|
|
||||||
// } catch (final Throwable t) {
|
|
||||||
// Log.e("Failed to toggle fullscreen mode.", t);
|
|
||||||
// try {
|
|
||||||
// Display.setDisplayMode(windowDisplayMode);
|
|
||||||
// Display.update();
|
|
||||||
// } catch (final Throwable t1) {
|
|
||||||
// throw new RuntimeException("Failed to revert failed fullscreen toggle.", t1);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Take screenshot (expensive processing is done on-demand when screenshot
|
|
||||||
// * is processed).
|
|
||||||
// *
|
|
||||||
// * @return screenshot object
|
|
||||||
// */
|
|
||||||
// public static AwtScreenshot prepareScreenshot()
|
|
||||||
// {
|
|
||||||
// glReadBuffer(GL_FRONT);
|
|
||||||
// final int width = Display.getWidth();
|
|
||||||
// final int height = Display.getHeight();
|
|
||||||
// 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;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * @return true if close was requested (i.e. click on cross)
|
|
||||||
// */
|
|
||||||
// public static boolean isCloseRequested()
|
|
||||||
// {
|
|
||||||
// return Display.isCloseRequested();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Get fullscreen state
|
|
||||||
// *
|
|
||||||
// * @return is fullscreen
|
|
||||||
// */
|
|
||||||
// public static boolean isFullscreen()
|
|
||||||
// {
|
|
||||||
// return Display.isFullscreen();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Get screen size. This Vect is final and views at it can safely be made.
|
|
||||||
// *
|
|
||||||
// * @return size
|
|
||||||
// */
|
|
||||||
// public static Vect getSize()
|
|
||||||
// {
|
|
||||||
// return screenSize;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Get screen rect. Static version of getRect().
|
|
||||||
// *
|
|
||||||
// * @return size
|
|
||||||
// */
|
|
||||||
// public static Rect getBounds()
|
|
||||||
// {
|
|
||||||
// return rect;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * @return screen width
|
|
||||||
// */
|
|
||||||
// public static int getWidth()
|
|
||||||
// {
|
|
||||||
// return screenSize.xi();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * @return screen height
|
|
||||||
// */
|
|
||||||
// public static int getHeight()
|
|
||||||
// {
|
|
||||||
// return screenSize.yi();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Start a OpenGL frame
|
|
||||||
// */
|
|
||||||
// public void beginFrame()
|
|
||||||
// {
|
|
||||||
// // handle resize
|
|
||||||
// if (Display.wasResized()) {
|
|
||||||
// getEventBus().send(new ViewportChangeEvent(getSize()));
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if (fullscreenSwitchRequested) {
|
|
||||||
// fullscreenSwitchRequested = false;
|
|
||||||
// doSwitchFullscreen();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// glLoadIdentity();
|
|
||||||
// glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
||||||
// fpsMeter.frame();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * End an OpenGL frame, flip buffers, sync to fps.
|
|
||||||
// */
|
|
||||||
// public void endFrame()
|
|
||||||
// {
|
|
||||||
// Display.update(false); // don't poll input devices
|
|
||||||
// Display.sync(targetFps);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Get screen rect. This Rect is final and views at it can safely be made.
|
|
||||||
// */
|
|
||||||
// @Override
|
|
||||||
// public Rect getRect()
|
|
||||||
// {
|
|
||||||
// return getBounds();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * @return current FPS
|
|
||||||
// */
|
|
||||||
// public long getFps()
|
|
||||||
// {
|
|
||||||
// return fpsMeter.getFPS();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Get screen center. This vect is final and views at it can safely be made.
|
|
||||||
// *
|
|
||||||
// * @return screen center.
|
|
||||||
// */
|
|
||||||
// public static Vect getCenter()
|
|
||||||
// {
|
|
||||||
// return rect.center();
|
|
||||||
// }
|
|
||||||
//}
|
|
@ -1,542 +0,0 @@ |
|||||||
//package junk;
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//import static org.lwjgl.opengl.GL11.*;
|
|
||||||
//
|
|
||||||
//import java.io.IOException;
|
|
||||||
//
|
|
||||||
//import mightypork.gamecore.resources.textures.FilterMode;
|
|
||||||
//import mightypork.gamecore.resources.textures.ITexture;
|
|
||||||
//import mightypork.gamecore.resources.textures.TxQuad;
|
|
||||||
//import mightypork.utils.files.FileUtils;
|
|
||||||
//import mightypork.utils.logging.Log;
|
|
||||||
//import mightypork.utils.math.color.Color;
|
|
||||||
//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.constraints.vect.VectConst;
|
|
||||||
//
|
|
||||||
//import org.lwjgl.opengl.GL11;
|
|
||||||
//import org.newdawn.slick.opengl.Texture;
|
|
||||||
//import org.newdawn.slick.opengl.TextureLoader;
|
|
||||||
//
|
|
||||||
//
|
|
||||||
///**
|
|
||||||
// * Render utilities
|
|
||||||
// *
|
|
||||||
// * @author Ondřej Hruška (MightyPork)
|
|
||||||
// */
|
|
||||||
//@Deprecated
|
|
||||||
//public class Render {
|
|
||||||
//
|
|
||||||
// public static final VectConst AXIS_X = Vect.make(1, 0, 0);
|
|
||||||
// public static final VectConst AXIS_Y = Vect.make(0, 1, 0);
|
|
||||||
// public static final VectConst AXIS_Z = Vect.make(0, 0, 1);
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Bind GL color
|
|
||||||
// *
|
|
||||||
// * @param color Color color
|
|
||||||
// */
|
|
||||||
// public static void setColor(Color color)
|
|
||||||
// {
|
|
||||||
// if (color != null) glColor4d(color.r(), color.g(), color.b(), color.a());
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Bind GL color
|
|
||||||
// *
|
|
||||||
// * @param color Color color
|
|
||||||
// * @param alpha alpha multiplier
|
|
||||||
// */
|
|
||||||
// public static void setColor(Color color, double alpha)
|
|
||||||
// {
|
|
||||||
// if (color != null) glColor4d(color.r(), color.g(), color.b(), color.a() * alpha);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Translate
|
|
||||||
// *
|
|
||||||
// * @param x
|
|
||||||
// * @param y
|
|
||||||
// */
|
|
||||||
// public static void translate(double x, double y)
|
|
||||||
// {
|
|
||||||
// glTranslated(x, y, 0);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Translate
|
|
||||||
// *
|
|
||||||
// * @param x
|
|
||||||
// * @param y
|
|
||||||
// * @param z
|
|
||||||
// */
|
|
||||||
// public static void translate(double x, double y, double z)
|
|
||||||
// {
|
|
||||||
// glTranslated(x, y, z);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Translate with coord
|
|
||||||
// *
|
|
||||||
// * @param coord coord
|
|
||||||
// */
|
|
||||||
// public static void translate(Vect coord)
|
|
||||||
// {
|
|
||||||
// glTranslated(coord.x(), coord.y(), coord.z());
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Translate with coord, discard Z
|
|
||||||
// *
|
|
||||||
// * @param coord coord
|
|
||||||
// */
|
|
||||||
// public static void translateXY(Vect coord)
|
|
||||||
// {
|
|
||||||
// glTranslated(coord.x(), coord.y(), 0);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Scale
|
|
||||||
// *
|
|
||||||
// * @param x
|
|
||||||
// * @param y
|
|
||||||
// */
|
|
||||||
// public static void scale(double x, double y)
|
|
||||||
// {
|
|
||||||
// glScaled(x, y, 0);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Scale
|
|
||||||
// *
|
|
||||||
// * @param x
|
|
||||||
// * @param y
|
|
||||||
// * @param z
|
|
||||||
// */
|
|
||||||
// public static void scale(double x, double y, double z)
|
|
||||||
// {
|
|
||||||
// glScaled(x, y, z);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Scale
|
|
||||||
// *
|
|
||||||
// * @param factor vector of scaling factors
|
|
||||||
// */
|
|
||||||
// public static void scale(Vect factor)
|
|
||||||
// {
|
|
||||||
// glScaled(factor.x(), factor.y(), factor.z());
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Scale by X factor
|
|
||||||
// *
|
|
||||||
// * @param factor scaling factor
|
|
||||||
// */
|
|
||||||
// public static void scaleXY(double factor)
|
|
||||||
// {
|
|
||||||
// glScaled(factor, factor, 1);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Scale by X factor
|
|
||||||
// *
|
|
||||||
// * @param factor scaling factor
|
|
||||||
// */
|
|
||||||
// public static void scaleX(double factor)
|
|
||||||
// {
|
|
||||||
// glScaled(factor, 1, 1);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Scale by Y factor
|
|
||||||
// *
|
|
||||||
// * @param factor scaling factor
|
|
||||||
// */
|
|
||||||
// public static void scaleY(double factor)
|
|
||||||
// {
|
|
||||||
// glScaled(1, factor, 1);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Scale by Z factor
|
|
||||||
// *
|
|
||||||
// * @param factor scaling factor
|
|
||||||
// */
|
|
||||||
// public static void scaleZ(double factor)
|
|
||||||
// {
|
|
||||||
// glScaled(1, 1, factor);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Rotate around X axis
|
|
||||||
// *
|
|
||||||
// * @param angle deg
|
|
||||||
// */
|
|
||||||
// public static void rotateX(double angle)
|
|
||||||
// {
|
|
||||||
// rotate(angle, AXIS_X);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Rotate around Y axis
|
|
||||||
// *
|
|
||||||
// * @param angle deg
|
|
||||||
// */
|
|
||||||
// public static void rotateY(double angle)
|
|
||||||
// {
|
|
||||||
// rotate(angle, AXIS_Y);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Rotate around Z axis
|
|
||||||
// *
|
|
||||||
// * @param angle deg
|
|
||||||
// */
|
|
||||||
// public static void rotateZ(double angle)
|
|
||||||
// {
|
|
||||||
// rotate(angle, AXIS_Z);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Rotate
|
|
||||||
// *
|
|
||||||
// * @param angle rotate angle
|
|
||||||
// * @param axis rotation axis
|
|
||||||
// */
|
|
||||||
// public static void rotate(double angle, Vect axis)
|
|
||||||
// {
|
|
||||||
// final Vect vec = axis.norm(1);
|
|
||||||
// glRotated(angle, vec.x(), vec.y(), vec.z());
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// private static int pushed = 0;
|
|
||||||
// /** Can be used to avoid texture binding and glBegin/glEnd in textured quads */
|
|
||||||
// public static boolean batchTexturedQuadMode;
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Store GL state
|
|
||||||
// */
|
|
||||||
// public static void pushState()
|
|
||||||
// {
|
|
||||||
// pushed++;
|
|
||||||
//
|
|
||||||
// if (pushed >= 100) {
|
|
||||||
// Log.w("Suspicious number of state pushes: " + pushed);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS);
|
|
||||||
// GL11.glPushClientAttrib(GL11.GL_ALL_CLIENT_ATTRIB_BITS);
|
|
||||||
// GL11.glMatrixMode(GL11.GL_MODELVIEW);
|
|
||||||
// GL11.glPushMatrix();
|
|
||||||
// GL11.glMatrixMode(GL11.GL_PROJECTION);
|
|
||||||
// GL11.glPushMatrix();
|
|
||||||
// GL11.glMatrixMode(GL11.GL_MODELVIEW);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Restore Gl state
|
|
||||||
// */
|
|
||||||
// public static void popState()
|
|
||||||
// {
|
|
||||||
// if (pushed == 0) {
|
|
||||||
// Log.w("Pop without push.");
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// pushed--;
|
|
||||||
//
|
|
||||||
// GL11.glMatrixMode(GL11.GL_PROJECTION);
|
|
||||||
// GL11.glPopMatrix();
|
|
||||||
// GL11.glMatrixMode(GL11.GL_MODELVIEW);
|
|
||||||
// GL11.glPopMatrix();
|
|
||||||
// GL11.glPopClientAttrib();
|
|
||||||
// GL11.glPopAttrib();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Store matrix
|
|
||||||
// */
|
|
||||||
// public static void pushMatrix()
|
|
||||||
// {
|
|
||||||
// GL11.glPushMatrix();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Restore Gl state
|
|
||||||
// */
|
|
||||||
// public static void popMatrix()
|
|
||||||
// {
|
|
||||||
// GL11.glPopMatrix();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Load texture
|
|
||||||
// *
|
|
||||||
// * @param resourcePath
|
|
||||||
// * @param filtering filtering mode to use while loading.
|
|
||||||
// * @return the loaded texture
|
|
||||||
// */
|
|
||||||
// public synchronized static Texture loadSlickTexture(String resourcePath, FilterMode filtering)
|
|
||||||
// {
|
|
||||||
//
|
|
||||||
// try {
|
|
||||||
//
|
|
||||||
// final String ext = FileUtils.getExtension(resourcePath).toUpperCase();
|
|
||||||
//
|
|
||||||
// final Texture texture = TextureLoader.getTexture(ext, FileUtils.getResource(resourcePath), false, filtering.num);
|
|
||||||
//
|
|
||||||
// if (texture == null) {
|
|
||||||
// Log.w("Texture " + resourcePath + " could not be loaded.");
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return texture;
|
|
||||||
//
|
|
||||||
// } catch (final IOException e) {
|
|
||||||
// Log.e("Loading of texture " + resourcePath + " failed.", e);
|
|
||||||
// throw new RuntimeException("Could not load texture " + resourcePath + ".", e);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Render quad 2D
|
|
||||||
// *
|
|
||||||
// * @param rect rectangle
|
|
||||||
// * @param color draw color
|
|
||||||
// */
|
|
||||||
// public static void quad(Rect rect, Color color)
|
|
||||||
// {
|
|
||||||
// setColor(color);
|
|
||||||
// quad(rect);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Render quad
|
|
||||||
// *
|
|
||||||
// * @param quad the quad to draw (px)
|
|
||||||
// */
|
|
||||||
// public static void quad(Rect quad)
|
|
||||||
// {
|
|
||||||
// final RectDigest q = quad.digest();
|
|
||||||
//
|
|
||||||
// // draw with color
|
|
||||||
//
|
|
||||||
// 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();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Draw quad with horizontal gradient
|
|
||||||
// *
|
|
||||||
// * @param quad drawn quad bounds
|
|
||||||
// * @param color1 left color
|
|
||||||
// * @param color2 right color
|
|
||||||
// */
|
|
||||||
// public static void quadGradH(Rect quad, Color color1, Color color2)
|
|
||||||
// {
|
|
||||||
// quadColor(quad, color1, color2, color2, color1);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// public static void quadColor(Rect quad, Color color)
|
|
||||||
// {
|
|
||||||
// quadColor(quad, color, color, color, color);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Draw quad with coloured vertices.
|
|
||||||
// *
|
|
||||||
// * @param quad drawn quad bounds
|
|
||||||
// * @param colorHMinVMin
|
|
||||||
// * @param colorHMaxVMin
|
|
||||||
// * @param colorHMaxVMax
|
|
||||||
// * @param colorHMinVMax
|
|
||||||
// */
|
|
||||||
// public static void quadColor(Rect quad, Color colorHMinVMin, Color colorHMaxVMin, Color colorHMaxVMax, Color colorHMinVMax)
|
|
||||||
// {
|
|
||||||
// final RectDigest r = quad.digest();
|
|
||||||
//
|
|
||||||
// // draw with color
|
|
||||||
//
|
|
||||||
// glDisable(GL_TEXTURE_2D);
|
|
||||||
//
|
|
||||||
// glBegin(GL_QUADS);
|
|
||||||
// setColor(colorHMinVMax);
|
|
||||||
// glVertex2d(r.left, r.bottom);
|
|
||||||
//
|
|
||||||
// setColor(colorHMaxVMax);
|
|
||||||
// glVertex2d(r.right, r.bottom);
|
|
||||||
//
|
|
||||||
// setColor(colorHMaxVMin);
|
|
||||||
// glVertex2d(r.right, r.top);
|
|
||||||
//
|
|
||||||
// setColor(colorHMinVMin);
|
|
||||||
// glVertex2d(r.left, r.top);
|
|
||||||
// glEnd();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Draw quad with vertical gradient
|
|
||||||
// *
|
|
||||||
// * @param quad drawn quad bounds
|
|
||||||
// * @param color1 top color
|
|
||||||
// * @param color2 bottom color
|
|
||||||
// */
|
|
||||||
// public static void quadGradV(Rect quad, Color color1, Color color2)
|
|
||||||
// {
|
|
||||||
// quadColor(quad, color1, color1, color2, color2);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Render textured rect
|
|
||||||
// *
|
|
||||||
// * @param quad rectangle (px)
|
|
||||||
// * @param txquad texture quad
|
|
||||||
// */
|
|
||||||
// public static void quadTextured(Rect quad, TxQuad txquad)
|
|
||||||
// {
|
|
||||||
// quadTextured(quad, txquad, RGB.WHITE);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Render textured rect
|
|
||||||
// *
|
|
||||||
// * @param quad rectangle (px)
|
|
||||||
// * @param txquad texture instance
|
|
||||||
// * @param tint color tint
|
|
||||||
// */
|
|
||||||
// public static void quadTextured(Rect quad, TxQuad txquad, Color tint)
|
|
||||||
// {
|
|
||||||
// if (!batchTexturedQuadMode) {
|
|
||||||
// glEnable(GL_TEXTURE_2D);
|
|
||||||
// txquad.tx.bind();
|
|
||||||
// glBegin(GL_QUADS);
|
|
||||||
// setColor(tint);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// final RectDigest q = quad.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 = txquad.tx.getWidth01();
|
|
||||||
// final double h = txquad.tx.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);
|
|
||||||
//
|
|
||||||
// if (!batchTexturedQuadMode) glEnd();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Setup Ortho projection for 2D graphics
|
|
||||||
// *
|
|
||||||
// * @param size viewport size (screen size)
|
|
||||||
// */
|
|
||||||
// public static void setupOrtho(Vect size)
|
|
||||||
// {
|
|
||||||
// // fix projection for changed size
|
|
||||||
// glMatrixMode(GL_PROJECTION);
|
|
||||||
// glLoadIdentity();
|
|
||||||
// glViewport(0, 0, size.xi(), size.yi());
|
|
||||||
// glOrtho(0, size.xi(), size.yi(), 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);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// public static void enterBatchTexturedQuadMode(ITexture texture)
|
|
||||||
// {
|
|
||||||
// texture.bind();
|
|
||||||
// glBegin(GL11.GL_QUADS);
|
|
||||||
// batchTexturedQuadMode = true;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// public static void leaveBatchTexturedQuadMode()
|
|
||||||
// {
|
|
||||||
// glEnd();
|
|
||||||
// batchTexturedQuadMode = false;
|
|
||||||
// }
|
|
||||||
//}
|
|
@ -1,261 +0,0 @@ |
|||||||
package junk; |
|
||||||
|
|
||||||
|
|
||||||
//package mightypork.gamecore.resources.audio;
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//import java.nio.FloatBuffer;
|
|
||||||
//import java.util.ArrayList;
|
|
||||||
//import java.util.List;
|
|
||||||
//
|
|
||||||
//import mightypork.gamecore.backend.lwjgl.SlickAudio;
|
|
||||||
//import mightypork.gamecore.core.modules.App;
|
|
||||||
//import mightypork.gamecore.resources.ResourceLoadRequest;
|
|
||||||
//import mightypork.gamecore.resources.audio.players.EffectPlayer;
|
|
||||||
//import mightypork.gamecore.resources.audio.players.LoopPlayer;
|
|
||||||
//import mightypork.gamecore.util.BufferHelper;
|
|
||||||
//import mightypork.utils.eventbus.clients.BusNode;
|
|
||||||
//import mightypork.utils.interfaces.Destroyable;
|
|
||||||
//import mightypork.utils.interfaces.Updateable;
|
|
||||||
//import mightypork.utils.logging.Log;
|
|
||||||
//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;
|
|
||||||
//
|
|
||||||
//
|
|
||||||
///**
|
|
||||||
// * Sound system class (only one instance should be made per application)
|
|
||||||
// *
|
|
||||||
// * @author Ondřej Hruška (MightyPork)
|
|
||||||
// */
|
|
||||||
//@Deprecated
|
|
||||||
//public class SoundSystem extends BusNode implements Updateable, Destroyable {
|
|
||||||
//
|
|
||||||
// private static final Vect INITIAL_LISTENER_POS = Vect.ZERO;
|
|
||||||
// private static final int MAX_SOURCES = 256;
|
|
||||||
//
|
|
||||||
// private static VectVar listener = Vect.makeVar();
|
|
||||||
// private static boolean soundSystemInited = false;
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Set listener pos
|
|
||||||
// *
|
|
||||||
// * @param pos
|
|
||||||
// */
|
|
||||||
// public static void setListener(Vect pos)
|
|
||||||
// {
|
|
||||||
// listener.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);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * @return listener coordinate
|
|
||||||
// */
|
|
||||||
// public static Vect getListener()
|
|
||||||
// {
|
|
||||||
// return listener;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // -- instance --
|
|
||||||
//
|
|
||||||
// private final Volume masterVolume = new Volume(1D);
|
|
||||||
// private final Volume effectsVolume = new JointVolume(masterVolume);
|
|
||||||
// private final Volume loopsVolume = new JointVolume(masterVolume);
|
|
||||||
//
|
|
||||||
// private final List<LoopPlayer> loopPlayers = new ArrayList<>();
|
|
||||||
// private final List<DeferredAudio> resources = new ArrayList<>();
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * @param busAccess app access
|
|
||||||
// */
|
|
||||||
// public SoundSystem() {
|
|
||||||
//
|
|
||||||
// if (!soundSystemInited) {
|
|
||||||
// soundSystemInited = true;
|
|
||||||
//
|
|
||||||
// try {
|
|
||||||
// SoundStore.get().setMaxSources(MAX_SOURCES);
|
|
||||||
// SoundStore.get().init();
|
|
||||||
// setListener(INITIAL_LISTENER_POS);
|
|
||||||
//
|
|
||||||
// App.bus().send(new AudioReadyEvent());
|
|
||||||
// } catch (final Throwable t) {
|
|
||||||
// Log.e("Error initializing sound system.", t);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// public void destroy()
|
|
||||||
// {
|
|
||||||
// for (final DeferredAudio r : resources) {
|
|
||||||
// r.destroy();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// SoundStore.get().clear();
|
|
||||||
// AL.destroy();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// public void update(double delta)
|
|
||||||
// {
|
|
||||||
// for (final Updateable lp : loopPlayers) {
|
|
||||||
// lp.update(delta);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Create effect resource
|
|
||||||
// *
|
|
||||||
// * @param resource resource path
|
|
||||||
// * @param pitch default pitch (1 = unchanged)
|
|
||||||
// * @param gain default gain (0-1)
|
|
||||||
// * @return player
|
|
||||||
// */
|
|
||||||
// public EffectPlayer createEffect(String resource, double pitch, double gain)
|
|
||||||
// {
|
|
||||||
// return new EffectPlayer(createResource(resource), pitch, gain, effectsVolume);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Register loop resource (music / effect loop)
|
|
||||||
// *
|
|
||||||
// * @param resource resource path
|
|
||||||
// * @param pitch default pitch (1 = unchanged)
|
|
||||||
// * @param gain default gain (0-1)
|
|
||||||
// * @param fadeIn default time for fadeIn
|
|
||||||
// * @param fadeOut default time for fadeOut
|
|
||||||
// * @return player
|
|
||||||
// */
|
|
||||||
// public LoopPlayer createLoop(String resource, double pitch, double gain, double fadeIn, double fadeOut)
|
|
||||||
// {
|
|
||||||
// final LoopPlayer p = new LoopPlayer(createResource(resource), pitch, gain, loopsVolume);
|
|
||||||
// p.setFadeTimes(fadeIn, fadeOut);
|
|
||||||
// loopPlayers.add(p);
|
|
||||||
// return p;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Create {@link DeferredAudio} for a resource
|
|
||||||
// *
|
|
||||||
// * @param res a resource name
|
|
||||||
// * @return the resource
|
|
||||||
// * @throws IllegalArgumentException if resource is already registered
|
|
||||||
// */
|
|
||||||
// private DeferredAudio createResource(String res)
|
|
||||||
// {
|
|
||||||
// final DeferredAudio a = new SlickAudio(res);
|
|
||||||
// App.bus().send(new ResourceLoadRequest(a));
|
|
||||||
// resources.add(a);
|
|
||||||
// return a;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Fade out all loops (ie. for screen transitions)
|
|
||||||
// */
|
|
||||||
// public void fadeOutAllLoops()
|
|
||||||
// {
|
|
||||||
// for (final LoopPlayer p : loopPlayers) {
|
|
||||||
// p.fadeOut();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Pause all loops (leave volume unchanged)
|
|
||||||
// */
|
|
||||||
// public void pauseAllLoops()
|
|
||||||
// {
|
|
||||||
// for (final LoopPlayer p : loopPlayers) {
|
|
||||||
// p.pause();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Set level of master volume
|
|
||||||
// *
|
|
||||||
// * @param d level
|
|
||||||
// */
|
|
||||||
// public void setMasterVolume(double d)
|
|
||||||
// {
|
|
||||||
// masterVolume.set(d);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Set level of effects volume
|
|
||||||
// *
|
|
||||||
// * @param d level
|
|
||||||
// */
|
|
||||||
// public void setEffectsVolume(double d)
|
|
||||||
// {
|
|
||||||
// effectsVolume.set(d);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Set level of music volume
|
|
||||||
// *
|
|
||||||
// * @param d level
|
|
||||||
// */
|
|
||||||
// public void setMusicVolume(double d)
|
|
||||||
// {
|
|
||||||
// loopsVolume.set(d);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Get level of master volume
|
|
||||||
// *
|
|
||||||
// * @return level
|
|
||||||
// */
|
|
||||||
// public double getMasterVolume()
|
|
||||||
// {
|
|
||||||
// return masterVolume.get();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Get level of effects volume
|
|
||||||
// *
|
|
||||||
// * @return level
|
|
||||||
// */
|
|
||||||
// public double getEffectsVolume()
|
|
||||||
// {
|
|
||||||
// return effectsVolume.get();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Get level of music volume
|
|
||||||
// *
|
|
||||||
// * @return level
|
|
||||||
// */
|
|
||||||
// public double getMusicVolume()
|
|
||||||
// {
|
|
||||||
// return loopsVolume.get();
|
|
||||||
// }
|
|
||||||
//}
|
|
@ -1,220 +0,0 @@ |
|||||||
package mightypork.gamecore.audio; |
|
||||||
|
|
||||||
|
|
||||||
import java.util.ArrayList; |
|
||||||
import java.util.List; |
|
||||||
|
|
||||||
import mightypork.gamecore.audio.players.EffectPlayer; |
|
||||||
import mightypork.gamecore.audio.players.LoopPlayer; |
|
||||||
import mightypork.gamecore.core.App; |
|
||||||
import mightypork.gamecore.core.BackendModule; |
|
||||||
import mightypork.gamecore.resources.loading.ResourceLoadRequest; |
|
||||||
import mightypork.utils.interfaces.Updateable; |
|
||||||
import mightypork.utils.math.constraints.vect.Vect; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Abstract audio module. |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public abstract class AudioModule extends BackendModule implements Updateable { |
|
||||||
|
|
||||||
/** |
|
||||||
* Set listener position |
|
||||||
* |
|
||||||
* @param pos listener position |
|
||||||
*/ |
|
||||||
public abstract void setListenerPos(Vect pos); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Get current listener position |
|
||||||
* |
|
||||||
* @return listener position |
|
||||||
*/ |
|
||||||
public abstract Vect getListenerPos(); |
|
||||||
|
|
||||||
// -- instance --
|
|
||||||
|
|
||||||
private final Volume masterVolume = new Volume(1D); |
|
||||||
private final Volume effectsVolume = new JointVolume(masterVolume); |
|
||||||
private final Volume loopsVolume = new JointVolume(masterVolume); |
|
||||||
|
|
||||||
private final List<LoopPlayer> loopPlayers = new ArrayList<>(); |
|
||||||
private final List<DeferredAudio> resources = new ArrayList<>(); |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void destroy() |
|
||||||
{ |
|
||||||
for (final DeferredAudio r : resources) { |
|
||||||
r.destroy(); |
|
||||||
} |
|
||||||
|
|
||||||
deinitSoundSystem(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Deinitialize the soud system, release resources etc.<br> |
|
||||||
* Audio resources are already destroyed. |
|
||||||
*/ |
|
||||||
protected abstract void deinitSoundSystem(); |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void update(double delta) |
|
||||||
{ |
|
||||||
for (final Updateable lp : loopPlayers) { |
|
||||||
lp.update(delta); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Create effect resource |
|
||||||
* |
|
||||||
* @param resource resource path |
|
||||||
* @param pitch default pitch (1 = unchanged) |
|
||||||
* @param gain default gain (0-1) |
|
||||||
* @return player |
|
||||||
*/ |
|
||||||
public EffectPlayer createEffect(String resource, double pitch, double gain) |
|
||||||
{ |
|
||||||
return new EffectPlayer(createResource(resource), pitch, gain, effectsVolume); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Register loop resource (music / effect loop) |
|
||||||
* |
|
||||||
* @param resource resource path |
|
||||||
* @param pitch default pitch (1 = unchanged) |
|
||||||
* @param gain default gain (0-1) |
|
||||||
* @param fadeIn default time for fadeIn |
|
||||||
* @param fadeOut default time for fadeOut |
|
||||||
* @return player |
|
||||||
*/ |
|
||||||
public LoopPlayer createLoop(String resource, double pitch, double gain, double fadeIn, double fadeOut) |
|
||||||
{ |
|
||||||
final LoopPlayer p = new LoopPlayer(createResource(resource), pitch, gain, loopsVolume); |
|
||||||
p.setFadeTimes(fadeIn, fadeOut); |
|
||||||
loopPlayers.add(p); |
|
||||||
return p; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Create {@link DeferredAudio} for a resource, request deferred load and |
|
||||||
* add to the resources list. |
|
||||||
* |
|
||||||
* @param res a resource name |
|
||||||
* @return the resource |
|
||||||
* @throws IllegalArgumentException if resource is already registered |
|
||||||
*/ |
|
||||||
protected DeferredAudio createResource(String res) |
|
||||||
{ |
|
||||||
final DeferredAudio a = doCreateResource(res); |
|
||||||
App.bus().send(new ResourceLoadRequest(a)); |
|
||||||
resources.add(a); |
|
||||||
return a; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Create a backend-specific deferred audio resource |
|
||||||
* |
|
||||||
* @param res resource path |
|
||||||
* @return Deferred Audio |
|
||||||
*/ |
|
||||||
protected abstract DeferredAudio doCreateResource(String res); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Fade out all loops (= fade out the currently playing loops) |
|
||||||
*/ |
|
||||||
public void fadeOutAllLoops() |
|
||||||
{ |
|
||||||
for (final LoopPlayer p : loopPlayers) { |
|
||||||
p.fadeOut(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Pause all loops (leave volume unchanged) |
|
||||||
*/ |
|
||||||
public void pauseAllLoops() |
|
||||||
{ |
|
||||||
for (final LoopPlayer p : loopPlayers) { |
|
||||||
p.pause(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Set level of master volume (volume multiplier) |
|
||||||
* |
|
||||||
* @param volume level (0..1) |
|
||||||
*/ |
|
||||||
public void setMasterVolume(double volume) |
|
||||||
{ |
|
||||||
masterVolume.set(volume); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Set level of effects volume (volume multiplier) |
|
||||||
* |
|
||||||
* @param volume level (0..1) |
|
||||||
*/ |
|
||||||
public void setEffectsVolume(double volume) |
|
||||||
{ |
|
||||||
effectsVolume.set(volume); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Set level of loops volume (volume multiplier) |
|
||||||
* |
|
||||||
* @param volume level (0..1) |
|
||||||
*/ |
|
||||||
public void setLoopsVolume(double volume) |
|
||||||
{ |
|
||||||
loopsVolume.set(volume); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Get level of master volume (volume multiplier) |
|
||||||
* |
|
||||||
* @return level (0..1) |
|
||||||
*/ |
|
||||||
public double getMasterVolume() |
|
||||||
{ |
|
||||||
return masterVolume.get(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Get level of effects volume (volume multiplier) |
|
||||||
* |
|
||||||
* @return level (0..1) |
|
||||||
*/ |
|
||||||
public double getEffectsVolume() |
|
||||||
{ |
|
||||||
return effectsVolume.get(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Get level of loops volume (volume multiplier) |
|
||||||
* |
|
||||||
* @return level (0..1) |
|
||||||
*/ |
|
||||||
public double getLoopsVolume() |
|
||||||
{ |
|
||||||
return loopsVolume.get(); |
|
||||||
} |
|
||||||
} |
|
@ -1,47 +0,0 @@ |
|||||||
package mightypork.gamecore.audio; |
|
||||||
|
|
||||||
|
|
||||||
import mightypork.gamecore.core.App; |
|
||||||
import mightypork.gamecore.resources.BaseDeferredResource; |
|
||||||
import mightypork.utils.annotations.Alias; |
|
||||||
import mightypork.utils.math.constraints.vect.Vect; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Abstract deferred audio, to be extended in backend. |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
@Alias(name = "Audio") |
|
||||||
public abstract class DeferredAudio extends BaseDeferredResource implements IAudio { |
|
||||||
|
|
||||||
/** |
|
||||||
* Create audio |
|
||||||
* |
|
||||||
* @param resourceName resource to load (when needed) |
|
||||||
*/ |
|
||||||
public DeferredAudio(String resourceName) { |
|
||||||
super(resourceName); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void play(double pitch, double gain, boolean loop) |
|
||||||
{ |
|
||||||
play(pitch, gain, loop, App.audio().getListenerPos()); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void play(double pitch, double gain, boolean loop, double x, double y) |
|
||||||
{ |
|
||||||
play(pitch, gain, loop, x, y, App.audio().getListenerPos().z()); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void play(double pitch, double gain, boolean loop, Vect pos) |
|
||||||
{ |
|
||||||
play(pitch, gain, loop, pos.x(), pos.y(), pos.z()); |
|
||||||
} |
|
||||||
} |
|
@ -1,99 +0,0 @@ |
|||||||
package mightypork.gamecore.audio; |
|
||||||
|
|
||||||
|
|
||||||
import mightypork.utils.interfaces.Destroyable; |
|
||||||
import mightypork.utils.math.constraints.vect.Vect; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Audio resource interface (backend independent) |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public interface IAudio extends Destroyable { |
|
||||||
|
|
||||||
/** |
|
||||||
* Pause loop (remember position and stop playing) - if was looping |
|
||||||
*/ |
|
||||||
void pauseLoop(); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Resume loop (if was paused) |
|
||||||
*/ |
|
||||||
void resumeLoop(); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Adjust gain for the currently playing effect (can be used for fading |
|
||||||
* music) |
|
||||||
* |
|
||||||
* @param gain gain to set 0..1 |
|
||||||
*/ |
|
||||||
void adjustGain(double gain); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Stop audio playback |
|
||||||
*/ |
|
||||||
void stop(); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* @return true if the audio is playing |
|
||||||
*/ |
|
||||||
boolean isPlaying(); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* @return trie if the audio is paused |
|
||||||
*/ |
|
||||||
boolean isPaused(); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Play as sound effect at listener position |
|
||||||
* |
|
||||||
* @param pitch pitch (1 = default) |
|
||||||
* @param gain gain (0-1) |
|
||||||
* @param loop looping |
|
||||||
*/ |
|
||||||
void play(double pitch, double gain, boolean loop); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Play as sound effect at given X-Y position |
|
||||||
* |
|
||||||
* @param pitch pitch (1 = default) |
|
||||||
* @param gain gain (0-1) |
|
||||||
* @param loop looping |
|
||||||
* @param x |
|
||||||
* @param y |
|
||||||
*/ |
|
||||||
void play(double pitch, double gain, boolean loop, double x, double y); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Play as sound effect at given position |
|
||||||
* |
|
||||||
* @param pitch pitch (1 = default) |
|
||||||
* @param gain gain (0-1) |
|
||||||
* @param loop looping |
|
||||||
* @param x |
|
||||||
* @param y |
|
||||||
* @param z |
|
||||||
*/ |
|
||||||
void play(double pitch, double gain, boolean loop, double x, double y, double z); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Play as sound effect at given position |
|
||||||
* |
|
||||||
* @param pitch pitch (1 = default) |
|
||||||
* @param gain gain (0-1) |
|
||||||
* @param loop looping |
|
||||||
* @param pos coord |
|
||||||
*/ |
|
||||||
void play(double pitch, double gain, boolean loop, Vect pos); |
|
||||||
|
|
||||||
} |
|
@ -1,51 +0,0 @@ |
|||||||
package mightypork.gamecore.audio; |
|
||||||
|
|
||||||
|
|
||||||
import mightypork.utils.math.Calc; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Volume combined of multiple volumes, combining them (multiplication). |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public class JointVolume extends Volume { |
|
||||||
|
|
||||||
private final Volume[] volumes; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Create joint volume with master gain of 1 |
|
||||||
* |
|
||||||
* @param volumes individual volumes to join |
|
||||||
*/ |
|
||||||
@SafeVarargs |
|
||||||
public JointVolume(Volume... volumes) { |
|
||||||
super(1D); |
|
||||||
this.volumes = volumes; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Get combined gain (multiplied) |
|
||||||
*/ |
|
||||||
@Override |
|
||||||
public Double get() |
|
||||||
{ |
|
||||||
double d = super.get(); |
|
||||||
for (final Volume v : volumes) |
|
||||||
d *= v.get(); |
|
||||||
|
|
||||||
return Calc.clamp(d, 0, 1); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Set master gain |
|
||||||
*/ |
|
||||||
@Override |
|
||||||
public void set(Double o) |
|
||||||
{ |
|
||||||
super.set(o); |
|
||||||
} |
|
||||||
} |
|
@ -1,83 +0,0 @@ |
|||||||
package mightypork.gamecore.audio; |
|
||||||
|
|
||||||
|
|
||||||
import java.util.HashMap; |
|
||||||
import java.util.Map; |
|
||||||
|
|
||||||
import mightypork.gamecore.audio.players.EffectPlayer; |
|
||||||
import mightypork.gamecore.audio.players.LoopPlayer; |
|
||||||
import mightypork.gamecore.core.App; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Audio resource storage |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public class SoundRegistry { |
|
||||||
|
|
||||||
private final Map<String, EffectPlayer> effects = new HashMap<>(); |
|
||||||
private final Map<String, LoopPlayer> loops = new HashMap<>(); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Register effect resource |
|
||||||
* |
|
||||||
* @param key sound key |
|
||||||
* @param resource resource path |
|
||||||
* @param pitch default pitch (1 = unchanged) |
|
||||||
* @param gain default gain (0-1) |
|
||||||
*/ |
|
||||||
public void addEffect(String key, String resource, double pitch, double gain) |
|
||||||
{ |
|
||||||
effects.put(key, App.audio().createEffect(resource, pitch, gain)); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Register loop resource (music / effect loop) |
|
||||||
* |
|
||||||
* @param key sound key |
|
||||||
* @param resource resource path |
|
||||||
* @param pitch default pitch (1 = unchanged) |
|
||||||
* @param gain default gain (0-1) |
|
||||||
* @param fadeIn default time for fadeIn |
|
||||||
* @param fadeOut default time for fadeOut |
|
||||||
*/ |
|
||||||
public void addLoop(String key, String resource, double pitch, double gain, double fadeIn, double fadeOut) |
|
||||||
{ |
|
||||||
loops.put(key, App.audio().createLoop(resource, pitch, gain, fadeIn, fadeOut)); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Get a loop player for key |
|
||||||
* |
|
||||||
* @param key sound key |
|
||||||
* @return loop player |
|
||||||
*/ |
|
||||||
public LoopPlayer getLoop(String key) |
|
||||||
{ |
|
||||||
final LoopPlayer p = loops.get(key); |
|
||||||
if (p == null) { |
|
||||||
throw new RuntimeException("Unknown sound loop \"" + key + "\"."); |
|
||||||
} |
|
||||||
return p; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Get a effect player for key |
|
||||||
* |
|
||||||
* @param key sound key |
|
||||||
* @return effect player |
|
||||||
*/ |
|
||||||
public EffectPlayer getEffect(String key) |
|
||||||
{ |
|
||||||
final EffectPlayer p = effects.get(key); |
|
||||||
if (p == null) { |
|
||||||
throw new RuntimeException("Unknown sound effect \"" + key + "\"."); |
|
||||||
} |
|
||||||
return p; |
|
||||||
} |
|
||||||
} |
|
@ -1,29 +0,0 @@ |
|||||||
package mightypork.gamecore.audio; |
|
||||||
|
|
||||||
|
|
||||||
import mightypork.utils.math.Calc; |
|
||||||
import mightypork.utils.struct.Mutable; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Mutable volume 0-1 |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public class Volume extends Mutable<Double> { |
|
||||||
|
|
||||||
/** |
|
||||||
* @param d initial value |
|
||||||
*/ |
|
||||||
public Volume(Double d) { |
|
||||||
super(d); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void set(Double d) |
|
||||||
{ |
|
||||||
super.set(Calc.clamp(d, 0, 1)); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -1,105 +0,0 @@ |
|||||||
package mightypork.gamecore.audio.players; |
|
||||||
|
|
||||||
|
|
||||||
import mightypork.gamecore.audio.DeferredAudio; |
|
||||||
import mightypork.gamecore.audio.Volume; |
|
||||||
import mightypork.utils.interfaces.Destroyable; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Basic abstract player |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public abstract class BaseAudioPlayer implements Destroyable { |
|
||||||
|
|
||||||
/** the track */ |
|
||||||
private final DeferredAudio audio; |
|
||||||
|
|
||||||
/** base gain for sfx */ |
|
||||||
private final double baseGain; |
|
||||||
|
|
||||||
/** base pitch for sfx */ |
|
||||||
private final double basePitch; |
|
||||||
|
|
||||||
/** dedicated volume control */ |
|
||||||
private final Volume gainMultiplier; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* @param track audio resource |
|
||||||
* @param basePitch base pitch (pitch multiplier) |
|
||||||
* @param baseGain base gain (volume multiplier) |
|
||||||
* @param volume colume control |
|
||||||
*/ |
|
||||||
public BaseAudioPlayer(DeferredAudio track, double basePitch, double baseGain, Volume volume) { |
|
||||||
this.audio = track; |
|
||||||
|
|
||||||
this.baseGain = baseGain; |
|
||||||
this.basePitch = basePitch; |
|
||||||
|
|
||||||
if (volume == null) volume = new Volume(1D); |
|
||||||
|
|
||||||
this.gainMultiplier = volume; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void destroy() |
|
||||||
{ |
|
||||||
audio.destroy(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* @return audio resource |
|
||||||
*/ |
|
||||||
protected DeferredAudio getAudio() |
|
||||||
{ |
|
||||||
return audio; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Get play gain, computed based on volume and given multiplier |
|
||||||
* |
|
||||||
* @param multiplier extra volume adjustment |
|
||||||
* @return computed gain |
|
||||||
*/ |
|
||||||
protected double computeGain(double multiplier) |
|
||||||
{ |
|
||||||
return baseGain * gainMultiplier.get() * multiplier; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Get pitch |
|
||||||
* |
|
||||||
* @param multiplier pitch adjustment |
|
||||||
* @return computed pitch |
|
||||||
*/ |
|
||||||
protected double computePitch(double multiplier) |
|
||||||
{ |
|
||||||
return basePitch * multiplier; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Get if audio is valid |
|
||||||
* |
|
||||||
* @return is valid |
|
||||||
*/ |
|
||||||
protected boolean hasAudio() |
|
||||||
{ |
|
||||||
return (audio != null); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* force load the resource |
|
||||||
*/ |
|
||||||
public void load() |
|
||||||
{ |
|
||||||
if (hasAudio()) audio.load(); |
|
||||||
} |
|
||||||
} |
|
@ -1,66 +0,0 @@ |
|||||||
package mightypork.gamecore.audio.players; |
|
||||||
|
|
||||||
|
|
||||||
import mightypork.gamecore.audio.DeferredAudio; |
|
||||||
import mightypork.gamecore.audio.Volume; |
|
||||||
import mightypork.utils.math.constraints.vect.Vect; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Player for one-off effects |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public class EffectPlayer extends BaseAudioPlayer { |
|
||||||
|
|
||||||
/** |
|
||||||
* @param track audio resource |
|
||||||
* @param basePitch base pitch (pitch multiplier) |
|
||||||
* @param baseGain base gain (volume multiplier) |
|
||||||
* @param volume volume control |
|
||||||
*/ |
|
||||||
public EffectPlayer(DeferredAudio track, double basePitch, double baseGain, Volume volume) { |
|
||||||
super(track, (float) basePitch, (float) baseGain, volume); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Play at listener |
|
||||||
* |
|
||||||
* @param pitch play pitch |
|
||||||
* @param gain play gain |
|
||||||
*/ |
|
||||||
public void play(double pitch, double gain) |
|
||||||
{ |
|
||||||
if (!hasAudio()) return; |
|
||||||
|
|
||||||
getAudio().play(computePitch(pitch), computeGain(gain), false); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Play at listener |
|
||||||
* |
|
||||||
* @param gain play gain |
|
||||||
*/ |
|
||||||
public void play(double gain) |
|
||||||
{ |
|
||||||
play(1, gain); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Play at given position |
|
||||||
* |
|
||||||
* @param pitch play pitch |
|
||||||
* @param gain play gain |
|
||||||
* @param pos play position |
|
||||||
*/ |
|
||||||
public void play(double pitch, double gain, Vect pos) |
|
||||||
{ |
|
||||||
if (!hasAudio()) return; |
|
||||||
|
|
||||||
getAudio().play(computePitch(pitch), computeGain(gain), false, pos); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -1,166 +0,0 @@ |
|||||||
package mightypork.gamecore.audio.players; |
|
||||||
|
|
||||||
|
|
||||||
import mightypork.gamecore.audio.DeferredAudio; |
|
||||||
import mightypork.gamecore.audio.Volume; |
|
||||||
import mightypork.utils.interfaces.Pauseable; |
|
||||||
import mightypork.utils.interfaces.Updateable; |
|
||||||
import mightypork.utils.math.animation.NumAnimated; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Audio loop player (with fading, good for music) |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public class LoopPlayer extends BaseAudioPlayer implements Updateable, Pauseable { |
|
||||||
|
|
||||||
private int sourceID = -1; |
|
||||||
|
|
||||||
/** animator for fade in and fade out */ |
|
||||||
private final NumAnimated fadeAnim = new NumAnimated(0); |
|
||||||
|
|
||||||
private double lastUpdateGain = 0; |
|
||||||
|
|
||||||
/** flag that track is paused */ |
|
||||||
private boolean paused = true; |
|
||||||
|
|
||||||
/** Default fadeIn time */ |
|
||||||
private double inTime = 1; |
|
||||||
|
|
||||||
/** Default fadeOut time */ |
|
||||||
private double outTime = 1; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* @param track audio resource |
|
||||||
* @param basePitch base pitch (pitch multiplier) |
|
||||||
* @param baseGain base gain (volume multiplier) |
|
||||||
* @param volume volume control |
|
||||||
*/ |
|
||||||
public LoopPlayer(DeferredAudio track, double basePitch, double baseGain, Volume volume) { |
|
||||||
super(track, (float) basePitch, (float) baseGain, volume); |
|
||||||
|
|
||||||
paused = true; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Set fading duration (seconds) |
|
||||||
* |
|
||||||
* @param in duration of fade-in |
|
||||||
* @param out duration of fade-out |
|
||||||
*/ |
|
||||||
public void setFadeTimes(double in, double out) |
|
||||||
{ |
|
||||||
inTime = in; |
|
||||||
outTime = out; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
private void initLoop() |
|
||||||
{ |
|
||||||
if (hasAudio() && sourceID == -1) { |
|
||||||
getAudio().play(computePitch(1), computeGain(1), true); |
|
||||||
getAudio().pauseLoop(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void pause() |
|
||||||
{ |
|
||||||
if (!hasAudio() || paused) return; |
|
||||||
|
|
||||||
initLoop(); |
|
||||||
|
|
||||||
getAudio().pauseLoop(); |
|
||||||
paused = true; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public boolean isPaused() |
|
||||||
{ |
|
||||||
return paused; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void resume() |
|
||||||
{ |
|
||||||
if (!hasAudio() || !paused) return; |
|
||||||
|
|
||||||
initLoop(); |
|
||||||
|
|
||||||
paused = false; |
|
||||||
|
|
||||||
getAudio().adjustGain(computeGain(fadeAnim.value())); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void update(double delta) |
|
||||||
{ |
|
||||||
if (!hasAudio() || paused) return; |
|
||||||
|
|
||||||
initLoop(); |
|
||||||
|
|
||||||
fadeAnim.update(delta); |
|
||||||
|
|
||||||
final double gain = computeGain(fadeAnim.value()); |
|
||||||
if (!paused && gain != lastUpdateGain) { |
|
||||||
getAudio().adjustGain(gain); |
|
||||||
lastUpdateGain = gain; |
|
||||||
} |
|
||||||
|
|
||||||
if (gain == 0 && !paused) pause(); // pause on zero volume
|
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Resume if paused, and fade in (pick up from current volume). |
|
||||||
* |
|
||||||
* @param secs |
|
||||||
*/ |
|
||||||
public void fadeIn(double secs) |
|
||||||
{ |
|
||||||
if (!hasAudio()) return; |
|
||||||
|
|
||||||
if (isPaused()) fadeAnim.setTo(0); |
|
||||||
resume(); |
|
||||||
fadeAnim.fadeIn(secs); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Fade out and pause when reached zero volume |
|
||||||
* |
|
||||||
* @param secs fade duration |
|
||||||
*/ |
|
||||||
public void fadeOut(double secs) |
|
||||||
{ |
|
||||||
if (!hasAudio()) return; |
|
||||||
if (isPaused()) return; |
|
||||||
fadeAnim.fadeOut(secs); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Fade in with default duration |
|
||||||
*/ |
|
||||||
public void fadeIn() |
|
||||||
{ |
|
||||||
fadeIn(inTime); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Fade out with default duration |
|
||||||
*/ |
|
||||||
public void fadeOut() |
|
||||||
{ |
|
||||||
fadeOut(outTime); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -1,277 +0,0 @@ |
|||||||
package mightypork.gamecore.core; |
|
||||||
|
|
||||||
|
|
||||||
import java.util.ArrayList; |
|
||||||
import java.util.List; |
|
||||||
|
|
||||||
import mightypork.gamecore.audio.AudioModule; |
|
||||||
import mightypork.gamecore.core.config.Config; |
|
||||||
import mightypork.gamecore.core.events.ShutdownEvent; |
|
||||||
import mightypork.gamecore.graphics.GraphicsModule; |
|
||||||
import mightypork.gamecore.input.InputModule; |
|
||||||
import mightypork.utils.annotations.Stub; |
|
||||||
import mightypork.utils.eventbus.EventBus; |
|
||||||
import mightypork.utils.eventbus.clients.BusNode; |
|
||||||
import mightypork.utils.eventbus.clients.DelegatingList; |
|
||||||
import mightypork.utils.eventbus.events.DestroyEvent; |
|
||||||
import mightypork.utils.logging.Log; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Game base class & static subsystem access |
|
||||||
* |
|
||||||
* @author MightyPork |
|
||||||
*/ |
|
||||||
public class App extends BusNode { |
|
||||||
|
|
||||||
private static App instance; |
|
||||||
|
|
||||||
private final AppBackend backend; |
|
||||||
private final EventBus eventBus = new EventBus(); |
|
||||||
private boolean started = false; |
|
||||||
|
|
||||||
protected final DelegatingList plugins = new DelegatingList(); |
|
||||||
protected final List<InitTask> initializers = new ArrayList<>(); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Create an app with given backend. |
|
||||||
* |
|
||||||
* @param backend |
|
||||||
*/ |
|
||||||
public App(AppBackend backend) { |
|
||||||
if (App.instance != null) { |
|
||||||
throw new IllegalStateException("App already initialized"); |
|
||||||
} |
|
||||||
|
|
||||||
// store current instance in static field
|
|
||||||
App.instance = this; |
|
||||||
|
|
||||||
// join the bus
|
|
||||||
this.eventBus.subscribe(this); |
|
||||||
|
|
||||||
// create plugin registry attached to bus
|
|
||||||
this.eventBus.subscribe(this.plugins); |
|
||||||
|
|
||||||
// initialize and use backend
|
|
||||||
this.backend = backend; |
|
||||||
this.eventBus.subscribe(backend); |
|
||||||
this.backend.bind(this); |
|
||||||
this.backend.initialize(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Add a plugin to the app. Plugins can eg. listen to bus events and react |
|
||||||
* to them. |
|
||||||
* |
|
||||||
* @param plugin the added plugin. |
|
||||||
*/ |
|
||||||
public void addPlugin(AppPlugin plugin) |
|
||||||
{ |
|
||||||
if (started) { |
|
||||||
throw new IllegalStateException("App already started, cannot add plugins."); |
|
||||||
} |
|
||||||
|
|
||||||
// attach to event bus
|
|
||||||
plugins.add(plugin); |
|
||||||
plugin.bind(this); |
|
||||||
plugin.initialize(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Add an initializer to the app. |
|
||||||
* |
|
||||||
* @param initializer |
|
||||||
*/ |
|
||||||
public void addInitTask(InitTask initializer) |
|
||||||
{ |
|
||||||
if (started) { |
|
||||||
throw new IllegalStateException("App already started, cannot add initializers."); |
|
||||||
} |
|
||||||
|
|
||||||
initializers.add(initializer); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Get current backend |
|
||||||
* |
|
||||||
* @return the backend |
|
||||||
*/ |
|
||||||
public AppBackend getBackend() |
|
||||||
{ |
|
||||||
return backend; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Initialize the App and start operating.<br> |
|
||||||
* This method should be called after adding all required initializers and |
|
||||||
* plugins. |
|
||||||
*/ |
|
||||||
public final void start() |
|
||||||
{ |
|
||||||
if (started) { |
|
||||||
throw new IllegalStateException("Already started."); |
|
||||||
} |
|
||||||
started = true; |
|
||||||
|
|
||||||
// pre-init hook, just in case anyone wanted to have one.
|
|
||||||
Log.f2("Calling pre-init hook..."); |
|
||||||
preInit(); |
|
||||||
|
|
||||||
Log.i("=== Starting initialization sequence ==="); |
|
||||||
|
|
||||||
// sort initializers by order.
|
|
||||||
List<InitTask> orderedInitializers = InitTask.inOrder(initializers); |
|
||||||
|
|
||||||
for (InitTask initializer : orderedInitializers) { |
|
||||||
Log.f1("Running init task \"" + initializer.getName() + "\"..."); |
|
||||||
initializer.bind(this); |
|
||||||
initializer.init(); |
|
||||||
initializer.run(); |
|
||||||
} |
|
||||||
|
|
||||||
Log.i("=== Initialization sequence completed ==="); |
|
||||||
|
|
||||||
// user can now start the main loop etc.
|
|
||||||
Log.f2("Calling post-init hook..."); |
|
||||||
postInit(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Hook called before the initialization sequence starts. |
|
||||||
*/ |
|
||||||
@Stub |
|
||||||
protected void preInit() |
|
||||||
{ |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Hook called after the initialization sequence is finished. |
|
||||||
*/ |
|
||||||
@Stub |
|
||||||
protected void postInit() |
|
||||||
{ |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Shut down the running instance.<br> |
|
||||||
* Deinitialize backend modules and terminate the JVM. |
|
||||||
*/ |
|
||||||
public static void shutdown() |
|
||||||
{ |
|
||||||
if (instance != null) { |
|
||||||
Log.i("Dispatching Shutdown event..."); |
|
||||||
|
|
||||||
bus().send(new ShutdownEvent(new Runnable() { |
|
||||||
|
|
||||||
@Override |
|
||||||
public void run() |
|
||||||
{ |
|
||||||
try { |
|
||||||
final EventBus bus = bus(); |
|
||||||
if (bus != null) { |
|
||||||
bus.send(new DestroyEvent()); |
|
||||||
bus.destroy(); |
|
||||||
} |
|
||||||
} catch (final Throwable e) { |
|
||||||
Log.e(e); |
|
||||||
} |
|
||||||
|
|
||||||
Log.i("Shutdown completed."); |
|
||||||
System.exit(0); |
|
||||||
} |
|
||||||
})); |
|
||||||
|
|
||||||
} else { |
|
||||||
Log.w("App is not running."); |
|
||||||
System.exit(0); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Get the currently running App instance. |
|
||||||
* |
|
||||||
* @return app instance |
|
||||||
*/ |
|
||||||
public static App instance() |
|
||||||
{ |
|
||||||
return instance; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Get graphics module from the running app's backend |
|
||||||
* |
|
||||||
* @return graphics module |
|
||||||
*/ |
|
||||||
public static GraphicsModule gfx() |
|
||||||
{ |
|
||||||
return instance.backend.getGraphics(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Get audio module from the running app's backend |
|
||||||
* |
|
||||||
* @return audio module |
|
||||||
*/ |
|
||||||
public static AudioModule audio() |
|
||||||
{ |
|
||||||
return instance.backend.getAudio(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Get input module from the running app's backend |
|
||||||
* |
|
||||||
* @return input module |
|
||||||
*/ |
|
||||||
public static InputModule input() |
|
||||||
{ |
|
||||||
return instance.backend.getInput(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Get event bus instance. |
|
||||||
* |
|
||||||
* @return event bus |
|
||||||
*/ |
|
||||||
public static EventBus bus() |
|
||||||
{ |
|
||||||
return instance.eventBus; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Get the main config, if initialized. |
|
||||||
* |
|
||||||
* @return main config |
|
||||||
* @throws IllegalArgumentException if there is no such config. |
|
||||||
*/ |
|
||||||
public static Config cfg() |
|
||||||
{ |
|
||||||
return cfg("main"); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Get a config by alias. |
|
||||||
* |
|
||||||
* @param alias config alias |
|
||||||
* @return the config |
|
||||||
* @throws IllegalArgumentException if there is no such config. |
|
||||||
*/ |
|
||||||
public static Config cfg(String alias) |
|
||||||
{ |
|
||||||
return Config.forAlias(alias); |
|
||||||
} |
|
||||||
} |
|
@ -1,65 +0,0 @@ |
|||||||
package mightypork.gamecore.core; |
|
||||||
|
|
||||||
|
|
||||||
import mightypork.gamecore.audio.AudioModule; |
|
||||||
import mightypork.gamecore.graphics.GraphicsModule; |
|
||||||
import mightypork.gamecore.input.InputModule; |
|
||||||
import mightypork.utils.eventbus.clients.BusNode; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Application backend interface (set of core modules).<br> |
|
||||||
* The goal of this abstraction is to allow easy migration to different |
|
||||||
* environment with different libraries etc. It should be as simple as using |
|
||||||
* different backend. |
|
||||||
* |
|
||||||
* @author MightyPork |
|
||||||
*/ |
|
||||||
public abstract class AppBackend extends BusNode { |
|
||||||
|
|
||||||
protected App app; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Assign an app instance. |
|
||||||
* |
|
||||||
* @param app app |
|
||||||
*/ |
|
||||||
public void bind(App app) |
|
||||||
{ |
|
||||||
if (this.app != null) { |
|
||||||
throw new IllegalStateException("App already set."); |
|
||||||
} |
|
||||||
this.app = app; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Initialize backend modules, add them to event bus. |
|
||||||
*/ |
|
||||||
public abstract void initialize(); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Get graphics module (screen manager, texture and font loader, renderer) |
|
||||||
* |
|
||||||
* @return graphics module |
|
||||||
*/ |
|
||||||
public abstract GraphicsModule getGraphics(); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Get audio module ( |
|
||||||
* |
|
||||||
* @return audio module |
|
||||||
*/ |
|
||||||
public abstract AudioModule getAudio(); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Get input module |
|
||||||
* |
|
||||||
* @return input module |
|
||||||
*/ |
|
||||||
public abstract InputModule getInput(); |
|
||||||
} |
|
@ -1,34 +0,0 @@ |
|||||||
package mightypork.gamecore.core; |
|
||||||
|
|
||||||
|
|
||||||
import mightypork.utils.annotations.Stub; |
|
||||||
import mightypork.utils.eventbus.clients.BusNode; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* App plugin. Plugins are an easy way to extend app functionality.<br> |
|
||||||
* Typically, a plugin waits for trigger event(s) and performs some action upon |
|
||||||
* receiving them. |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public class AppPlugin extends BusNode { |
|
||||||
|
|
||||||
protected App app; |
|
||||||
|
|
||||||
|
|
||||||
void bind(App app) |
|
||||||
{ |
|
||||||
this.app = app; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Initialize the plugin for the given App.<br> |
|
||||||
* The plugin is already attached to the event bus. |
|
||||||
*/ |
|
||||||
@Stub |
|
||||||
public void initialize() |
|
||||||
{ |
|
||||||
} |
|
||||||
} |
|
@ -1,24 +0,0 @@ |
|||||||
package mightypork.gamecore.core; |
|
||||||
|
|
||||||
|
|
||||||
import mightypork.utils.annotations.Stub; |
|
||||||
import mightypork.utils.eventbus.clients.BusNode; |
|
||||||
import mightypork.utils.interfaces.Destroyable; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Abstract application backend module. |
|
||||||
* |
|
||||||
* @author MightyPork |
|
||||||
*/ |
|
||||||
public abstract class BackendModule extends BusNode implements Destroyable { |
|
||||||
|
|
||||||
public abstract void init(); |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
@Stub |
|
||||||
public void destroy() |
|
||||||
{ |
|
||||||
} |
|
||||||
} |
|
@ -1,150 +0,0 @@ |
|||||||
package mightypork.gamecore.core; |
|
||||||
|
|
||||||
|
|
||||||
import java.util.ArrayList; |
|
||||||
import java.util.HashSet; |
|
||||||
import java.util.Iterator; |
|
||||||
import java.util.List; |
|
||||||
import java.util.Set; |
|
||||||
|
|
||||||
import mightypork.utils.Reflect; |
|
||||||
import mightypork.utils.annotations.Stub; |
|
||||||
import mightypork.utils.logging.Log; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* App initializer. A sequence of initializers is executed once the start() |
|
||||||
* method on App is called. Adding initializers is one way to customize the App |
|
||||||
* behavior and features. |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public abstract class InitTask { |
|
||||||
|
|
||||||
protected App app; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Assign the initialized app instance to a protected "app" field. |
|
||||||
* |
|
||||||
* @param app app |
|
||||||
*/ |
|
||||||
void bind(App app) |
|
||||||
{ |
|
||||||
this.app = app; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* An intialization method that is called before the run() method.<br> |
|
||||||
* This method should be left unimplemented in the task, and can be used to |
|
||||||
* configure the init task when using it as anonymous inner type. |
|
||||||
*/ |
|
||||||
@Stub |
|
||||||
public void init() |
|
||||||
{ |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Run the initalizer on app. |
|
||||||
*/ |
|
||||||
public abstract void run(); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Get name of this initializer (for dependency resolver).<br> |
|
||||||
* The name should be short, snake_case and precise. |
|
||||||
* |
|
||||||
* @return name |
|
||||||
*/ |
|
||||||
public abstract String getName(); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Get what other initializers must be already loaded before this can load.<br> |
|
||||||
* Depending on itself or creating a circular dependency will cause error.<br> |
|
||||||
* If the dependencies cannot be satisfied, the initialization sequence will |
|
||||||
* be aborted. |
|
||||||
* |
|
||||||
* @return array of names of required initializers. |
|
||||||
*/ |
|
||||||
@Stub |
|
||||||
public String[] getDependencies() |
|
||||||
{ |
|
||||||
return new String[] {}; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Order init tasks so that all dependencies are loaded before thye are |
|
||||||
* needed by the tasks. |
|
||||||
* |
|
||||||
* @param tasks task list |
|
||||||
* @return task list ordered |
|
||||||
*/ |
|
||||||
public static List<InitTask> inOrder(List<InitTask> tasks) |
|
||||||
{ |
|
||||||
List<InitTask> remaining = new ArrayList<>(tasks); |
|
||||||
|
|
||||||
List<InitTask> ordered = new ArrayList<>(); |
|
||||||
Set<String> loaded = new HashSet<>(); |
|
||||||
|
|
||||||
// resolve task order
|
|
||||||
int addedThisIteration = 0; |
|
||||||
do { |
|
||||||
for (Iterator<InitTask> i = remaining.iterator(); i.hasNext();) { |
|
||||||
InitTask task = i.next(); |
|
||||||
|
|
||||||
String[] deps = task.getDependencies(); |
|
||||||
if (deps == null) deps = new String[] {}; |
|
||||||
|
|
||||||
int unmetDepsCount = deps.length; |
|
||||||
|
|
||||||
for (String d : deps) { |
|
||||||
if (loaded.contains(d)) unmetDepsCount--; |
|
||||||
} |
|
||||||
|
|
||||||
if (unmetDepsCount == 0) { |
|
||||||
ordered.add(task); |
|
||||||
loaded.add(task.getName()); |
|
||||||
i.remove(); |
|
||||||
addedThisIteration++; |
|
||||||
} |
|
||||||
} |
|
||||||
} while (addedThisIteration > 0); |
|
||||||
|
|
||||||
// check if any tasks are left out
|
|
||||||
if (remaining.size() > 0) { |
|
||||||
|
|
||||||
// build error message for each bad task
|
|
||||||
int badInitializers = 0; |
|
||||||
for (InitTask task : remaining) { |
|
||||||
if (Reflect.hasAnnotation(task.getClass(), OptionalInitTask.class)) { |
|
||||||
continue; |
|
||||||
} |
|
||||||
|
|
||||||
badInitializers++; |
|
||||||
|
|
||||||
String notSatisfied = ""; |
|
||||||
|
|
||||||
for (String d : task.getDependencies()) { |
|
||||||
if (!loaded.contains(d)) { |
|
||||||
|
|
||||||
if (!notSatisfied.isEmpty()) { |
|
||||||
notSatisfied += ", "; |
|
||||||
} |
|
||||||
|
|
||||||
notSatisfied += d; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
Log.w("InitTask \"" + task.getName() + "\" - missing dependencies: " + notSatisfied); |
|
||||||
} |
|
||||||
|
|
||||||
if (badInitializers > 0) throw new RuntimeException("Some InitTask dependencies could not be satisfied."); |
|
||||||
} |
|
||||||
|
|
||||||
return ordered; |
|
||||||
} |
|
||||||
} |
|
@ -1,130 +0,0 @@ |
|||||||
package mightypork.gamecore.core; |
|
||||||
|
|
||||||
|
|
||||||
import java.util.Deque; |
|
||||||
import java.util.concurrent.ConcurrentLinkedDeque; |
|
||||||
|
|
||||||
import mightypork.gamecore.graphics.Renderable; |
|
||||||
import mightypork.gamecore.gui.screens.ScreenRegistry; |
|
||||||
import mightypork.utils.annotations.Stub; |
|
||||||
import mightypork.utils.eventbus.clients.BusNode; |
|
||||||
import mightypork.utils.eventbus.events.UpdateEvent; |
|
||||||
import mightypork.utils.interfaces.Destroyable; |
|
||||||
import mightypork.utils.logging.Log; |
|
||||||
import mightypork.utils.math.timing.Profiler; |
|
||||||
import mightypork.utils.math.timing.TimerDelta; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Delta-timed game loop with task queue etc. |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public class MainLoop extends BusNode implements Destroyable { |
|
||||||
|
|
||||||
private static final double MAX_TIME_TASKS = 1 / 30D; // (avoid queue from hogging timing)
|
|
||||||
private static final double MAX_DELTA = 1 / 20D; // (skip huge gaps caused by loading resources etc)
|
|
||||||
|
|
||||||
private final Deque<Runnable> tasks = new ConcurrentLinkedDeque<>(); |
|
||||||
private TimerDelta timer; |
|
||||||
private Renderable rootRenderable; |
|
||||||
private volatile boolean running = true; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Set primary renderable |
|
||||||
* |
|
||||||
* @param rootRenderable main {@link Renderable}, typically a |
|
||||||
* {@link ScreenRegistry} |
|
||||||
*/ |
|
||||||
public void setRootRenderable(Renderable rootRenderable) |
|
||||||
{ |
|
||||||
this.rootRenderable = rootRenderable; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Start the loop |
|
||||||
*/ |
|
||||||
public void start() |
|
||||||
{ |
|
||||||
timer = new TimerDelta(); |
|
||||||
|
|
||||||
while (running) { |
|
||||||
App.gfx().beginFrame(); |
|
||||||
|
|
||||||
double delta = timer.getDelta(); |
|
||||||
if (delta > MAX_DELTA) { |
|
||||||
Log.f3("(timing) Cropping delta: was " + delta + " , limit " + MAX_DELTA); |
|
||||||
delta = MAX_DELTA; |
|
||||||
} |
|
||||||
|
|
||||||
App.bus().sendDirect(new UpdateEvent(delta)); |
|
||||||
|
|
||||||
Runnable r; |
|
||||||
final long t = Profiler.begin(); |
|
||||||
while ((r = tasks.poll()) != null) { |
|
||||||
Log.f3(" * Main loop task."); |
|
||||||
r.run(); |
|
||||||
if (Profiler.end(t) > MAX_TIME_TASKS) { |
|
||||||
Log.f3("! Postponing main loop tasks to next cycle."); |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
beforeRender(); |
|
||||||
|
|
||||||
if (rootRenderable != null) { |
|
||||||
rootRenderable.render(); |
|
||||||
} |
|
||||||
|
|
||||||
afterRender(); |
|
||||||
|
|
||||||
App.gfx().endFrame(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Called before render |
|
||||||
*/ |
|
||||||
@Stub |
|
||||||
protected void beforeRender() |
|
||||||
{ |
|
||||||
//
|
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Called after render |
|
||||||
*/ |
|
||||||
@Stub |
|
||||||
protected void afterRender() |
|
||||||
{ |
|
||||||
//
|
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void destroy() |
|
||||||
{ |
|
||||||
running = false; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Add a task to queue to be executed in the main loop (OpenGL thread) |
|
||||||
* |
|
||||||
* @param request task |
|
||||||
* @param priority if true, skip other tasks |
|
||||||
*/ |
|
||||||
public synchronized void queueTask(Runnable request, boolean priority) |
|
||||||
{ |
|
||||||
if (priority) { |
|
||||||
tasks.addFirst(request); |
|
||||||
} else { |
|
||||||
tasks.addLast(request); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -1,19 +0,0 @@ |
|||||||
package mightypork.gamecore.core; |
|
||||||
|
|
||||||
|
|
||||||
import java.lang.annotation.*; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Indicates that an {@link InitTask} can safely be ignored if it's dependencies |
|
||||||
* are not satisfied. |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
@Retention(RetentionPolicy.RUNTIME) |
|
||||||
@Target(ElementType.TYPE) |
|
||||||
@Documented |
|
||||||
@Inherited |
|
||||||
public @interface OptionalInitTask { |
|
||||||
|
|
||||||
} |
|
@ -1,91 +0,0 @@ |
|||||||
package mightypork.gamecore.core; |
|
||||||
|
|
||||||
|
|
||||||
import java.io.File; |
|
||||||
import java.util.HashMap; |
|
||||||
import java.util.Map; |
|
||||||
|
|
||||||
import mightypork.utils.logging.Log; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Static application workdir accessor. |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public class WorkDir { |
|
||||||
|
|
||||||
private static File workdir; |
|
||||||
private static Map<String, String> namedPaths = new HashMap<>(); |
|
||||||
|
|
||||||
|
|
||||||
public static void init(File workdir) |
|
||||||
{ |
|
||||||
WorkDir.workdir = workdir; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Add a path alias (dir or file), relative to the workdir. |
|
||||||
* |
|
||||||
* @param alias path alias |
|
||||||
* @param path path relative to workdir |
|
||||||
*/ |
|
||||||
public static void addPath(String alias, String path) |
|
||||||
{ |
|
||||||
namedPaths.put(alias, path); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Get workdir folder, create if not exists. |
|
||||||
* |
|
||||||
* @param path dir path relative to workdir |
|
||||||
* @return dir file |
|
||||||
*/ |
|
||||||
public static File getDir(String path) |
|
||||||
{ |
|
||||||
if (namedPaths.containsKey(path)) path = namedPaths.get(path); |
|
||||||
|
|
||||||
final File f = new File(workdir, path); |
|
||||||
if (!f.exists()) { |
|
||||||
if (!f.mkdirs()) { |
|
||||||
Log.w("Could not create a directory: " + f + " (path: " + path + ")"); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
return f; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Get workdir file, create parent if not exists. |
|
||||||
* |
|
||||||
* @param path dir path relative to workdir |
|
||||||
* @return dir file |
|
||||||
*/ |
|
||||||
public static File getFile(String path) |
|
||||||
{ |
|
||||||
if (namedPaths.containsKey(path)) path = namedPaths.get(path); |
|
||||||
|
|
||||||
final File f = new File(workdir, path); |
|
||||||
|
|
||||||
// create the parent dir
|
|
||||||
if (!f.getParent().equals(workdir)) { |
|
||||||
f.getParentFile().mkdirs(); |
|
||||||
} |
|
||||||
|
|
||||||
return f; |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* @return the workdir File |
|
||||||
*/ |
|
||||||
public static File getWorkDir() |
|
||||||
{ |
|
||||||
return workdir; |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -1,269 +0,0 @@ |
|||||||
package mightypork.gamecore.core.config; |
|
||||||
|
|
||||||
|
|
||||||
import java.util.HashMap; |
|
||||||
import java.util.Map; |
|
||||||
|
|
||||||
import mightypork.gamecore.core.WorkDir; |
|
||||||
import mightypork.gamecore.input.Key; |
|
||||||
import mightypork.gamecore.input.KeyStroke; |
|
||||||
import mightypork.utils.config.propmgr.Property; |
|
||||||
import mightypork.utils.config.propmgr.PropertyManager; |
|
||||||
import mightypork.utils.config.propmgr.PropertyStore; |
|
||||||
import mightypork.utils.config.propmgr.store.PropertyFile; |
|
||||||
import mightypork.utils.logging.Log; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Settings repository. |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public class Config { |
|
||||||
|
|
||||||
protected static Map<String, Config> configs = new HashMap<>(); |
|
||||||
|
|
||||||
private Map<String, KeyStrokeProperty> strokes = new HashMap<>(); |
|
||||||
|
|
||||||
private PropertyManager propertyManager; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Get a config from the static map, by given alias |
|
||||||
* |
|
||||||
* @param alias alias |
|
||||||
* @return the config |
|
||||||
*/ |
|
||||||
public static Config forAlias(String alias) |
|
||||||
{ |
|
||||||
Config c = configs.get(alias); |
|
||||||
|
|
||||||
if (c == null) { |
|
||||||
throw new IllegalArgumentException("There is no config with alias \"" + alias + "\""); |
|
||||||
} |
|
||||||
|
|
||||||
return c; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Register a config by alias. |
|
||||||
* |
|
||||||
* @param alias config alias |
|
||||||
* @param config the config |
|
||||||
*/ |
|
||||||
public static void register(String alias, Config config) |
|
||||||
{ |
|
||||||
if (configs.get(alias) != null) { |
|
||||||
throw new IllegalArgumentException("The alias \"" + alias + "\" is already used."); |
|
||||||
} |
|
||||||
|
|
||||||
configs.put(alias, config); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Initialize property manager for a file |
|
||||||
* |
|
||||||
* @param file config file, relative to workdir |
|
||||||
* @param headComment file comment |
|
||||||
*/ |
|
||||||
public Config(String file, String headComment) { |
|
||||||
this(new PropertyFile(WorkDir.getFile(file), headComment)); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Initialize property manager for a given store |
|
||||||
* |
|
||||||
* @param store property store backing the property manager |
|
||||||
*/ |
|
||||||
public Config(PropertyStore store) { |
|
||||||
if (propertyManager != null) { |
|
||||||
throw new IllegalStateException("Config already initialized."); |
|
||||||
} |
|
||||||
|
|
||||||
propertyManager = new PropertyManager(store); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Add a keystroke property |
|
||||||
* |
|
||||||
* @param key key in config file |
|
||||||
* @param defval default value (keystroke datastring) |
|
||||||
* @param comment optional comment, can be null |
|
||||||
*/ |
|
||||||
public void addKeyStroke(String key, String defval, String comment) |
|
||||||
{ |
|
||||||
final KeyStrokeProperty kprop = new KeyStrokeProperty(prefixKeyStroke(key), KeyStroke.createFromString(defval), comment); |
|
||||||
strokes.put(prefixKeyStroke(key), kprop); |
|
||||||
propertyManager.addProperty(kprop); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Add a boolean property (flag) |
|
||||||
* |
|
||||||
* @param key key in config file |
|
||||||
* @param defval default value |
|
||||||
* @param comment optional comment, can be null |
|
||||||
*/ |
|
||||||
public void addBoolean(String key, boolean defval, String comment) |
|
||||||
{ |
|
||||||
propertyManager.addBoolean(key, defval, comment); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Add an integer property |
|
||||||
* |
|
||||||
* @param key key in config file |
|
||||||
* @param defval default value |
|
||||||
* @param comment optional comment, can be null |
|
||||||
*/ |
|
||||||
public void addInteger(String key, int defval, String comment) |
|
||||||
{ |
|
||||||
propertyManager.addInteger(key, defval, comment); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Add a double property |
|
||||||
* |
|
||||||
* @param key key in config file |
|
||||||
* @param defval default value |
|
||||||
* @param comment optional comment, can be null |
|
||||||
*/ |
|
||||||
public void addDouble(String key, double defval, String comment) |
|
||||||
{ |
|
||||||
propertyManager.addDouble(key, defval, comment); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Add a string property |
|
||||||
* |
|
||||||
* @param key key in config file |
|
||||||
* @param defval default value |
|
||||||
* @param comment optional comment, can be null |
|
||||||
*/ |
|
||||||
public void addString(String key, String defval, String comment) |
|
||||||
{ |
|
||||||
propertyManager.addString(key, defval, comment); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Add an arbitrary property (can be custom type) |
|
||||||
* |
|
||||||
* @param prop the property to add |
|
||||||
*/ |
|
||||||
public <T> void addProperty(Property<T> prop) |
|
||||||
{ |
|
||||||
propertyManager.addProperty(prop); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Load config from file |
|
||||||
*/ |
|
||||||
public void load() |
|
||||||
{ |
|
||||||
propertyManager.load(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Save config to file |
|
||||||
*/ |
|
||||||
public void save() |
|
||||||
{ |
|
||||||
Log.f3("Saving config."); |
|
||||||
propertyManager.save(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Get an option for key |
|
||||||
* |
|
||||||
* @param key |
|
||||||
* @return option value |
|
||||||
*/ |
|
||||||
public <T> T getValue(String key) |
|
||||||
{ |
|
||||||
try { |
|
||||||
if (propertyManager.getProperty(key) == null) { |
|
||||||
throw new IllegalArgumentException("No such property: " + key); |
|
||||||
} |
|
||||||
|
|
||||||
return propertyManager.getValue(key); |
|
||||||
} catch (final ClassCastException cce) { |
|
||||||
throw new RuntimeException("Property of incompatible type: " + key); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Set option to a value. Call the save() method to make the change |
|
||||||
* permanent. |
|
||||||
* |
|
||||||
* @param key option key |
|
||||||
* @param value value to set |
|
||||||
*/ |
|
||||||
public <T> void setValue(String key, T value) |
|
||||||
{ |
|
||||||
if (propertyManager.getProperty(key) == null) { |
|
||||||
throw new IllegalArgumentException("No such property: " + key); |
|
||||||
} |
|
||||||
|
|
||||||
propertyManager.setValue(key, value); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Add "key." before the given config file key |
|
||||||
* |
|
||||||
* @param cfgKey config key |
|
||||||
* @return key. + cfgKey |
|
||||||
*/ |
|
||||||
private String prefixKeyStroke(String cfgKey) |
|
||||||
{ |
|
||||||
return "key." + cfgKey; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Get keystroke for name |
|
||||||
* |
|
||||||
* @param cfgKey stroke identifier in config file |
|
||||||
* @return the stroke |
|
||||||
*/ |
|
||||||
public KeyStroke getKeyStroke(String cfgKey) |
|
||||||
{ |
|
||||||
final KeyStrokeProperty kp = strokes.get(prefixKeyStroke(cfgKey)); |
|
||||||
if (kp == null) { |
|
||||||
throw new IllegalArgumentException("No such stroke: " + cfgKey); |
|
||||||
} |
|
||||||
|
|
||||||
return kp.getValue(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Set a keystroke for name |
|
||||||
* |
|
||||||
* @param cfgKey stroke identifier in config file |
|
||||||
* @param key stroke key |
|
||||||
* @param mod stroke modifiers |
|
||||||
*/ |
|
||||||
public void setKeyStroke(String cfgKey, Key key, int mod) |
|
||||||
{ |
|
||||||
final KeyStrokeProperty kp = strokes.get(prefixKeyStroke(cfgKey)); |
|
||||||
if (kp == null) { |
|
||||||
throw new IllegalArgumentException("No such stroke: " + cfgKey); |
|
||||||
} |
|
||||||
|
|
||||||
kp.getValue().setTo(key, mod); |
|
||||||
} |
|
||||||
} |
|
@ -1,75 +0,0 @@ |
|||||||
package mightypork.gamecore.core.config; |
|
||||||
|
|
||||||
|
|
||||||
import mightypork.gamecore.core.InitTask; |
|
||||||
import mightypork.utils.annotations.Stub; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Initialize config. To apply this initializer, you must extend it. That |
|
||||||
* ensures that the workdir initializer has already finished when the code is |
|
||||||
* executed (such as resolving a file path for the config file). |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public abstract class InitTaskConfig extends InitTask { |
|
||||||
|
|
||||||
/** |
|
||||||
* Add a config with given alias |
|
||||||
* |
|
||||||
* @param alias config alias |
|
||||||
* @param config config to add |
|
||||||
*/ |
|
||||||
protected void addConfig(String alias, Config config) |
|
||||||
{ |
|
||||||
Config.register(alias, config); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Initialize the main config. |
|
||||||
* |
|
||||||
* @return the main config. |
|
||||||
*/ |
|
||||||
protected abstract Config buildConfig(); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Initialize extra configs.<br> |
|
||||||
* the addConfig() method can be used to register configs. |
|
||||||
*/ |
|
||||||
@Stub |
|
||||||
protected void buildExtraConfigs() |
|
||||||
{ |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
// locked to encourage the use of the build* methods.
|
|
||||||
@Override |
|
||||||
public final void init() |
|
||||||
{ |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public final void run() |
|
||||||
{ |
|
||||||
addConfig("main", buildConfig()); |
|
||||||
buildExtraConfigs(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public String getName() |
|
||||||
{ |
|
||||||
return "config"; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public String[] getDependencies() |
|
||||||
{ |
|
||||||
return new String[] { "workdir" }; |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -1,55 +0,0 @@ |
|||||||
package mightypork.gamecore.core.config; |
|
||||||
|
|
||||||
|
|
||||||
import mightypork.gamecore.input.Key; |
|
||||||
import mightypork.gamecore.input.KeyStroke; |
|
||||||
import mightypork.gamecore.input.Keys; |
|
||||||
import mightypork.utils.config.propmgr.Property; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Key property.<br> |
|
||||||
* The stored value must stay the same instance ({@link KeyStroke} is mutable).<br> |
|
||||||
* That ensures that bindings based on this keystroke are automatically updated |
|
||||||
* when the settings change. |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public class KeyStrokeProperty extends Property<KeyStroke> { |
|
||||||
|
|
||||||
public KeyStrokeProperty(String key, KeyStroke defaultValue, String comment) { |
|
||||||
super(key, defaultValue, comment); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void fromString(String string) |
|
||||||
{ |
|
||||||
if (string != null) { |
|
||||||
// keep the same instance
|
|
||||||
|
|
||||||
final Key backup_key = value.getKey(); |
|
||||||
final int backup_mod = value.getMod(); |
|
||||||
|
|
||||||
value.loadFromString(string); |
|
||||||
if (value.getKey() == Keys.NONE) { |
|
||||||
value.setTo(backup_key, backup_mod); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public String toString() |
|
||||||
{ |
|
||||||
return value.saveToString(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void setValue(Object value) |
|
||||||
{ |
|
||||||
// keep the same instance
|
|
||||||
this.value.setTo(((KeyStroke) value).getKey(), ((KeyStroke) value).getMod()); |
|
||||||
} |
|
||||||
} |
|
@ -1,44 +0,0 @@ |
|||||||
package mightypork.gamecore.core.events; |
|
||||||
|
|
||||||
|
|
||||||
import mightypork.gamecore.core.MainLoop; |
|
||||||
import mightypork.utils.eventbus.BusEvent; |
|
||||||
import mightypork.utils.eventbus.events.flags.SingleReceiverEvent; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Request to execute given {@link Runnable} in main loop. |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
@SingleReceiverEvent |
|
||||||
public class MainLoopRequest extends BusEvent<MainLoop> { |
|
||||||
|
|
||||||
private final Runnable task; |
|
||||||
private final boolean priority; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* @param task task to run on main thread in rendering context |
|
||||||
*/ |
|
||||||
public MainLoopRequest(Runnable task) { |
|
||||||
this(task, false); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* @param task task to run on main thread in rendering context |
|
||||||
* @param priority if true, skip other tasks in queue |
|
||||||
*/ |
|
||||||
public MainLoopRequest(Runnable task, boolean priority) { |
|
||||||
this.task = task; |
|
||||||
this.priority = priority; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void handleBy(MainLoop handler) |
|
||||||
{ |
|
||||||
handler.queueTask(task, priority); |
|
||||||
} |
|
||||||
} |
|
@ -1,47 +0,0 @@ |
|||||||
package mightypork.gamecore.core.events; |
|
||||||
|
|
||||||
|
|
||||||
import mightypork.utils.eventbus.BusEvent; |
|
||||||
import mightypork.utils.eventbus.EventBus; |
|
||||||
import mightypork.utils.logging.Log; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Shutdown event.<br> |
|
||||||
* This event is dispatched when the <code>App.shutdown()</code> method is |
|
||||||
* called. If no client consumes it, the shutdown will immediately follow.<br> |
|
||||||
* This is a way to allow clients to abort the shutdown (ie. ask user to save |
|
||||||
* game). After the game is saved, the <code>App.shutdown()</code> method can be |
|
||||||
* called again. |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public class ShutdownEvent extends BusEvent<ShutdownListener> { |
|
||||||
|
|
||||||
private Runnable shutdownTask; |
|
||||||
|
|
||||||
|
|
||||||
public ShutdownEvent(Runnable doShutdown) { |
|
||||||
this.shutdownTask = doShutdown; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
protected void handleBy(ShutdownListener handler) |
|
||||||
{ |
|
||||||
handler.onShutdown(this); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void onDispatchComplete(EventBus bus) |
|
||||||
{ |
|
||||||
if (!isConsumed()) { |
|
||||||
Log.i("Shutting down..."); |
|
||||||
shutdownTask.run(); |
|
||||||
} else { |
|
||||||
Log.i("Shutdown aborted."); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -1,18 +0,0 @@ |
|||||||
package mightypork.gamecore.core.events; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Quit request listener; implementing client can abort shutdown. |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public interface ShutdownListener { |
|
||||||
|
|
||||||
/** |
|
||||||
* Intercept quit request.<br> |
|
||||||
* Consume the event to abort shutdown (ie. ask user to save) |
|
||||||
* |
|
||||||
* @param event quit request event. |
|
||||||
*/ |
|
||||||
void onShutdown(ShutdownEvent event); |
|
||||||
} |
|
@ -1,42 +0,0 @@ |
|||||||
package mightypork.gamecore.core.init; |
|
||||||
|
|
||||||
|
|
||||||
import java.lang.Thread.UncaughtExceptionHandler; |
|
||||||
|
|
||||||
import mightypork.gamecore.core.App; |
|
||||||
import mightypork.gamecore.core.InitTask; |
|
||||||
import mightypork.utils.annotations.Stub; |
|
||||||
import mightypork.utils.logging.Log; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Add a crash handler to the app.<br> |
|
||||||
* For customized crash message / crash dialog etc, override the |
|
||||||
* uncaughtException() method. |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public class InitTaskCrashHandler extends InitTask implements UncaughtExceptionHandler { |
|
||||||
|
|
||||||
@Override |
|
||||||
public void run() |
|
||||||
{ |
|
||||||
Thread.setDefaultUncaughtExceptionHandler(this); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
@Stub |
|
||||||
public void uncaughtException(Thread thread, Throwable throwable) |
|
||||||
{ |
|
||||||
Log.e("The game has crashed.", throwable); |
|
||||||
App.shutdown(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public String getName() |
|
||||||
{ |
|
||||||
return "crash_handler"; |
|
||||||
} |
|
||||||
} |
|
@ -1,97 +0,0 @@ |
|||||||
package mightypork.gamecore.core.init; |
|
||||||
|
|
||||||
|
|
||||||
import mightypork.gamecore.core.InitTask; |
|
||||||
import mightypork.gamecore.graphics.GraphicsModule; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Setup main window. |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public class InitTaskDisplay extends InitTask { |
|
||||||
|
|
||||||
private int width = 800, height = 600, fps = 60; |
|
||||||
private boolean resizable, fullscreen; |
|
||||||
private String title = "Game"; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Set initial window size |
|
||||||
* |
|
||||||
* @param width width (px) |
|
||||||
* @param height height (px) |
|
||||||
*/ |
|
||||||
public void setSize(int width, int height) |
|
||||||
{ |
|
||||||
this.width = width; |
|
||||||
this.height = height; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Set whether the window should be resizable |
|
||||||
* |
|
||||||
* @param resizable true for resizable |
|
||||||
*/ |
|
||||||
public void setResizable(boolean resizable) |
|
||||||
{ |
|
||||||
this.resizable = resizable; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Set window title |
|
||||||
* |
|
||||||
* @param title title text |
|
||||||
*/ |
|
||||||
public void setTitle(String title) |
|
||||||
{ |
|
||||||
this.title = title; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Set desired framerate. |
|
||||||
* |
|
||||||
* @param fps FPS |
|
||||||
*/ |
|
||||||
public void setTargetFps(int fps) |
|
||||||
{ |
|
||||||
this.fps = fps; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Set whether the window should start in fullscreen |
|
||||||
* |
|
||||||
* @param fullscreen true for fullscreen |
|
||||||
*/ |
|
||||||
public void setFullscreen(boolean fullscreen) |
|
||||||
{ |
|
||||||
this.fullscreen = fullscreen; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void run() |
|
||||||
{ |
|
||||||
GraphicsModule gfx = app.getBackend().getGraphics(); |
|
||||||
|
|
||||||
gfx.setSize(width, height); |
|
||||||
gfx.setResizable(resizable); |
|
||||||
gfx.setTitle(title); |
|
||||||
gfx.setTargetFps(fps); |
|
||||||
|
|
||||||
if (fullscreen) gfx.setFullscreen(true); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public String getName() |
|
||||||
{ |
|
||||||
return "display"; |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -1,74 +0,0 @@ |
|||||||
package mightypork.gamecore.core.init; |
|
||||||
|
|
||||||
|
|
||||||
import java.io.IOException; |
|
||||||
|
|
||||||
import mightypork.gamecore.core.InitTask; |
|
||||||
import mightypork.utils.ion.Ion; |
|
||||||
import mightypork.utils.ion.IonInput; |
|
||||||
import mightypork.utils.ion.IonOutput; |
|
||||||
import mightypork.utils.ion.IonizerBinary; |
|
||||||
import mightypork.utils.math.algo.Coord; |
|
||||||
import mightypork.utils.math.algo.Move; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Register extra ionizables added by the game library (non-native ION types).<br> |
|
||||||
* This initializer can be called anywhere in the initialization sequence. |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public class InitTaskIonizables extends InitTask { |
|
||||||
|
|
||||||
@Override |
|
||||||
public void run() |
|
||||||
{ |
|
||||||
Ion.registerIndirect(255, new IonizerBinary<Coord>() { |
|
||||||
|
|
||||||
@Override |
|
||||||
public void save(Coord object, IonOutput out) throws IOException |
|
||||||
{ |
|
||||||
out.writeInt(object.x); |
|
||||||
out.writeInt(object.y); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public Coord load(IonInput in) throws IOException |
|
||||||
{ |
|
||||||
final int x = in.readInt(); |
|
||||||
final int y = in.readInt(); |
|
||||||
return new Coord(x, y); |
|
||||||
} |
|
||||||
|
|
||||||
}); |
|
||||||
|
|
||||||
Ion.registerIndirect(254, new IonizerBinary<Move>() { |
|
||||||
|
|
||||||
@Override |
|
||||||
public void save(Move object, IonOutput out) throws IOException |
|
||||||
{ |
|
||||||
out.writeInt(object.x()); |
|
||||||
out.writeInt(object.y()); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public Move load(IonInput in) throws IOException |
|
||||||
{ |
|
||||||
final int x = in.readInt(); |
|
||||||
final int y = in.readInt(); |
|
||||||
return new Move(x, y); |
|
||||||
} |
|
||||||
|
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public String getName() |
|
||||||
{ |
|
||||||
return "ion"; |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -1,108 +0,0 @@ |
|||||||
package mightypork.gamecore.core.init; |
|
||||||
|
|
||||||
|
|
||||||
import java.io.File; |
|
||||||
import java.util.logging.Level; |
|
||||||
|
|
||||||
import mightypork.gamecore.core.InitTask; |
|
||||||
import mightypork.gamecore.core.WorkDir; |
|
||||||
import mightypork.utils.logging.Log; |
|
||||||
import mightypork.utils.logging.writers.LogWriter; |
|
||||||
import mightypork.utils.string.StringUtil; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Init main logger and console log printing.<br> |
|
||||||
* Must be called after workdir is initialized. |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public class InitTaskLog extends InitTask { |
|
||||||
|
|
||||||
private String logDir = "log"; |
|
||||||
private String logName = "runtime"; |
|
||||||
private int archiveCount = 5; |
|
||||||
|
|
||||||
private Level levelWrite = Level.ALL; |
|
||||||
private Level levelPrint = Level.ALL; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Set log directory (relative to workdir).<br> |
|
||||||
* Defaults to "log". |
|
||||||
* |
|
||||||
* @param logDir log directory. |
|
||||||
*/ |
|
||||||
public void setLogDir(String logDir) |
|
||||||
{ |
|
||||||
this.logDir = logDir; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Set log name. This name is used as a prefix for archived log files.<br> |
|
||||||
* Should contain only valid filename characters.<br> |
|
||||||
* Defaults to "runtime". |
|
||||||
* |
|
||||||
* @param logName log name |
|
||||||
*/ |
|
||||||
public void setLogName(String logName) |
|
||||||
{ |
|
||||||
if (!StringUtil.isValidFilenameString(logName)) { |
|
||||||
throw new IllegalArgumentException("Invalid log name."); |
|
||||||
} |
|
||||||
|
|
||||||
this.logName = logName; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Set number of logs to keep in the logs directory.<br> |
|
||||||
* Set to 0 to keep just the last log, -1 to keep unlimited number of logs.<br> |
|
||||||
* Defaults to 5. |
|
||||||
* |
|
||||||
* @param archiveCount logs to keep |
|
||||||
*/ |
|
||||||
public void setArchiveCount(int archiveCount) |
|
||||||
{ |
|
||||||
this.archiveCount = archiveCount; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Set logging levels (minimal level of message to be accepted)<br> |
|
||||||
* Defaults to ALL, ALL. |
|
||||||
* |
|
||||||
* @param levelWrite level for writing to file |
|
||||||
* @param levelPrint level for writing to stdout / stderr |
|
||||||
*/ |
|
||||||
public void setLevels(Level levelWrite, Level levelPrint) |
|
||||||
{ |
|
||||||
this.levelWrite = levelWrite; |
|
||||||
this.levelPrint = levelPrint; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void run() |
|
||||||
{ |
|
||||||
final LogWriter log = Log.create(logName, new File(WorkDir.getDir(logDir), logName + ".log"), archiveCount); |
|
||||||
Log.setMainLogger(log); |
|
||||||
Log.setLevel(levelWrite); |
|
||||||
Log.setSysoutLevel(levelPrint); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public String getName() |
|
||||||
{ |
|
||||||
return "log"; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public String[] getDependencies() |
|
||||||
{ |
|
||||||
return new String[] { "workdir" }; |
|
||||||
} |
|
||||||
} |
|
@ -1,54 +0,0 @@ |
|||||||
package mightypork.gamecore.core.init; |
|
||||||
|
|
||||||
|
|
||||||
import java.io.IOException; |
|
||||||
|
|
||||||
import mightypork.gamecore.core.InitTask; |
|
||||||
import mightypork.gamecore.core.OptionalInitTask; |
|
||||||
import mightypork.gamecore.core.WorkDir; |
|
||||||
import mightypork.utils.logging.Log; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* initializer task that writes a system info header to the log file.<br> |
|
||||||
* Must be called after log is initialized. |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
@OptionalInitTask |
|
||||||
public class InitTaskLogHeader extends InitTask { |
|
||||||
|
|
||||||
@Override |
|
||||||
public void run() |
|
||||||
{ |
|
||||||
String txt = ""; |
|
||||||
|
|
||||||
txt += "\n### SYSTEM INFO ###\n\n"; |
|
||||||
txt += " Platform ...... " + System.getProperty("os.name") + "\n"; |
|
||||||
txt += " Runtime ....... " + System.getProperty("java.runtime.name") + "\n"; |
|
||||||
txt += " Java .......... " + System.getProperty("java.version") + "\n"; |
|
||||||
txt += " Launch path ... " + System.getProperty("user.dir") + "\n"; |
|
||||||
|
|
||||||
try { |
|
||||||
txt += " Workdir ....... " + WorkDir.getWorkDir().getCanonicalPath() + "\n"; |
|
||||||
} catch (final IOException e) { |
|
||||||
Log.e(e); |
|
||||||
} |
|
||||||
|
|
||||||
Log.i(txt); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public String getName() |
|
||||||
{ |
|
||||||
return "log_header"; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public String[] getDependencies() |
|
||||||
{ |
|
||||||
return new String[] { "log", "workdir" }; |
|
||||||
} |
|
||||||
} |
|
@ -1,136 +0,0 @@ |
|||||||
package mightypork.gamecore.core.init; |
|
||||||
|
|
||||||
|
|
||||||
import java.io.File; |
|
||||||
import java.util.HashMap; |
|
||||||
import java.util.Map; |
|
||||||
import java.util.Map.Entry; |
|
||||||
|
|
||||||
import javax.swing.JOptionPane; |
|
||||||
|
|
||||||
import mightypork.gamecore.core.App; |
|
||||||
import mightypork.gamecore.core.InitTask; |
|
||||||
import mightypork.gamecore.core.WorkDir; |
|
||||||
import mightypork.utils.annotations.Stub; |
|
||||||
import mightypork.utils.files.InstanceLock; |
|
||||||
import mightypork.utils.logging.Log; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Initializer that takes care of setting up the proper workdir. |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public class InitTaskWorkdir extends InitTask { |
|
||||||
|
|
||||||
private File workdirPath; |
|
||||||
private boolean doLock; |
|
||||||
private String lockFile = ".lock"; |
|
||||||
private Map<String, String> namedPaths = new HashMap<>(); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* @param workdir path to the working directory |
|
||||||
* @param lock whether to lock the directory (single instance mode) |
|
||||||
*/ |
|
||||||
public InitTaskWorkdir(File workdir, boolean lock) { |
|
||||||
this.workdirPath = workdir; |
|
||||||
this.doLock = lock; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Set workdir root path |
|
||||||
* |
|
||||||
* @param path workdir path |
|
||||||
*/ |
|
||||||
public void setWorkdirPath(File path) |
|
||||||
{ |
|
||||||
this.workdirPath = path; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Set whether the workdir should be locked when the app is running, to |
|
||||||
* prevent other instances from running simultaneously. |
|
||||||
* |
|
||||||
* @param lock |
|
||||||
*/ |
|
||||||
public void setInstanceLock(boolean lock) |
|
||||||
{ |
|
||||||
this.doLock = lock; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Set name of the lock file. |
|
||||||
* |
|
||||||
* @param lockFile |
|
||||||
*/ |
|
||||||
public void setLockFileName(String lockFile) |
|
||||||
{ |
|
||||||
this.lockFile = lockFile; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Add a named path |
|
||||||
* |
|
||||||
* @param alias path alias (snake_case) |
|
||||||
* @param path path (relative to the workdir) |
|
||||||
*/ |
|
||||||
public void addPath(String alias, String path) |
|
||||||
{ |
|
||||||
namedPaths.put(alias, path); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void run() |
|
||||||
{ |
|
||||||
WorkDir.init(workdirPath); |
|
||||||
|
|
||||||
// lock working directory
|
|
||||||
if (doLock) { |
|
||||||
final File lock = WorkDir.getFile(lockFile); |
|
||||||
if (!InstanceLock.onFile(lock)) { |
|
||||||
onLockError(); |
|
||||||
return; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
for (Entry<String, String> e : namedPaths.entrySet()) { |
|
||||||
WorkDir.addPath(e.getKey(), e.getValue()); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Called when the lock file could not be obtained (cannot write or already |
|
||||||
* exists).<br> |
|
||||||
* Feel free to override this method to define custom behavior. |
|
||||||
*/ |
|
||||||
@Stub |
|
||||||
protected void onLockError() |
|
||||||
{ |
|
||||||
Log.e("Could not obtain lock file.\nOnly one instance can run at a time."); |
|
||||||
|
|
||||||
//@formatter:off
|
|
||||||
JOptionPane.showMessageDialog( |
|
||||||
null, |
|
||||||
"Another instance is already running.\n(Delete the "+lockFile +" file in the working directory to override)", |
|
||||||
"Lock Error", |
|
||||||
JOptionPane.ERROR_MESSAGE |
|
||||||
); |
|
||||||
//@formatter:on
|
|
||||||
|
|
||||||
App.shutdown(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public String getName() |
|
||||||
{ |
|
||||||
return "workdir"; |
|
||||||
} |
|
||||||
} |
|
@ -1,68 +0,0 @@ |
|||||||
package mightypork.gamecore.core.plugins.screenshot; |
|
||||||
|
|
||||||
|
|
||||||
import mightypork.gamecore.core.InitTask; |
|
||||||
import mightypork.gamecore.core.WorkDir; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Register screenshot plugin to the App. |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public class InitTaskPluginScreenshot extends InitTask { |
|
||||||
|
|
||||||
private String screenshotDir; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Initialize to use the "screenshots" directory |
|
||||||
*/ |
|
||||||
public InitTaskPluginScreenshot() { |
|
||||||
this("screenshots"); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Initialize to use the given directory for saving. |
|
||||||
* |
|
||||||
* @param dir screenshot dir (relative to workdir) |
|
||||||
*/ |
|
||||||
public InitTaskPluginScreenshot(String dir) { |
|
||||||
this.screenshotDir = dir; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Set screenshot directory |
|
||||||
* |
|
||||||
* @param dir screenshot dir (relative to workdir) |
|
||||||
*/ |
|
||||||
public void setScreenshotDir(String dir) |
|
||||||
{ |
|
||||||
this.screenshotDir = dir; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void run() |
|
||||||
{ |
|
||||||
WorkDir.addPath("_screenshot_dir", screenshotDir); |
|
||||||
app.addPlugin(new ScreenshotPlugin()); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public String getName() |
|
||||||
{ |
|
||||||
return "plugin_screenshot"; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public String[] getDependencies() |
|
||||||
{ |
|
||||||
return new String[] { "workdir" }; |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -1,34 +0,0 @@ |
|||||||
package mightypork.gamecore.core.plugins.screenshot; |
|
||||||
|
|
||||||
|
|
||||||
import mightypork.gamecore.core.App; |
|
||||||
import mightypork.gamecore.core.AppPlugin; |
|
||||||
import mightypork.gamecore.core.events.MainLoopRequest; |
|
||||||
import mightypork.utils.Support; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* This plugin waits for a {@link ScreenshotRequest} event.<br> |
|
||||||
* Upon receiving it, a screenshot is captured and written to file |
|
||||||
* asynchronously. |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public class ScreenshotPlugin extends AppPlugin { |
|
||||||
|
|
||||||
/** |
|
||||||
* Take screenshot. Called by the trigger event. |
|
||||||
*/ |
|
||||||
void takeScreenshot() |
|
||||||
{ |
|
||||||
App.bus().send(new MainLoopRequest(new Runnable() { |
|
||||||
|
|
||||||
@Override |
|
||||||
public void run() |
|
||||||
{ |
|
||||||
Runnable tts = new TaskTakeScreenshot(); |
|
||||||
Support.runAsThread(tts); |
|
||||||
} |
|
||||||
})); |
|
||||||
} |
|
||||||
} |
|
@ -1,22 +0,0 @@ |
|||||||
package mightypork.gamecore.core.plugins.screenshot; |
|
||||||
|
|
||||||
|
|
||||||
import mightypork.utils.eventbus.BusEvent; |
|
||||||
import mightypork.utils.eventbus.events.flags.SingleReceiverEvent; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Event used to request screenshot capture. |
|
||||||
* |
|
||||||
* @author MightyPork |
|
||||||
*/ |
|
||||||
@SingleReceiverEvent |
|
||||||
public class ScreenshotRequest extends BusEvent<ScreenshotPlugin> { |
|
||||||
|
|
||||||
@Override |
|
||||||
protected void handleBy(ScreenshotPlugin handler) |
|
||||||
{ |
|
||||||
handler.takeScreenshot(); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -1,100 +0,0 @@ |
|||||||
package mightypork.gamecore.core.plugins.screenshot; |
|
||||||
|
|
||||||
|
|
||||||
import java.io.File; |
|
||||||
import java.io.IOException; |
|
||||||
|
|
||||||
import mightypork.gamecore.core.App; |
|
||||||
import mightypork.gamecore.core.WorkDir; |
|
||||||
import mightypork.gamecore.graphics.Screenshot; |
|
||||||
import mightypork.utils.Support; |
|
||||||
import mightypork.utils.logging.Log; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Task that takes screenshot and asynchronously saves it to a file.<br> |
|
||||||
* Can be run in a separate thread, but must be instantiated in the render |
|
||||||
* thread. |
|
||||||
* |
|
||||||
* @author MightyPork |
|
||||||
*/ |
|
||||||
public class TaskTakeScreenshot implements Runnable { |
|
||||||
|
|
||||||
private final Screenshot scr; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Take screenshot. Must be called in render thread. |
|
||||||
*/ |
|
||||||
public TaskTakeScreenshot() { |
|
||||||
scr = App.gfx().takeScreenshot(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void run() |
|
||||||
{ |
|
||||||
// generate unique filename
|
|
||||||
final File file = getScreenshotFile(); |
|
||||||
|
|
||||||
Log.f3("Saving screenshot to file: " + file); |
|
||||||
|
|
||||||
// save to disk
|
|
||||||
try { |
|
||||||
scr.save(file); |
|
||||||
} catch (final IOException e) { |
|
||||||
Log.e("Failed to save screenshot.", e); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* @return File to save the screenshot to. |
|
||||||
*/ |
|
||||||
protected File getScreenshotFile() |
|
||||||
{ |
|
||||||
final String fname = getBaseFilename(); |
|
||||||
return findFreeFile(fname); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* @return directory for screenshots |
|
||||||
*/ |
|
||||||
protected File getScreenshotDirectory() |
|
||||||
{ |
|
||||||
return WorkDir.getDir("_screenshot_dir"); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Get base filename for the screenshot, without extension. |
|
||||||
* |
|
||||||
* @return filename |
|
||||||
*/ |
|
||||||
protected String getBaseFilename() |
|
||||||
{ |
|
||||||
return Support.getTime("yyyy-MM-dd_HH-mm-ss"); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Find first free filename for the screenshot, by adding -NUMBER after the |
|
||||||
* base filename and before extension. |
|
||||||
* |
|
||||||
* @param base_name base filename |
|
||||||
* @return full path to screenshot file |
|
||||||
*/ |
|
||||||
protected File findFreeFile(String base_name) |
|
||||||
{ |
|
||||||
File file; |
|
||||||
int index = 0; |
|
||||||
while (true) { |
|
||||||
file = new File(getScreenshotDirectory(), base_name + (index > 0 ? "-" + index : "") + ".png"); |
|
||||||
if (!file.exists()) break; |
|
||||||
index++; |
|
||||||
} |
|
||||||
return file; |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -1,16 +0,0 @@ |
|||||||
package mightypork.gamecore.graphics; |
|
||||||
|
|
||||||
|
|
||||||
import mightypork.utils.eventbus.BusEvent; |
|
||||||
import mightypork.utils.eventbus.events.flags.SingleReceiverEvent; |
|
||||||
|
|
||||||
|
|
||||||
@SingleReceiverEvent |
|
||||||
public class FullscreenToggleRequest extends BusEvent<GraphicsModule> { |
|
||||||
|
|
||||||
@Override |
|
||||||
protected void handleBy(GraphicsModule handler) |
|
||||||
{ |
|
||||||
handler.switchFullscreen(); |
|
||||||
} |
|
||||||
} |
|
@ -1,406 +0,0 @@ |
|||||||
package mightypork.gamecore.graphics; |
|
||||||
|
|
||||||
|
|
||||||
import mightypork.gamecore.core.BackendModule; |
|
||||||
import mightypork.gamecore.graphics.textures.DeferredTexture; |
|
||||||
import mightypork.gamecore.graphics.textures.TxQuad; |
|
||||||
import mightypork.gamecore.gui.events.ViewportChangeEvent; |
|
||||||
import mightypork.utils.math.color.Color; |
|
||||||
import mightypork.utils.math.color.Grad; |
|
||||||
import mightypork.utils.math.constraints.rect.Rect; |
|
||||||
import mightypork.utils.math.constraints.vect.Vect; |
|
||||||
import mightypork.utils.math.constraints.vect.VectConst; |
|
||||||
import mightypork.utils.math.timing.FpsMeter; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Render and display backend module.<br> |
|
||||||
* This module takes care of setting and getting screen size and parameters, |
|
||||||
* drawing on screen and timing render frames. |
|
||||||
* |
|
||||||
* @author MightyPork |
|
||||||
*/ |
|
||||||
public abstract class GraphicsModule extends BackendModule { |
|
||||||
|
|
||||||
protected static final VectConst AXIS_X = Vect.make(1, 0, 0); |
|
||||||
protected static final VectConst AXIS_Y = Vect.make(0, 1, 0); |
|
||||||
protected static final VectConst AXIS_Z = Vect.make(0, 0, 1); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Set drawing color |
|
||||||
* |
|
||||||
* @param color color |
|
||||||
*/ |
|
||||||
public abstract void setColor(Color color); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Set drawing color, adjust alpha |
|
||||||
* |
|
||||||
* @param color color |
|
||||||
* @param alpha alpha multiplier |
|
||||||
*/ |
|
||||||
public abstract void setColor(Color color, double alpha); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Translate by x, y |
|
||||||
* |
|
||||||
* @param x x offset |
|
||||||
* @param y y offset |
|
||||||
*/ |
|
||||||
public abstract void translate(double x, double y); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Translate by x, y, z |
|
||||||
* |
|
||||||
* @param x x offset |
|
||||||
* @param y y offset |
|
||||||
* @param z z offset |
|
||||||
*/ |
|
||||||
public abstract void translate(double x, double y, double z); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Translate by offset vector |
|
||||||
* |
|
||||||
* @param offset offset coordinate |
|
||||||
*/ |
|
||||||
public abstract void translate(Vect offset); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Translate by offset vector, ignore Z |
|
||||||
* |
|
||||||
* @param offset offset coordinate |
|
||||||
*/ |
|
||||||
public abstract void translateXY(Vect offset); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Set scale for translations and coordinates |
|
||||||
* |
|
||||||
* @param x x scale |
|
||||||
* @param y y scale |
|
||||||
*/ |
|
||||||
public abstract void scale(double x, double y); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Set scale for translations and coordinates |
|
||||||
* |
|
||||||
* @param x x scale |
|
||||||
* @param y y scale |
|
||||||
* @param z z scale |
|
||||||
*/ |
|
||||||
public abstract void scale(double x, double y, double z); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Set scale for translations and coordinates |
|
||||||
* |
|
||||||
* @param scale vector |
|
||||||
*/ |
|
||||||
public abstract void scale(Vect scale); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Set scale for translations and coordinates (same value for X and Y scale) |
|
||||||
* |
|
||||||
* @param scale scaling factor |
|
||||||
*/ |
|
||||||
public abstract void scaleXY(double scale); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Set X scale for translations and coordinates |
|
||||||
* |
|
||||||
* @param scale scaling factor |
|
||||||
*/ |
|
||||||
public abstract void scaleX(double scale); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Set Y scale for translations and coordinates |
|
||||||
* |
|
||||||
* @param scale scaling factor |
|
||||||
*/ |
|
||||||
public abstract void scaleY(double scale); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Set Z scale for translations and coordinates |
|
||||||
* |
|
||||||
* @param scale scaling factor |
|
||||||
*/ |
|
||||||
public abstract void scaleZ(double scale); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Rotate coordinate system around X axis |
|
||||||
* |
|
||||||
* @param angle rotation (in degrees) |
|
||||||
*/ |
|
||||||
public abstract void rotateX(double angle); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Rotate coordinate system around Y axis |
|
||||||
* |
|
||||||
* @param angle rotation (in degrees) |
|
||||||
*/ |
|
||||||
public abstract void rotateY(double angle); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Rotate coordinate system around Z axis |
|
||||||
* |
|
||||||
* @param angle rotation (in degrees) |
|
||||||
*/ |
|
||||||
public abstract void rotateZ(double angle); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Rotate coordinate system around given axis |
|
||||||
* |
|
||||||
* @param angle rotation angle |
|
||||||
* @param axis rotation axis (unit vector) |
|
||||||
*/ |
|
||||||
public abstract void rotate(double angle, Vect axis); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Store render state on stack<br> |
|
||||||
* This includes pushGeometry and pushColor. |
|
||||||
*/ |
|
||||||
public abstract void pushState(); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Restore state from stack (must be pushed first)<br> |
|
||||||
* This includes popColor and popGeometry. |
|
||||||
*/ |
|
||||||
public abstract void popState(); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Store current rotation and translation on stack |
|
||||||
*/ |
|
||||||
public abstract void pushGeometry(); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Restore rotation and translation from stack |
|
||||||
*/ |
|
||||||
public abstract void popGeometry(); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Store color on stack (so it can later be restored) |
|
||||||
*/ |
|
||||||
public abstract void pushColor(); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Restore color from stack (must be pushed first) |
|
||||||
*/ |
|
||||||
public abstract void popColor(); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Render 2D quad with currently set color |
|
||||||
* |
|
||||||
* @param rect drawn rect |
|
||||||
*/ |
|
||||||
public abstract void quad(Rect rect); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Render 2D quad with given color.<br> |
|
||||||
* This may change current drawing color. |
|
||||||
* |
|
||||||
* @param rect rectangle |
|
||||||
* @param color draw color |
|
||||||
*/ |
|
||||||
public abstract void quad(Rect rect, Color color); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Render 2D quad with gradient.<br> |
|
||||||
* This may change current drawing color. |
|
||||||
* |
|
||||||
* @param rect rectangle |
|
||||||
* @param grad gradient |
|
||||||
*/ |
|
||||||
public abstract void quad(Rect rect, Grad grad); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Render textured quad with current color |
|
||||||
* |
|
||||||
* @param rect rectangle to draw |
|
||||||
* @param txquad texture quad |
|
||||||
*/ |
|
||||||
public abstract void quad(Rect rect, TxQuad txquad); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Render textured quad with given color |
|
||||||
* |
|
||||||
* @param rect rectangle to draw |
|
||||||
* @param txquad texture instance |
|
||||||
* @param color color tint |
|
||||||
*/ |
|
||||||
public abstract void quad(Rect rect, TxQuad txquad, Color color); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Setup projection for 2D graphics, using current scren size |
|
||||||
*/ |
|
||||||
public abstract void setupProjection(); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Get backend-flavoured lazy texture |
|
||||||
* |
|
||||||
* @param path path to texture |
|
||||||
* @return the lazy texture |
|
||||||
*/ |
|
||||||
public abstract DeferredTexture getLazyTexture(String path); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Set target fps (for syncing in endFrame() call).<br> |
|
||||||
* With vsync enabled, the target fps may not be met. |
|
||||||
* |
|
||||||
* @param fps requested fps |
|
||||||
*/ |
|
||||||
public abstract void setTargetFps(int fps); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Set fullscreen. The fullscreen state will be changed when possible (eg. |
|
||||||
* at the end of the current frame) and a {@link ViewportChangeEvent} will |
|
||||||
* be fired. |
|
||||||
* |
|
||||||
* @param fs true for fullscreen |
|
||||||
*/ |
|
||||||
public abstract void setFullscreen(boolean fs); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Request fullscreen toggle. See setFullscreen() for more info) |
|
||||||
*/ |
|
||||||
public abstract void switchFullscreen(); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Get fullscreen state (note that methods changing fullscreen may not have |
|
||||||
* immediate effect, so this method may report the old state if the |
|
||||||
* fullscreen state has not yet been changed). |
|
||||||
* |
|
||||||
* @return is fullscreen |
|
||||||
*/ |
|
||||||
public abstract boolean isFullscreen(); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Take screenshot (expensive processing should be done in separate thread |
|
||||||
* when screenshot is saved).<br> |
|
||||||
* This method is utilized by the Screenshot plugin. |
|
||||||
* |
|
||||||
* @return screenshot object |
|
||||||
*/ |
|
||||||
public abstract Screenshot takeScreenshot(); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Start a render frame - clear buffers, prepare rendering context etc. |
|
||||||
*/ |
|
||||||
public abstract void beginFrame(); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* End a render frame: flip buffers, sync to fps... |
|
||||||
*/ |
|
||||||
public abstract void endFrame(); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Set display dimensions |
|
||||||
* |
|
||||||
* @param width display width (pixels) |
|
||||||
* @param height display height (pixels) |
|
||||||
*/ |
|
||||||
public abstract void setSize(int width, int height); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Set window titlebar text |
|
||||||
* |
|
||||||
* @param title titlebar text |
|
||||||
*/ |
|
||||||
public abstract void setTitle(String title); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Enable or disable VSync |
|
||||||
* |
|
||||||
* @param vsync true for vsync enabled |
|
||||||
*/ |
|
||||||
public abstract void setVSync(boolean vsync); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Set window resizable / fixed |
|
||||||
* |
|
||||||
* @param resizable true for resizable |
|
||||||
*/ |
|
||||||
public abstract void setResizable(boolean resizable); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Get screen rect. Should always return the same Rect instance. |
|
||||||
* |
|
||||||
* @return the rect |
|
||||||
*/ |
|
||||||
public abstract Rect getRect(); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Get current FPS (eg. measured by a {@link FpsMeter}) |
|
||||||
* |
|
||||||
* @return current FPS |
|
||||||
*/ |
|
||||||
public abstract long getFps(); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Get screen center. Should always return the same Vect instance. |
|
||||||
* |
|
||||||
* @return screen center. |
|
||||||
*/ |
|
||||||
public abstract Vect getCenter(); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Get screen size. Should always return the same Vect instance. |
|
||||||
* |
|
||||||
* @return size |
|
||||||
*/ |
|
||||||
public abstract Vect getSize(); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* @return screen width |
|
||||||
*/ |
|
||||||
public abstract int getWidth(); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* @return screen height |
|
||||||
*/ |
|
||||||
public abstract int getHeight(); |
|
||||||
} |
|
@ -1,16 +0,0 @@ |
|||||||
package mightypork.gamecore.graphics; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Can be rendered |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public interface Renderable { |
|
||||||
|
|
||||||
/** |
|
||||||
* Render on screen. |
|
||||||
*/ |
|
||||||
void render(); |
|
||||||
|
|
||||||
} |
|
@ -1,34 +0,0 @@ |
|||||||
package mightypork.gamecore.graphics; |
|
||||||
|
|
||||||
|
|
||||||
import java.io.File; |
|
||||||
import java.io.IOException; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* <p> |
|
||||||
* Screenshot object used to save screenshot to a file. The Screenshot object is |
|
||||||
* created by the Graphics module. |
|
||||||
* </p> |
|
||||||
* <p> |
|
||||||
* Screenshot typically takes a byte buffer and converts it to image before |
|
||||||
* saving to file. This image can be cached to speed up repeated saving. |
|
||||||
* </p> |
|
||||||
* <p> |
|
||||||
* Once created (passing byte buffer in constructor), the Screenshot should be |
|
||||||
* safe to process (call the save() method) in separate thread. |
|
||||||
* </p> |
|
||||||
* |
|
||||||
* @author MightyPork |
|
||||||
*/ |
|
||||||
public interface Screenshot { |
|
||||||
|
|
||||||
/** |
|
||||||
* Process byte buffer and write image to a file.<br> |
|
||||||
* Image can be cached for future save. |
|
||||||
* |
|
||||||
* @param file target file |
|
||||||
* @throws IOException on error writing to file |
|
||||||
*/ |
|
||||||
void save(File file) throws IOException; |
|
||||||
} |
|
@ -1,98 +0,0 @@ |
|||||||
package mightypork.gamecore.graphics.fonts; |
|
||||||
|
|
||||||
|
|
||||||
import mightypork.gamecore.graphics.textures.FilterMode; |
|
||||||
import mightypork.gamecore.resources.BaseDeferredResource; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Abstract deferred font stub. |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public abstract class DeferredFont extends BaseDeferredResource implements IFont { |
|
||||||
|
|
||||||
public static enum FontStyle |
|
||||||
{ |
|
||||||
PLAIN(0), BOLD(1), ITALIC(2), BOLD_ITALIC(3); |
|
||||||
|
|
||||||
public int numval; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Font style |
|
||||||
* |
|
||||||
* @param style style index as in awt Font. Not using constants to be |
|
||||||
* independent on awt. |
|
||||||
*/ |
|
||||||
private FontStyle(int style) { |
|
||||||
this.numval = style; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
protected double size = 12; |
|
||||||
protected FontStyle style = FontStyle.PLAIN; |
|
||||||
protected String chars = Glyphs.basic; |
|
||||||
protected FilterMode filter = FilterMode.NEAREST; |
|
||||||
protected boolean antialias = false; |
|
||||||
protected double discardTop = 0; |
|
||||||
protected double discardBottom = 0; |
|
||||||
|
|
||||||
|
|
||||||
public DeferredFont(String resource) { |
|
||||||
super(resource); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public void setSize(double size) |
|
||||||
{ |
|
||||||
this.size = size; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public void setStyle(FontStyle style) |
|
||||||
{ |
|
||||||
this.style = style; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public void setChars(String chars) |
|
||||||
{ |
|
||||||
this.chars = chars; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public void setFilter(FilterMode filter) |
|
||||||
{ |
|
||||||
this.filter = filter; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public void setAntialias(boolean antialias) |
|
||||||
{ |
|
||||||
this.antialias = antialias; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void setDiscardRatio(double top, double bottom) |
|
||||||
{ |
|
||||||
discardTop = top; |
|
||||||
discardBottom = bottom; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public double getTopDiscardRatio() |
|
||||||
{ |
|
||||||
return discardTop; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public double getBottomDiscardRatio() |
|
||||||
{ |
|
||||||
return discardBottom; |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -1,82 +0,0 @@ |
|||||||
package mightypork.gamecore.graphics.fonts; |
|
||||||
|
|
||||||
|
|
||||||
import java.util.HashMap; |
|
||||||
|
|
||||||
import mightypork.gamecore.backends.lwjgl.graphics.font.DeferredLwjglFont; |
|
||||||
import mightypork.gamecore.core.App; |
|
||||||
import mightypork.gamecore.resources.loading.ResourceLoadRequest; |
|
||||||
import mightypork.utils.eventbus.clients.BusNode; |
|
||||||
|
|
||||||
import org.newdawn.slick.opengl.Texture; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Font loader and registry |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public class FontRegistry extends BusNode { |
|
||||||
|
|
||||||
private final HashMap<String, IFont> fonts = new HashMap<>(); |
|
||||||
private final HashMap<String, String> aliases = new HashMap<>(); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Load a {@link DeferredLwjglFont} |
|
||||||
* |
|
||||||
* @param key font key |
|
||||||
* @param font font instance |
|
||||||
*/ |
|
||||||
public void addFont(String key, DeferredFont font) |
|
||||||
{ |
|
||||||
App.bus().send(new ResourceLoadRequest(font)); |
|
||||||
|
|
||||||
fonts.put(key, font); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Add a {@link IFont} to the bank. |
|
||||||
* |
|
||||||
* @param key font key |
|
||||||
* @param font font instance |
|
||||||
*/ |
|
||||||
public void addFont(String key, IFont font) |
|
||||||
{ |
|
||||||
fonts.put(key, font); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Add a font alias. |
|
||||||
* |
|
||||||
* @param alias_key alias key |
|
||||||
* @param font_key font key |
|
||||||
*/ |
|
||||||
public void addAlias(String alias_key, String font_key) |
|
||||||
{ |
|
||||||
aliases.put(alias_key, font_key); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Get a loaded {@link Texture} |
|
||||||
* |
|
||||||
* @param key texture key |
|
||||||
* @return the texture |
|
||||||
*/ |
|
||||||
public IFont getFont(String key) |
|
||||||
{ |
|
||||||
IFont f = fonts.get(key); |
|
||||||
|
|
||||||
if (f == null) f = fonts.get(aliases.get(key)); |
|
||||||
|
|
||||||
if (f == null) { |
|
||||||
throw new RuntimeException("There's no font called " + key + "!"); |
|
||||||
} |
|
||||||
|
|
||||||
return f; |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -1,213 +0,0 @@ |
|||||||
package mightypork.gamecore.graphics.fonts; |
|
||||||
|
|
||||||
|
|
||||||
import mightypork.gamecore.core.App; |
|
||||||
import mightypork.utils.math.AlignX; |
|
||||||
import mightypork.utils.math.color.Color; |
|
||||||
import mightypork.utils.math.color.pal.RGB; |
|
||||||
import mightypork.utils.math.constraints.rect.Rect; |
|
||||||
import mightypork.utils.math.constraints.vect.Vect; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Font renderer |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public class FontRenderer { |
|
||||||
|
|
||||||
private IFont font; |
|
||||||
|
|
||||||
private Color color; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* @param font used font |
|
||||||
*/ |
|
||||||
public FontRenderer(IFont font) { |
|
||||||
this(font, RGB.WHITE); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* @param font used font |
|
||||||
* @param color drawing color |
|
||||||
*/ |
|
||||||
public FontRenderer(IFont font, Color color) { |
|
||||||
this.font = font; |
|
||||||
this.color = color; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Get region needed to draw text at size |
|
||||||
* |
|
||||||
* @param text text to draw |
|
||||||
* @param height drawing height |
|
||||||
* @return taken space (width, height) |
|
||||||
*/ |
|
||||||
public Vect getNeededSpace(String text, double height) |
|
||||||
{ |
|
||||||
return font.getNeededSpace(text).mul(getScale(height)); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Get width needed to draw text at size |
|
||||||
* |
|
||||||
* @param text text to draw |
|
||||||
* @param height drawing height |
|
||||||
* @return needed width |
|
||||||
*/ |
|
||||||
public double getWidth(String text, double height) |
|
||||||
{ |
|
||||||
return getNeededSpace(text, height).x(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
private double getScale(double height) |
|
||||||
{ |
|
||||||
return height / font.getLineHeight(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Change drawing font |
|
||||||
* |
|
||||||
* @param font font to use for drawing |
|
||||||
*/ |
|
||||||
public void setFont(IFont font) |
|
||||||
{ |
|
||||||
this.font = font; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Set drawing color |
|
||||||
* |
|
||||||
* @param color color |
|
||||||
*/ |
|
||||||
public void setColor(Color color) |
|
||||||
{ |
|
||||||
this.color = color; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Draw on screen |
|
||||||
* |
|
||||||
* @param text text to draw |
|
||||||
* @param pos origin (min coord) |
|
||||||
* @param height drawing height |
|
||||||
* @param color drawing color |
|
||||||
*/ |
|
||||||
public void draw(String text, Vect pos, double height, Color color) |
|
||||||
{ |
|
||||||
App.gfx().pushGeometry(); |
|
||||||
|
|
||||||
final double sc = getScale(height); |
|
||||||
|
|
||||||
App.gfx().translate(pos.x(), pos.y()); |
|
||||||
App.gfx().scaleXY(sc); |
|
||||||
|
|
||||||
font.draw(text, color); |
|
||||||
|
|
||||||
App.gfx().popGeometry(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Draw on screen |
|
||||||
* |
|
||||||
* @param text text to draw |
|
||||||
* @param bounds drawing bounds (height for font height, horizontal bounds |
|
||||||
* for align) |
|
||||||
* @param align horizontal alignment (with respect to bounds) |
|
||||||
*/ |
|
||||||
public void draw(String text, Rect bounds, AlignX align) |
|
||||||
{ |
|
||||||
this.draw(text, bounds, align, this.color); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Draw on screen |
|
||||||
* |
|
||||||
* @param text text to draw |
|
||||||
* @param bounds drawing bounds (height for font height, horizontal bounds |
|
||||||
* for align) |
|
||||||
* @param align horizontal alignment (with respect to bounds) |
|
||||||
* @param color drawing color |
|
||||||
*/ |
|
||||||
public void draw(String text, Rect bounds, AlignX align, Color color) |
|
||||||
{ |
|
||||||
Vect start; |
|
||||||
|
|
||||||
switch (align) { |
|
||||||
case LEFT: |
|
||||||
start = bounds.topLeft(); |
|
||||||
break; |
|
||||||
|
|
||||||
case CENTER: |
|
||||||
start = bounds.topCenter(); |
|
||||||
break; |
|
||||||
|
|
||||||
case RIGHT: |
|
||||||
default: |
|
||||||
start = bounds.topRight(); |
|
||||||
break; |
|
||||||
} |
|
||||||
|
|
||||||
draw(text, start, bounds.height().value(), align, color); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Draw on screen |
|
||||||
* |
|
||||||
* @param text text to draw |
|
||||||
* @param pos origin (min coord) |
|
||||||
* @param height drawing height |
|
||||||
* @param align horizontal alignment |
|
||||||
*/ |
|
||||||
public void draw(String text, Vect pos, double height, AlignX align) |
|
||||||
{ |
|
||||||
draw(text, pos, height, align, this.color); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Draw on screen |
|
||||||
* |
|
||||||
* @param text text to draw |
|
||||||
* @param pos origin (min coord) |
|
||||||
* @param height drawing height |
|
||||||
* @param align horizontal alignment |
|
||||||
* @param color drawing color |
|
||||||
*/ |
|
||||||
public void draw(String text, Vect pos, double height, AlignX align, Color color) |
|
||||||
{ |
|
||||||
|
|
||||||
final double w = getWidth(text, height); |
|
||||||
|
|
||||||
Vect start; |
|
||||||
|
|
||||||
switch (align) { |
|
||||||
case LEFT: |
|
||||||
start = pos; |
|
||||||
break; |
|
||||||
|
|
||||||
case CENTER: |
|
||||||
start = pos.sub(w / 2D, 0); |
|
||||||
break; |
|
||||||
|
|
||||||
case RIGHT: |
|
||||||
default: |
|
||||||
start = pos.sub(w, 0); |
|
||||||
break; |
|
||||||
} |
|
||||||
|
|
||||||
draw(text, start, height, color); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -1,76 +0,0 @@ |
|||||||
package mightypork.gamecore.graphics.fonts; |
|
||||||
|
|
||||||
|
|
||||||
import mightypork.utils.math.color.Color; |
|
||||||
import mightypork.utils.math.constraints.vect.Vect; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Interface bor drawable font. |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public interface IFont { |
|
||||||
|
|
||||||
/** |
|
||||||
* Draw without scaling at (0, 0) in given color. |
|
||||||
* |
|
||||||
* @param text text to draw |
|
||||||
* @param color draw color |
|
||||||
*/ |
|
||||||
void draw(String text, Color color); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Get suize needed to render give string |
|
||||||
* |
|
||||||
* @param text string to check |
|
||||||
* @return coord (width, height) |
|
||||||
*/ |
|
||||||
Vect getNeededSpace(String text); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* @return font height |
|
||||||
*/ |
|
||||||
int getLineHeight(); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* @param text texted text |
|
||||||
* @return space needed |
|
||||||
*/ |
|
||||||
int getWidth(String text); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* @return specified font size |
|
||||||
*/ |
|
||||||
int getFontSize(); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Set what vertical ratio of the font size is blank and should be cut off |
|
||||||
* when rendering |
|
||||||
* |
|
||||||
* @param top top ratio (0-1) |
|
||||||
* @param bottom bottom ratio (0-1) |
|
||||||
*/ |
|
||||||
void setDiscardRatio(double top, double bottom); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Get top discard ratio (blank unused space) |
|
||||||
* |
|
||||||
* @return ratio |
|
||||||
*/ |
|
||||||
double getTopDiscardRatio(); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Get bottom discard ratio (blank unused space) |
|
||||||
* |
|
||||||
* @return ratio |
|
||||||
*/ |
|
||||||
double getBottomDiscardRatio(); |
|
||||||
} |
|
@ -1,57 +0,0 @@ |
|||||||
package mightypork.gamecore.graphics.textures; |
|
||||||
|
|
||||||
|
|
||||||
import mightypork.gamecore.resources.BaseDeferredResource; |
|
||||||
import mightypork.gamecore.resources.loading.MustLoadInRenderingContext; |
|
||||||
import mightypork.utils.annotations.Alias; |
|
||||||
import mightypork.utils.math.constraints.rect.Rect; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Deferred texture (to be extended by backend texture) |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
@Alias(name = "Texture") |
|
||||||
@MustLoadInRenderingContext |
|
||||||
public abstract class DeferredTexture extends BaseDeferredResource implements ITexture { |
|
||||||
|
|
||||||
protected FilterMode filter = FilterMode.NEAREST; |
|
||||||
protected WrapMode wrap = WrapMode.CLAMP; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* @param resourcePath resource path |
|
||||||
*/ |
|
||||||
public DeferredTexture(String resourcePath) { |
|
||||||
super(resourcePath); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public TxQuad makeQuad(Rect uvs) |
|
||||||
{ |
|
||||||
return new TxQuad(this, uvs); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void setFilter(FilterMode filterMin) |
|
||||||
{ |
|
||||||
this.filter = filterMin; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void setWrap(WrapMode wrapping) |
|
||||||
{ |
|
||||||
this.wrap = wrapping; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public QuadGrid grid(int x, int y) |
|
||||||
{ |
|
||||||
return new QuadGrid(this, x, y); |
|
||||||
} |
|
||||||
} |
|
@ -1,12 +0,0 @@ |
|||||||
package mightypork.gamecore.graphics.textures; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Texture filtering mode |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public enum FilterMode |
|
||||||
{ |
|
||||||
LINEAR, NEAREST; |
|
||||||
} |
|
@ -1,64 +0,0 @@ |
|||||||
package mightypork.gamecore.graphics.textures; |
|
||||||
|
|
||||||
|
|
||||||
import mightypork.utils.interfaces.Destroyable; |
|
||||||
import mightypork.utils.math.constraints.rect.Rect; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Texture interface, backend independent |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public interface ITexture extends Destroyable { |
|
||||||
|
|
||||||
/** |
|
||||||
* Set filter for scaling |
|
||||||
* |
|
||||||
* @param filter filter |
|
||||||
*/ |
|
||||||
void setFilter(FilterMode filter); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* @param wrapping wrap mode |
|
||||||
*/ |
|
||||||
void setWrap(WrapMode wrapping); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Get a quad from this texture of given position/size |
|
||||||
* |
|
||||||
* @param uvs quad rect |
|
||||||
* @return the quad |
|
||||||
*/ |
|
||||||
TxQuad makeQuad(Rect uvs); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Get a grid for given number of tiles |
|
||||||
* |
|
||||||
* @param x horizontal tile count |
|
||||||
* @param y vertical tile count |
|
||||||
* @return grid |
|
||||||
*/ |
|
||||||
QuadGrid grid(int x, int y); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* @return source image width (corresponding to width01) |
|
||||||
*/ |
|
||||||
int getImageWidth(); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* @return source image height (corresponding to height01) |
|
||||||
*/ |
|
||||||
int getImageHeight(); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* @return true if the image is RGBA |
|
||||||
*/ |
|
||||||
boolean hasAlpha(); |
|
||||||
} |
|
@ -1,92 +0,0 @@ |
|||||||
package mightypork.gamecore.graphics.textures; |
|
||||||
|
|
||||||
|
|
||||||
import mightypork.utils.math.constraints.rect.Rect; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* {@link TxQuad} and {@link TxSheet} building utility |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public class QuadGrid { |
|
||||||
|
|
||||||
private final ITexture tx; |
|
||||||
private final int txHeight; |
|
||||||
private final int txWidth; |
|
||||||
private final double tileW; |
|
||||||
private final double tileH; |
|
||||||
|
|
||||||
|
|
||||||
public QuadGrid(ITexture tx, int tilesX, int tilesY) { |
|
||||||
this.tx = tx; |
|
||||||
this.txWidth = tilesX; |
|
||||||
this.txHeight = tilesY; |
|
||||||
this.tileW = 1D / tilesX; |
|
||||||
this.tileH = 1D / tilesY; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Make square quad at given coords (one grid cell) |
|
||||||
* |
|
||||||
* @param x x coordinate (cells) |
|
||||||
* @param y y coordinate (cells) |
|
||||||
* @return the quad |
|
||||||
*/ |
|
||||||
public TxQuad makeQuad(double x, double y) |
|
||||||
{ |
|
||||||
if (x < 0 || x >= txWidth || y < 0 || y >= txHeight) { |
|
||||||
throw new IndexOutOfBoundsException("Requested invalid txquad coordinates."); |
|
||||||
} |
|
||||||
|
|
||||||
return makeQuad(x, y, 1, 1); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Make square quad at given coords, with arbitrary size. Coordinates are |
|
||||||
* multiples of cell size. |
|
||||||
* |
|
||||||
* @param x x coordinate (cells) |
|
||||||
* @param y y coordinate (cells) |
|
||||||
* @param width width (cells) |
|
||||||
* @param height height (cells) |
|
||||||
* @return the quad |
|
||||||
*/ |
|
||||||
public TxQuad makeQuad(double x, double y, double width, double height) |
|
||||||
{ |
|
||||||
if (x < 0 || x >= txWidth || y < 0 || y >= txHeight) { |
|
||||||
throw new IndexOutOfBoundsException("Requested invalid txquad coordinates."); |
|
||||||
} |
|
||||||
|
|
||||||
if (x + width > txWidth || y + height > txHeight) { |
|
||||||
throw new IndexOutOfBoundsException("Requested invalid txquad size (would go beyond texture size)."); |
|
||||||
} |
|
||||||
|
|
||||||
return tx.makeQuad(Rect.make(tileW * x, tileH * y, tileW * width, tileH * height)); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Make a sheet. |
|
||||||
* |
|
||||||
* @param x x origin coordinate (cells) |
|
||||||
* @param y y origin coordinate (cells) |
|
||||||
* @param width width (cells) |
|
||||||
* @param height height (cells) |
|
||||||
* @return the sheet |
|
||||||
*/ |
|
||||||
public TxSheet makeSheet(double x, double y, double width, double height) |
|
||||||
{ |
|
||||||
if (x < 0 || x >= txWidth || y < 0 || y >= txHeight) { |
|
||||||
throw new IndexOutOfBoundsException("Requested invalid txquad coordinates."); |
|
||||||
} |
|
||||||
|
|
||||||
if (x + width > txWidth || y + height > txHeight) { |
|
||||||
throw new IndexOutOfBoundsException("Requested invalid txsheet size (would go beyond texture size)."); |
|
||||||
} |
|
||||||
|
|
||||||
return makeQuad(x, y).makeSheet(width, height); |
|
||||||
} |
|
||||||
} |
|
@ -1,143 +0,0 @@ |
|||||||
package mightypork.gamecore.graphics.textures; |
|
||||||
|
|
||||||
|
|
||||||
import java.util.HashMap; |
|
||||||
import java.util.Map; |
|
||||||
|
|
||||||
import mightypork.gamecore.core.App; |
|
||||||
import mightypork.gamecore.resources.loading.ResourceLoadRequest; |
|
||||||
import mightypork.utils.exceptions.KeyAlreadyExistsException; |
|
||||||
import mightypork.utils.math.constraints.rect.Rect; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Texture storage and quad/sheet registry. Quads and Sheets are interchangeable |
|
||||||
* once registered. |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public class TextureRegistry { |
|
||||||
|
|
||||||
private final Map<String, ITexture> textures = new HashMap<>(); |
|
||||||
private final Map<String, TxSheet> sheets = new HashMap<>(); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Load a texture from resource, without a key. This texture will not be |
|
||||||
* added to the bank. |
|
||||||
* |
|
||||||
* @param resourcePath resource path of the texture |
|
||||||
* @param filter |
|
||||||
* @param wrap |
|
||||||
* @return texture reference |
|
||||||
*/ |
|
||||||
public ITexture addTexture(String resourcePath, FilterMode filter, WrapMode wrap) |
|
||||||
{ |
|
||||||
return addTexture(resourcePath, resourcePath, filter, wrap); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Load a texture from resource; if key is not null, the texture will be |
|
||||||
* added to the bank. |
|
||||||
* |
|
||||||
* @param key texture key, can be null. |
|
||||||
* @param resourcePath resource path of the texture |
|
||||||
* @param filter |
|
||||||
* @param wrap |
|
||||||
* @return texture reference |
|
||||||
*/ |
|
||||||
public ITexture addTexture(String key, String resourcePath, FilterMode filter, WrapMode wrap) |
|
||||||
{ |
|
||||||
if (key != null) if (textures.containsKey(key)) throw new KeyAlreadyExistsException(); |
|
||||||
|
|
||||||
final DeferredTexture texture = App.gfx().getLazyTexture(resourcePath); |
|
||||||
texture.setFilter(filter); |
|
||||||
texture.setWrap(wrap); |
|
||||||
|
|
||||||
App.bus().send(new ResourceLoadRequest(texture)); |
|
||||||
|
|
||||||
if (key != null) { |
|
||||||
textures.put(key, texture); |
|
||||||
add(key, texture.makeQuad(Rect.ONE)); |
|
||||||
} |
|
||||||
|
|
||||||
return texture; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Add already created quad to the quad registry |
|
||||||
* |
|
||||||
* @param quadKey key |
|
||||||
* @param quad quad to add |
|
||||||
*/ |
|
||||||
public void add(String quadKey, TxQuad quad) |
|
||||||
{ |
|
||||||
if (sheets.containsKey(quadKey)) throw new KeyAlreadyExistsException(); |
|
||||||
|
|
||||||
sheets.put(quadKey, quad.makeSheet(1, 1)); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Add an already created sheet |
|
||||||
* |
|
||||||
* @param sheetKey key |
|
||||||
* @param sheet sheet to add |
|
||||||
*/ |
|
||||||
public void add(String sheetKey, TxSheet sheet) |
|
||||||
{ |
|
||||||
if (sheets.containsKey(sheetKey)) throw new KeyAlreadyExistsException(); |
|
||||||
|
|
||||||
sheets.put(sheetKey, sheet); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Get a {@link TxQuad} for key; if it was added as sheet, the first quad |
|
||||||
* ofthe sheet is returned. |
|
||||||
* |
|
||||||
* @param key quad key |
|
||||||
* @return the quad |
|
||||||
*/ |
|
||||||
public TxQuad getQuad(String key) |
|
||||||
{ |
|
||||||
return getSheet(key).getQuad(0); // get the first
|
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Get a loaded {@link ITexture} |
|
||||||
* |
|
||||||
* @param key texture key |
|
||||||
* @return the texture |
|
||||||
*/ |
|
||||||
public ITexture getTexture(String key) |
|
||||||
{ |
|
||||||
final ITexture tx = textures.get(key); |
|
||||||
|
|
||||||
if (tx == null) throw new RuntimeException("There's no texture called \"" + key + "\"!"); |
|
||||||
|
|
||||||
return tx; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Get a {@link TxSheet} for key |
|
||||||
* |
|
||||||
* @param key sheet key |
|
||||||
* @return the sheet |
|
||||||
*/ |
|
||||||
public TxSheet getSheet(String key) |
|
||||||
{ |
|
||||||
final TxSheet sh = sheets.get(key); |
|
||||||
|
|
||||||
if (sh == null) { |
|
||||||
throw new RuntimeException("There's no sheet called \"" + key + "\"!"); |
|
||||||
} |
|
||||||
|
|
||||||
return sh; |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -1,164 +0,0 @@ |
|||||||
package mightypork.gamecore.graphics.textures; |
|
||||||
|
|
||||||
|
|
||||||
import mightypork.utils.math.constraints.rect.Rect; |
|
||||||
import mightypork.utils.math.constraints.rect.RectConst; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Texture Quad (describing a part of a texture) |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public class TxQuad { |
|
||||||
|
|
||||||
/** The texture */ |
|
||||||
public final ITexture tx; |
|
||||||
/** Coords in texture (0-1) */ |
|
||||||
public final RectConst uvs; |
|
||||||
|
|
||||||
private boolean flipX; |
|
||||||
private boolean flipY; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* TxQuad from origin and size in pixels |
|
||||||
* |
|
||||||
* @param tx texture |
|
||||||
* @param xPx left top X (0-1) |
|
||||||
* @param yPx left top Y (0-1) |
|
||||||
* @param widthPx area width (0-1) |
|
||||||
* @param heightPx area height (0-1) |
|
||||||
* @return new TxQuad |
|
||||||
*/ |
|
||||||
public static TxQuad fromSizePx(ITexture tx, double xPx, double yPx, double widthPx, double heightPx) |
|
||||||
{ |
|
||||||
final double w = tx.getImageWidth(); |
|
||||||
final double h = tx.getImageHeight(); |
|
||||||
|
|
||||||
return fromSize(tx, xPx / w, yPx / h, widthPx / w, heightPx / h); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* TxQuad from origin and size 0-1 |
|
||||||
* |
|
||||||
* @param tx texture |
|
||||||
* @param x1 left top X (0-1) |
|
||||||
* @param y1 left top Y (0-1) |
|
||||||
* @param width area width (0-1) |
|
||||||
* @param height area height (0-1) |
|
||||||
* @return new TxQuad |
|
||||||
*/ |
|
||||||
public static TxQuad fromSize(ITexture tx, double x1, double y1, double width, double height) |
|
||||||
{ |
|
||||||
return new TxQuad(tx, x1, y1, x1 + width, y1 + height); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Make of coords |
|
||||||
* |
|
||||||
* @param tx texture |
|
||||||
* @param x1 left top X (0-1) |
|
||||||
* @param y1 left top Y (0-1) |
|
||||||
* @param x2 right bottom X (0-1) |
|
||||||
* @param y2 right bottom Y (0-1) |
|
||||||
*/ |
|
||||||
public TxQuad(ITexture tx, double x1, double y1, double x2, double y2) { |
|
||||||
this(tx, Rect.make(x1, y1, x2, y2)); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* @param tx Texture |
|
||||||
* @param uvs Rect of texture UVs (0-1); will be frozen. |
|
||||||
*/ |
|
||||||
public TxQuad(ITexture tx, Rect uvs) { |
|
||||||
this.tx = tx; |
|
||||||
this.uvs = uvs.freeze(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Clone another |
|
||||||
* |
|
||||||
* @param txQuad a copied quad |
|
||||||
*/ |
|
||||||
public TxQuad(TxQuad txQuad) { |
|
||||||
this.tx = txQuad.tx; |
|
||||||
this.uvs = txQuad.uvs; |
|
||||||
this.flipX = txQuad.flipX; |
|
||||||
this.flipY = txQuad.flipY; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Get copy |
|
||||||
* |
|
||||||
* @return copy of this |
|
||||||
*/ |
|
||||||
public TxQuad copy() |
|
||||||
{ |
|
||||||
return new TxQuad(this); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Make a sheet starting with this quad, spannign to right and down. |
|
||||||
* |
|
||||||
* @param width sheet width |
|
||||||
* @param height sheet height |
|
||||||
* @return sheet |
|
||||||
*/ |
|
||||||
public TxSheet makeSheet(double width, double height) |
|
||||||
{ |
|
||||||
return new TxSheet(this, (int) Math.round(width), (int) Math.round(height)); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* @return copy flipped X |
|
||||||
*/ |
|
||||||
public TxQuad flipX() |
|
||||||
{ |
|
||||||
final TxQuad copy = new TxQuad(this); |
|
||||||
copy.flipX ^= true; |
|
||||||
return copy; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* @return copy flipped Y |
|
||||||
*/ |
|
||||||
public TxQuad flipY() |
|
||||||
{ |
|
||||||
final TxQuad copy = new TxQuad(this); |
|
||||||
copy.flipY ^= true; |
|
||||||
return copy; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public boolean isFlippedY() |
|
||||||
{ |
|
||||||
return flipY; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public boolean isFlippedX() |
|
||||||
{ |
|
||||||
return flipX; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Use the same flit/other attributes as the original txQuad |
|
||||||
* |
|
||||||
* @param original |
|
||||||
*/ |
|
||||||
public void dupeAttrs(TxQuad original) |
|
||||||
{ |
|
||||||
this.flipX = original.flipX; |
|
||||||
this.flipY = original.flipY; |
|
||||||
} |
|
||||||
} |
|
@ -1,121 +0,0 @@ |
|||||||
package mightypork.gamecore.graphics.textures; |
|
||||||
|
|
||||||
|
|
||||||
import java.util.Random; |
|
||||||
|
|
||||||
import mightypork.utils.logging.Log; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Basic sprite sheet |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public class TxSheet { |
|
||||||
|
|
||||||
private final TxQuad original; |
|
||||||
private final TxQuad[] sprites; |
|
||||||
private final int width; |
|
||||||
|
|
||||||
private final Random rand = new Random(); |
|
||||||
private final Random randForSeed = new Random(); |
|
||||||
private final int count; |
|
||||||
|
|
||||||
|
|
||||||
public TxSheet(TxQuad tx, int width, int height) { |
|
||||||
this.original = tx; |
|
||||||
this.width = width; |
|
||||||
this.count = width * height; |
|
||||||
|
|
||||||
this.sprites = new TxQuad[count]; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* @return number of quads |
|
||||||
*/ |
|
||||||
public int getQuadCount() |
|
||||||
{ |
|
||||||
return count; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Get a quad based on ratio 0-1 (0: first, 1: last) |
|
||||||
* |
|
||||||
* @param ratio ratio |
|
||||||
* @return quad |
|
||||||
*/ |
|
||||||
public TxQuad getQuad(double ratio) |
|
||||||
{ |
|
||||||
return getQuad((int) Math.round((count - 1) * ratio)); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Get quad of index |
|
||||||
* |
|
||||||
* @param index index |
|
||||||
* @return the quad |
|
||||||
*/ |
|
||||||
public TxQuad getQuad(int index) |
|
||||||
{ |
|
||||||
if (index < 0 || index >= count) { |
|
||||||
Log.w("Index out of bounds: " + index + ", allowed: 0.." + count); |
|
||||||
index = index % count; |
|
||||||
} |
|
||||||
|
|
||||||
// lazy - init only when needed
|
|
||||||
if (sprites[index] == null) { |
|
||||||
final int x = index % width; |
|
||||||
final int y = index / width; |
|
||||||
|
|
||||||
final double origW = original.uvs.width().value(); |
|
||||||
final double origH = original.uvs.height().value(); |
|
||||||
|
|
||||||
final TxQuad txq = new TxQuad(original.tx, original.uvs.move(x * origW, y * origH)); |
|
||||||
txq.dupeAttrs(original); |
|
||||||
|
|
||||||
sprites[index] = txq; |
|
||||||
} |
|
||||||
|
|
||||||
return sprites[index]; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Get entirely random TxQuad from this sheet |
|
||||||
* |
|
||||||
* @return the picked quad |
|
||||||
*/ |
|
||||||
public TxQuad getRandomQuad() |
|
||||||
{ |
|
||||||
return getQuad(rand.nextInt(count)); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Get random TxQuad from this sheet |
|
||||||
* |
|
||||||
* @param seed random number generator seed |
|
||||||
* @return the picked quad |
|
||||||
*/ |
|
||||||
public TxQuad getRandomQuad(long seed) |
|
||||||
{ |
|
||||||
randForSeed.setSeed(seed); |
|
||||||
return getQuad(randForSeed.nextInt(count)); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Get random TxQuad from this sheet |
|
||||||
* |
|
||||||
* @param seed random number generator seed (double will be converted to |
|
||||||
* long) |
|
||||||
* @return the picked quad |
|
||||||
*/ |
|
||||||
public TxQuad getRandomQuad(double seed) |
|
||||||
{ |
|
||||||
return getRandomQuad(Double.doubleToLongBits(seed)); |
|
||||||
} |
|
||||||
} |
|
@ -1,12 +0,0 @@ |
|||||||
package mightypork.gamecore.graphics.textures; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Texture wrap mode |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public enum WrapMode |
|
||||||
{ |
|
||||||
CLAMP, REPEAT; |
|
||||||
} |
|
@ -1,54 +0,0 @@ |
|||||||
package mightypork.gamecore.gui; |
|
||||||
|
|
||||||
|
|
||||||
import mightypork.utils.interfaces.Enableable; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Triggered action |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public abstract class Action implements Runnable, Enableable { |
|
||||||
|
|
||||||
private boolean enabled = true; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Enable the action |
|
||||||
* |
|
||||||
* @param enable true to enable |
|
||||||
*/ |
|
||||||
@Override |
|
||||||
public final void setEnabled(boolean enable) |
|
||||||
{ |
|
||||||
this.enabled = enable; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* @return true if this action is enabled. |
|
||||||
*/ |
|
||||||
@Override |
|
||||||
public final boolean isEnabled() |
|
||||||
{ |
|
||||||
return enabled; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Run the action, if it's enabled. |
|
||||||
*/ |
|
||||||
@Override |
|
||||||
public final void run() |
|
||||||
{ |
|
||||||
if (enabled) execute(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Do the work. |
|
||||||
*/ |
|
||||||
protected abstract void execute(); |
|
||||||
|
|
||||||
} |
|
@ -1,38 +0,0 @@ |
|||||||
package mightypork.gamecore.gui; |
|
||||||
|
|
||||||
|
|
||||||
import java.util.HashSet; |
|
||||||
import java.util.Set; |
|
||||||
|
|
||||||
import mightypork.utils.interfaces.Enableable; |
|
||||||
|
|
||||||
|
|
||||||
public class ActionGroup implements Enableable { |
|
||||||
|
|
||||||
private boolean enabled = true; |
|
||||||
|
|
||||||
private final Set<Enableable> groupMembers = new HashSet<>(); |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void setEnabled(boolean yes) |
|
||||||
{ |
|
||||||
enabled = yes; |
|
||||||
for (final Enableable e : groupMembers) |
|
||||||
e.setEnabled(yes); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public boolean isEnabled() |
|
||||||
{ |
|
||||||
return enabled; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public void add(Enableable action) |
|
||||||
{ |
|
||||||
groupMembers.add(action); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -1,17 +0,0 @@ |
|||||||
package mightypork.gamecore.gui; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Element that can be assigned an action (ie. button); |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public interface ActionTrigger { |
|
||||||
|
|
||||||
/** |
|
||||||
* Assign an action |
|
||||||
* |
|
||||||
* @param action action |
|
||||||
*/ |
|
||||||
void setAction(Action action); |
|
||||||
} |
|
@ -1,169 +0,0 @@ |
|||||||
package mightypork.gamecore.gui.components; |
|
||||||
|
|
||||||
|
|
||||||
import mightypork.gamecore.core.App; |
|
||||||
import mightypork.gamecore.graphics.Renderable; |
|
||||||
import mightypork.gamecore.gui.events.LayoutChangeEvent; |
|
||||||
import mightypork.gamecore.gui.events.LayoutChangeListener; |
|
||||||
import mightypork.utils.Support; |
|
||||||
import mightypork.utils.annotations.Stub; |
|
||||||
import mightypork.utils.interfaces.Enableable; |
|
||||||
import mightypork.utils.logging.Log; |
|
||||||
import mightypork.utils.math.color.Color; |
|
||||||
import mightypork.utils.math.constraints.num.Num; |
|
||||||
import mightypork.utils.math.constraints.rect.Rect; |
|
||||||
import mightypork.utils.math.constraints.rect.RectBound; |
|
||||||
import mightypork.utils.math.constraints.rect.caching.AbstractRectCache; |
|
||||||
import mightypork.utils.math.constraints.rect.proxy.RectProxy; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* {@link Renderable} with pluggable context. When caching is enabled, the |
|
||||||
* layout update can be triggered by firing the {@link LayoutChangeEvent}. |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public abstract class BaseComponent extends AbstractRectCache implements Component, LayoutChangeListener, Enableable { |
|
||||||
|
|
||||||
private Rect source; |
|
||||||
private boolean visible = true; |
|
||||||
private boolean enabled = true; |
|
||||||
private int indirectDisableLevel = 0; |
|
||||||
|
|
||||||
private Num alphaMul = Num.ONE; |
|
||||||
|
|
||||||
|
|
||||||
public BaseComponent() { |
|
||||||
enableCaching(false); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void setRect(RectBound rect) |
|
||||||
{ |
|
||||||
this.source = new RectProxy(rect); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public final boolean isVisible() |
|
||||||
{ |
|
||||||
return visible; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public final void setVisible(boolean visible) |
|
||||||
{ |
|
||||||
this.visible = visible; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public final Rect getCacheSource() |
|
||||||
{ |
|
||||||
return source.round(); // round to avoid visual artifacts in fonts and such
|
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public final void render() |
|
||||||
{ |
|
||||||
if (!isVisible()) return; |
|
||||||
|
|
||||||
Color.pushAlpha(alphaMul); |
|
||||||
renderComponent(); |
|
||||||
Color.popAlpha(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public final void onLayoutChanged() |
|
||||||
{ |
|
||||||
try { |
|
||||||
poll(); |
|
||||||
} catch (final NullPointerException e) { |
|
||||||
Log.e("Component is missing a bounding rect, at: " + Support.str(getClass())); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public final void onConstraintChanged() |
|
||||||
{ |
|
||||||
updateLayout(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public final boolean isMouseOver() |
|
||||||
{ |
|
||||||
return App.input().getMousePos().isInside(this); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Draw the component (it's visible) |
|
||||||
*/ |
|
||||||
protected abstract void renderComponent(); |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
@Stub |
|
||||||
public void updateLayout() |
|
||||||
{ |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void setEnabled(boolean yes) |
|
||||||
{ |
|
||||||
enabled = yes; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public boolean isEnabled() |
|
||||||
{ |
|
||||||
return enabled && isIndirectlyEnabled(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public final void setAlpha(Num alpha) |
|
||||||
{ |
|
||||||
this.alphaMul = alpha; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public final void setAlpha(double alpha) |
|
||||||
{ |
|
||||||
this.alphaMul = Num.make(alpha); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void setIndirectlyEnabled(boolean yes) |
|
||||||
{ |
|
||||||
if (!yes) { |
|
||||||
indirectDisableLevel++; |
|
||||||
} else { |
|
||||||
if (indirectDisableLevel > 0) indirectDisableLevel--; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public boolean isIndirectlyEnabled() |
|
||||||
{ |
|
||||||
return indirectDisableLevel == 0; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public boolean isDirectlyEnabled() |
|
||||||
{ |
|
||||||
return enabled; |
|
||||||
} |
|
||||||
} |
|
@ -1,95 +0,0 @@ |
|||||||
package mightypork.gamecore.gui.components; |
|
||||||
|
|
||||||
|
|
||||||
import mightypork.utils.interfaces.Enableable; |
|
||||||
import mightypork.utils.interfaces.Hideable; |
|
||||||
import mightypork.utils.math.constraints.num.Num; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Basic UI component interface
|
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public interface Component extends Enableable, Hideable, PluggableRenderable { |
|
||||||
|
|
||||||
/** |
|
||||||
* Render the component, if it is visible. |
|
||||||
*/ |
|
||||||
@Override |
|
||||||
void render(); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* The bounding rect was changed. The component should now update any cached |
|
||||||
* constraints derived from it. |
|
||||||
*/ |
|
||||||
void updateLayout(); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* @return true if mouse is currently over the component |
|
||||||
*/ |
|
||||||
boolean isMouseOver(); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Set alpha multiplier for this and nested components |
|
||||||
* |
|
||||||
* @param alpha alpha multiplier (dynamic value) |
|
||||||
*/ |
|
||||||
void setAlpha(Num alpha); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Set alpha multiplier for this and nested components |
|
||||||
* |
|
||||||
* @param alpha alpha multiplier (constant value) |
|
||||||
*/ |
|
||||||
void setAlpha(double alpha); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Indirectly enable / disable, used for nested hierarchies.<br> |
|
||||||
* When component is twice indirectly disabled, it needs to be twice |
|
||||||
* indirectly enabled to be enabled again. |
|
||||||
* |
|
||||||
* @param yes |
|
||||||
*/ |
|
||||||
void setIndirectlyEnabled(boolean yes); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Check if the compionent is not indirectly disabled. May still be directly |
|
||||||
* disabled. |
|
||||||
* |
|
||||||
* @return indirectly enabled |
|
||||||
*/ |
|
||||||
boolean isIndirectlyEnabled(); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Check if the component is directly enabled (set by setEnabled()). May |
|
||||||
* still be indirectly disabled. |
|
||||||
* |
|
||||||
* @return directly enabled |
|
||||||
*/ |
|
||||||
boolean isDirectlyEnabled(); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Set directly enabled (must be both directly and indirectly enabled to be |
|
||||||
* enabled completely) |
|
||||||
*/ |
|
||||||
@Override |
|
||||||
public void setEnabled(boolean yes); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Check if the component is both directly and indirectly enabled |
|
||||||
* |
|
||||||
* @return enabled |
|
||||||
*/ |
|
||||||
@Override |
|
||||||
public boolean isEnabled(); |
|
||||||
} |
|
@ -1,7 +0,0 @@ |
|||||||
package mightypork.gamecore.gui.components; |
|
||||||
|
|
||||||
|
|
||||||
public interface DynamicWidthComponent extends Component { |
|
||||||
|
|
||||||
double computeWidth(double height); |
|
||||||
} |
|
@ -1,15 +0,0 @@ |
|||||||
package mightypork.gamecore.gui.components; |
|
||||||
|
|
||||||
|
|
||||||
import mightypork.utils.eventbus.clients.ToggleableClient; |
|
||||||
import mightypork.utils.interfaces.Enableable; |
|
||||||
|
|
||||||
|
|
||||||
public abstract class InputComponent extends BaseComponent implements Enableable, ToggleableClient { |
|
||||||
|
|
||||||
@Override |
|
||||||
public boolean isListening() |
|
||||||
{ |
|
||||||
return isEnabled(); |
|
||||||
} |
|
||||||
} |
|
@ -1,122 +0,0 @@ |
|||||||
package mightypork.gamecore.gui.components; |
|
||||||
|
|
||||||
|
|
||||||
import java.util.Collection; |
|
||||||
import java.util.LinkedList; |
|
||||||
|
|
||||||
import mightypork.utils.eventbus.clients.ClientHub; |
|
||||||
import mightypork.utils.eventbus.clients.DelegatingList; |
|
||||||
import mightypork.utils.math.constraints.rect.RectBound; |
|
||||||
|
|
||||||
|
|
||||||
public abstract class LayoutComponent extends BaseComponent implements ClientHub { |
|
||||||
|
|
||||||
private final DelegatingList clientList; |
|
||||||
final LinkedList<Component> components = new LinkedList<>(); |
|
||||||
|
|
||||||
|
|
||||||
public LayoutComponent(RectBound context) { |
|
||||||
this.clientList = new DelegatingList(); |
|
||||||
setRect(context); |
|
||||||
enableCaching(true); // layout is typically updated only when screen resizes.
|
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public LayoutComponent() { |
|
||||||
this(null); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public Collection<Object> getChildClients() |
|
||||||
{ |
|
||||||
return clientList; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public boolean doesDelegate() |
|
||||||
{ |
|
||||||
return clientList.doesDelegate(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public boolean isListening() |
|
||||||
{ |
|
||||||
return clientList.isListening(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void addChildClient(Object client) |
|
||||||
{ |
|
||||||
clientList.add(client); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void removeChildClient(Object client) |
|
||||||
{ |
|
||||||
clientList.remove(client); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void setEnabled(boolean yes) |
|
||||||
{ |
|
||||||
if (isDirectlyEnabled() != yes) { |
|
||||||
super.setEnabled(yes); |
|
||||||
|
|
||||||
for (final Component c : components) { |
|
||||||
c.setIndirectlyEnabled(yes); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Connect to bus and add to element list |
|
||||||
* |
|
||||||
* @param component added component, whose context has already been set. |
|
||||||
*/ |
|
||||||
protected final void attach(Component component) |
|
||||||
{ |
|
||||||
if (component == null) return; |
|
||||||
if (component == this) { |
|
||||||
throw new IllegalArgumentException("Uruboros. (infinite recursion evaded)"); |
|
||||||
} |
|
||||||
|
|
||||||
components.add(component); |
|
||||||
addChildClient(component); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void renderComponent() |
|
||||||
{ |
|
||||||
for (final Component cmp : components) { |
|
||||||
cmp.render(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void updateLayout() |
|
||||||
{ |
|
||||||
for (final Component cmp : components) { |
|
||||||
cmp.updateLayout(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void setIndirectlyEnabled(boolean yes) |
|
||||||
{ |
|
||||||
super.setIndirectlyEnabled(yes); |
|
||||||
|
|
||||||
for (final Component cmp : components) { |
|
||||||
cmp.setIndirectlyEnabled(yes); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
@ -1,77 +0,0 @@ |
|||||||
package mightypork.gamecore.gui.components; |
|
||||||
|
|
||||||
|
|
||||||
import mightypork.utils.math.constraints.num.Num; |
|
||||||
import mightypork.utils.math.constraints.rect.Rect; |
|
||||||
import mightypork.utils.math.constraints.rect.RectBound; |
|
||||||
import mightypork.utils.math.constraints.vect.Vect; |
|
||||||
import mightypork.utils.math.constraints.vect.proxy.VectAdapter; |
|
||||||
|
|
||||||
|
|
||||||
public abstract class LinearComponent extends BaseComponent implements DynamicWidthComponent { |
|
||||||
|
|
||||||
private final Rect rect = new Rect() { |
|
||||||
|
|
||||||
@Override |
|
||||||
public Vect size() |
|
||||||
{ |
|
||||||
return new Vect() { |
|
||||||
|
|
||||||
@Override |
|
||||||
public double x() |
|
||||||
{ |
|
||||||
return computeWidth(y()); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public double y() |
|
||||||
{ |
|
||||||
return height.value(); |
|
||||||
} |
|
||||||
|
|
||||||
}; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public Vect origin() |
|
||||||
{ |
|
||||||
return new VectAdapter() { |
|
||||||
|
|
||||||
@Override |
|
||||||
protected Vect getSource() |
|
||||||
{ |
|
||||||
return origin; |
|
||||||
} |
|
||||||
}; |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
private Vect origin; |
|
||||||
private Num height; |
|
||||||
|
|
||||||
|
|
||||||
public LinearComponent() { |
|
||||||
super.setRect(rect); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void setRect(RectBound rect) |
|
||||||
{ |
|
||||||
throw new RuntimeException("Cannot assign a rect to a linear component. Set origin and height instead."); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public void setHeight(Num height) |
|
||||||
{ |
|
||||||
this.height = height; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public void setOrigin(Vect origin) |
|
||||||
{ |
|
||||||
this.origin = origin; |
|
||||||
} |
|
||||||
} |
|
@ -1,28 +0,0 @@ |
|||||||
package mightypork.gamecore.gui.components; |
|
||||||
|
|
||||||
|
|
||||||
import mightypork.gamecore.graphics.Renderable; |
|
||||||
import mightypork.utils.math.constraints.rect.PluggableRectBound; |
|
||||||
import mightypork.utils.math.constraints.rect.Rect; |
|
||||||
import mightypork.utils.math.constraints.rect.RectBound; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Renderable that can be assigned different context |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public interface PluggableRenderable extends Renderable, PluggableRectBound { |
|
||||||
|
|
||||||
@Override |
|
||||||
void render(); |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
Rect getRect(); |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
void setRect(RectBound rect); |
|
||||||
|
|
||||||
} |
|
@ -1,49 +0,0 @@ |
|||||||
package mightypork.gamecore.gui.components.input; |
|
||||||
|
|
||||||
|
|
||||||
import mightypork.gamecore.gui.Action; |
|
||||||
import mightypork.gamecore.gui.ActionTrigger; |
|
||||||
import mightypork.gamecore.gui.components.InputComponent; |
|
||||||
import mightypork.gamecore.input.events.MouseButtonEvent; |
|
||||||
import mightypork.gamecore.input.events.MouseButtonHandler; |
|
||||||
|
|
||||||
|
|
||||||
public abstract class ClickableComponent extends InputComponent implements ActionTrigger, MouseButtonHandler { |
|
||||||
|
|
||||||
protected boolean btnDownOver; |
|
||||||
private Action action; |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void setAction(Action action) |
|
||||||
{ |
|
||||||
this.action = action; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
protected void triggerAction() |
|
||||||
{ |
|
||||||
if (action != null && isEnabled()) action.run(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void receive(MouseButtonEvent event) |
|
||||||
{ |
|
||||||
if (!event.isButtonEvent()) return; |
|
||||||
|
|
||||||
if (event.isDown()) { |
|
||||||
btnDownOver = event.isOver(this); |
|
||||||
} |
|
||||||
|
|
||||||
if (event.isUp()) { |
|
||||||
|
|
||||||
if (btnDownOver && event.isOver(this)) { |
|
||||||
triggerAction(); |
|
||||||
event.consume(); |
|
||||||
} |
|
||||||
|
|
||||||
btnDownOver = false; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
@ -1,63 +0,0 @@ |
|||||||
package mightypork.gamecore.gui.components.input; |
|
||||||
|
|
||||||
|
|
||||||
import java.util.Collection; |
|
||||||
|
|
||||||
import mightypork.gamecore.gui.components.Component; |
|
||||||
import mightypork.utils.eventbus.clients.ClientList; |
|
||||||
import mightypork.utils.eventbus.clients.DelegatingClient; |
|
||||||
|
|
||||||
|
|
||||||
public class ClickableWrapper extends ClickableComponent implements DelegatingClient { |
|
||||||
|
|
||||||
private final Component wrapped; |
|
||||||
private final ClientList list; |
|
||||||
|
|
||||||
|
|
||||||
public ClickableWrapper(Component wrapped) { |
|
||||||
this.wrapped = wrapped; |
|
||||||
wrapped.setRect(this); |
|
||||||
|
|
||||||
list = new ClientList(wrapped); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public Collection<?> getChildClients() |
|
||||||
{ |
|
||||||
return list; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public boolean doesDelegate() |
|
||||||
{ |
|
||||||
return true; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
protected void renderComponent() |
|
||||||
{ |
|
||||||
wrapped.render(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void setEnabled(boolean yes) |
|
||||||
{ |
|
||||||
if (yes != super.isDirectlyEnabled()) { |
|
||||||
super.setEnabled(yes); |
|
||||||
wrapped.setIndirectlyEnabled(yes); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void setIndirectlyEnabled(boolean yes) |
|
||||||
{ |
|
||||||
super.setIndirectlyEnabled(yes); |
|
||||||
wrapped.setIndirectlyEnabled(yes); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -1,77 +0,0 @@ |
|||||||
package mightypork.gamecore.gui.components.input; |
|
||||||
|
|
||||||
|
|
||||||
import mightypork.gamecore.core.App; |
|
||||||
import mightypork.gamecore.graphics.fonts.IFont; |
|
||||||
import mightypork.gamecore.gui.components.DynamicWidthComponent; |
|
||||||
import mightypork.gamecore.gui.components.painters.TextPainter; |
|
||||||
import mightypork.utils.math.AlignX; |
|
||||||
import mightypork.utils.math.color.Color; |
|
||||||
import mightypork.utils.math.color.pal.RGB; |
|
||||||
import mightypork.utils.math.constraints.vect.Vect; |
|
||||||
import mightypork.utils.math.constraints.vect.var.VectVar; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Menu-like button with shadow and push state |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public class TextButton extends ClickableComponent implements DynamicWidthComponent { |
|
||||||
|
|
||||||
public final TextPainter textPainter; |
|
||||||
|
|
||||||
private final VectVar offset = Vect.makeVar(); |
|
||||||
|
|
||||||
public Vect offsetPassive = height().div(16).toVectXY(); |
|
||||||
public Vect offsetOver = height().div(20).toVectXY(); |
|
||||||
public Vect offsetUnder = height().div(32).toVectXY(); |
|
||||||
|
|
||||||
private final Color color; |
|
||||||
|
|
||||||
private boolean hoverMove = true; |
|
||||||
|
|
||||||
|
|
||||||
public TextButton(IFont font, String text, Color color) { |
|
||||||
this.color = color; |
|
||||||
|
|
||||||
this.textPainter = new TextPainter(font, AlignX.CENTER, this.color, text); |
|
||||||
this.textPainter.setRect(this); |
|
||||||
this.textPainter.setShadow(RGB.BLACK_30, offset); |
|
||||||
textPainter.setVPaddingPercent(5); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
protected void renderComponent() |
|
||||||
{ |
|
||||||
if (isMouseOver()) { |
|
||||||
if (App.input().isMouseButtonDown(0)) { |
|
||||||
offset.setTo(offsetUnder); |
|
||||||
} else { |
|
||||||
offset.setTo(hoverMove ? offsetOver : offsetPassive); |
|
||||||
} |
|
||||||
} else { |
|
||||||
offset.setTo(offsetPassive); |
|
||||||
} |
|
||||||
|
|
||||||
textPainter.render(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Disable offset change on hover |
|
||||||
*/ |
|
||||||
public void disableHoverEffect() |
|
||||||
{ |
|
||||||
hoverMove = false; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public double computeWidth(double height) |
|
||||||
{ |
|
||||||
return textPainter.computeWidth(height); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -1,42 +0,0 @@ |
|||||||
package mightypork.gamecore.gui.components.layout; |
|
||||||
|
|
||||||
|
|
||||||
import mightypork.gamecore.gui.components.Component; |
|
||||||
import mightypork.utils.math.constraints.rect.RectBound; |
|
||||||
|
|
||||||
|
|
||||||
public class ColumnLayout extends GridLayout { |
|
||||||
|
|
||||||
private int col = 0; |
|
||||||
|
|
||||||
|
|
||||||
public ColumnLayout(int rows) { |
|
||||||
this(null, rows); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public ColumnLayout(RectBound context, int cols) { |
|
||||||
super(context, 1, cols); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public void add(final Component elem) |
|
||||||
{ |
|
||||||
add(elem, 1); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public void add(final Component elem, int colSpan) |
|
||||||
{ |
|
||||||
if (elem == null) return; |
|
||||||
|
|
||||||
put(elem, 0, col, 1, colSpan); |
|
||||||
col += colSpan; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public void skip(int cols) |
|
||||||
{ |
|
||||||
col += cols; |
|
||||||
} |
|
||||||
} |
|
@ -1,36 +0,0 @@ |
|||||||
package mightypork.gamecore.gui.components.layout; |
|
||||||
|
|
||||||
|
|
||||||
import mightypork.gamecore.gui.components.Component; |
|
||||||
import mightypork.gamecore.gui.components.LayoutComponent; |
|
||||||
import mightypork.utils.math.constraints.rect.RectBound; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Layout for components with arbitrary constraints. |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public class ConstraintLayout extends LayoutComponent { |
|
||||||
|
|
||||||
public ConstraintLayout() { |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public ConstraintLayout(RectBound context) { |
|
||||||
super(context); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Add a component to the layout.<br> |
|
||||||
* The component's rect must be set up manually. |
|
||||||
* |
|
||||||
* @param component |
|
||||||
*/ |
|
||||||
public void add(Component component) |
|
||||||
{ |
|
||||||
attach(component); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -1,85 +0,0 @@ |
|||||||
package mightypork.gamecore.gui.components.layout; |
|
||||||
|
|
||||||
|
|
||||||
import mightypork.gamecore.gui.components.Component; |
|
||||||
import mightypork.gamecore.gui.components.LayoutComponent; |
|
||||||
import mightypork.utils.math.AlignX; |
|
||||||
import mightypork.utils.math.constraints.num.Num; |
|
||||||
import mightypork.utils.math.constraints.rect.Rect; |
|
||||||
import mightypork.utils.math.constraints.rect.RectBound; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Holder with same-sized columns, aligned to left or right |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public class FlowColumnLayout extends LayoutComponent { |
|
||||||
|
|
||||||
private int col = 0; |
|
||||||
private Num elementWidth; |
|
||||||
private final AlignX align; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* @param context context |
|
||||||
* @param elementWidth width of all elements |
|
||||||
* @param align component align. Legal values are LEFT and RIGHT. |
|
||||||
*/ |
|
||||||
public FlowColumnLayout(RectBound context, Num elementWidth, AlignX align) { |
|
||||||
super(context); |
|
||||||
this.elementWidth = elementWidth; |
|
||||||
this.align = align; |
|
||||||
|
|
||||||
if (align != AlignX.LEFT && align != AlignX.RIGHT) { |
|
||||||
throw new IllegalArgumentException("Can align only left or right."); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* make a new holder.<br> |
|
||||||
* Context must be assigned before rendering. |
|
||||||
* |
|
||||||
* @param elementWidth width of all elements |
|
||||||
* @param align component align. Legal values are LEFT and RIGHT. |
|
||||||
*/ |
|
||||||
public FlowColumnLayout(Num elementWidth, AlignX align) { |
|
||||||
this(null, elementWidth, align); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Add an item |
|
||||||
* |
|
||||||
* @param elem |
|
||||||
*/ |
|
||||||
public void add(final Component elem) |
|
||||||
{ |
|
||||||
if (elem == null) return; |
|
||||||
|
|
||||||
final Rect r; |
|
||||||
|
|
||||||
switch (align) { |
|
||||||
case LEFT: |
|
||||||
r = leftEdge().growRight(elementWidth).moveX(elementWidth.mul(col++)); |
|
||||||
break; |
|
||||||
case RIGHT: |
|
||||||
r = rightEdge().growLeft(elementWidth).moveX(elementWidth.mul(-(col++))); |
|
||||||
break; |
|
||||||
default: |
|
||||||
throw new IllegalArgumentException("Bad align."); |
|
||||||
} |
|
||||||
|
|
||||||
elem.setRect(r); |
|
||||||
|
|
||||||
attach(elem); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public void setElementWidth(Num elementWidth) |
|
||||||
{ |
|
||||||
this.elementWidth = elementWidth; |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -1,84 +0,0 @@ |
|||||||
package mightypork.gamecore.gui.components.layout; |
|
||||||
|
|
||||||
|
|
||||||
import mightypork.gamecore.gui.components.Component; |
|
||||||
import mightypork.gamecore.gui.components.LayoutComponent; |
|
||||||
import mightypork.utils.math.AlignY; |
|
||||||
import mightypork.utils.math.constraints.num.Num; |
|
||||||
import mightypork.utils.math.constraints.rect.Rect; |
|
||||||
import mightypork.utils.math.constraints.rect.RectBound; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Holder with same-sized rows, aligned to top or bottom |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public class FlowRowLayout extends LayoutComponent { |
|
||||||
|
|
||||||
private int row = 0; |
|
||||||
private Num elementHeight; |
|
||||||
private final AlignY align; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* @param context context |
|
||||||
* @param elementHeight height of all elements |
|
||||||
* @param align component align. Legal values are TOP and BOTTOM. |
|
||||||
*/ |
|
||||||
public FlowRowLayout(RectBound context, Num elementHeight, AlignY align) { |
|
||||||
super(context); |
|
||||||
this.elementHeight = elementHeight; |
|
||||||
this.align = align; |
|
||||||
|
|
||||||
if (align != AlignY.TOP && align != AlignY.BOTTOM) { |
|
||||||
throw new IllegalArgumentException("Can align only to top or bottom."); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* make a new holder.<br> |
|
||||||
* Context must be assigned before rendering. |
|
||||||
* |
|
||||||
* @param elementHeight height of all elements |
|
||||||
* @param align component align. Legal values are TOP and BOTTOM. |
|
||||||
*/ |
|
||||||
public FlowRowLayout(Num elementHeight, AlignY align) { |
|
||||||
this(null, elementHeight, align); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Add an item |
|
||||||
* |
|
||||||
* @param elem |
|
||||||
*/ |
|
||||||
public void add(final Component elem) |
|
||||||
{ |
|
||||||
if (elem == null) return; |
|
||||||
|
|
||||||
final Rect r; |
|
||||||
|
|
||||||
switch (align) { |
|
||||||
case TOP: |
|
||||||
r = topEdge().growDown(elementHeight).moveY(elementHeight.mul(row++)); |
|
||||||
break; |
|
||||||
case BOTTOM: |
|
||||||
r = bottomEdge().growUp(elementHeight).moveY(elementHeight.mul(-(row++))); |
|
||||||
break; |
|
||||||
default: |
|
||||||
throw new IllegalArgumentException("Bad align."); |
|
||||||
} |
|
||||||
|
|
||||||
elem.setRect(r); |
|
||||||
|
|
||||||
attach(elem); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public void setElementHeight(Num elementHeight) |
|
||||||
{ |
|
||||||
this.elementHeight = elementHeight; |
|
||||||
} |
|
||||||
} |
|
@ -1,78 +0,0 @@ |
|||||||
package mightypork.gamecore.gui.components.layout; |
|
||||||
|
|
||||||
|
|
||||||
import mightypork.gamecore.gui.components.Component; |
|
||||||
import mightypork.gamecore.gui.components.LayoutComponent; |
|
||||||
import mightypork.utils.math.constraints.rect.RectBound; |
|
||||||
import mightypork.utils.math.constraints.rect.builders.TiledRect; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Holder with table cells |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public class GridLayout extends LayoutComponent { |
|
||||||
|
|
||||||
private final TiledRect tiler; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* @param context context |
|
||||||
* @param rows number of rows |
|
||||||
* @param cols number of columns |
|
||||||
*/ |
|
||||||
public GridLayout(RectBound context, int rows, int cols) { |
|
||||||
super(context); |
|
||||||
this.tiler = tiles(cols, rows); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* make a new holder.<br> |
|
||||||
* Context must be assigned before rendering. |
|
||||||
* |
|
||||||
* @param rows number of rows |
|
||||||
* @param cols number of columns |
|
||||||
*/ |
|
||||||
public GridLayout(int rows, int cols) { |
|
||||||
this(null, rows, cols); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Add a row to the holder. |
|
||||||
* |
|
||||||
* @param row row (one-based) |
|
||||||
* @param column column (one-based) |
|
||||||
* @param elem added component |
|
||||||
*/ |
|
||||||
public void put(Component elem, int row, int column) |
|
||||||
{ |
|
||||||
if (elem == null) return; |
|
||||||
|
|
||||||
elem.setRect(tiler.tile(column, row)); |
|
||||||
|
|
||||||
attach(elem); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Put with span |
|
||||||
* |
|
||||||
* @param elem |
|
||||||
* @param row |
|
||||||
* @param column |
|
||||||
* @param rowspan |
|
||||||
* @param colspan |
|
||||||
*/ |
|
||||||
public void put(Component elem, int row, int column, int rowspan, int colspan) |
|
||||||
{ |
|
||||||
if (elem == null) return; |
|
||||||
|
|
||||||
elem.setRect(tiler.span(column, row, colspan, rowspan)); |
|
||||||
|
|
||||||
attach(elem); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -1,18 +0,0 @@ |
|||||||
package mightypork.gamecore.gui.components.layout; |
|
||||||
|
|
||||||
|
|
||||||
import mightypork.gamecore.gui.components.BaseComponent; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Invisible component that does nothing at all; Null object pattern |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public class NullComponent extends BaseComponent { |
|
||||||
|
|
||||||
@Override |
|
||||||
protected void renderComponent() |
|
||||||
{ |
|
||||||
} |
|
||||||
} |
|
@ -1,42 +0,0 @@ |
|||||||
package mightypork.gamecore.gui.components.layout; |
|
||||||
|
|
||||||
|
|
||||||
import mightypork.gamecore.gui.components.Component; |
|
||||||
import mightypork.utils.math.constraints.rect.RectBound; |
|
||||||
|
|
||||||
|
|
||||||
public class RowLayout extends GridLayout { |
|
||||||
|
|
||||||
private int row = 0; |
|
||||||
|
|
||||||
|
|
||||||
public RowLayout(int rows) { |
|
||||||
this(null, rows); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public RowLayout(RectBound context, int rows) { |
|
||||||
super(context, rows, 1); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public void add(final Component elem) |
|
||||||
{ |
|
||||||
add(elem, 1); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public void add(final Component elem, int rowSpan) |
|
||||||
{ |
|
||||||
if (elem == null) return; |
|
||||||
|
|
||||||
put(elem, row, 0, rowSpan, 1); |
|
||||||
row += rowSpan; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public void skip(int rows) |
|
||||||
{ |
|
||||||
row += rows; |
|
||||||
} |
|
||||||
} |
|
@ -1,78 +0,0 @@ |
|||||||
package mightypork.gamecore.gui.components.layout.linear; |
|
||||||
|
|
||||||
|
|
||||||
import java.util.Collection; |
|
||||||
|
|
||||||
import mightypork.gamecore.gui.components.Component; |
|
||||||
import mightypork.gamecore.gui.components.LinearComponent; |
|
||||||
import mightypork.utils.eventbus.clients.ClientList; |
|
||||||
import mightypork.utils.eventbus.clients.DelegatingClient; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Converts a component into a linear component |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public abstract class AbstractLinearWrapper extends LinearComponent implements DelegatingClient { |
|
||||||
|
|
||||||
protected final Component wrapped; |
|
||||||
private final ClientList list; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* @param wrapped wrapped component. Can be null. |
|
||||||
*/ |
|
||||||
public AbstractLinearWrapper(Component wrapped) { |
|
||||||
this.wrapped = wrapped; |
|
||||||
if (wrapped != null) { |
|
||||||
if (wrapped instanceof LinearComponent) { |
|
||||||
((LinearComponent) wrapped).setHeight(height()); |
|
||||||
((LinearComponent) wrapped).setOrigin(origin()); |
|
||||||
} else { |
|
||||||
wrapped.setRect(this); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
list = new ClientList(wrapped); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
protected void renderComponent() |
|
||||||
{ |
|
||||||
if (wrapped != null) wrapped.render(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public Collection<?> getChildClients() |
|
||||||
{ |
|
||||||
return list; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public boolean doesDelegate() |
|
||||||
{ |
|
||||||
return true; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void setEnabled(boolean yes) |
|
||||||
{ |
|
||||||
if (yes != super.isDirectlyEnabled()) { |
|
||||||
super.setEnabled(yes); |
|
||||||
wrapped.setIndirectlyEnabled(yes); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void setIndirectlyEnabled(boolean yes) |
|
||||||
{ |
|
||||||
super.setIndirectlyEnabled(yes); |
|
||||||
wrapped.setIndirectlyEnabled(yes); |
|
||||||
} |
|
||||||
} |
|
@ -1,24 +0,0 @@ |
|||||||
package mightypork.gamecore.gui.components.layout.linear; |
|
||||||
|
|
||||||
|
|
||||||
import mightypork.gamecore.gui.components.layout.NullComponent; |
|
||||||
import mightypork.utils.math.constraints.num.Num; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Gap in linear layout |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public class LinearGap extends LinearRectangle { |
|
||||||
|
|
||||||
public LinearGap(Num width) { |
|
||||||
super(new NullComponent(), width); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public LinearGap(double heightPercent) { |
|
||||||
this(Num.ZERO); |
|
||||||
setWidth(height().perc(heightPercent)); |
|
||||||
} |
|
||||||
} |
|
@ -1,93 +0,0 @@ |
|||||||
package mightypork.gamecore.gui.components.layout.linear; |
|
||||||
|
|
||||||
|
|
||||||
import mightypork.gamecore.gui.components.DynamicWidthComponent; |
|
||||||
import mightypork.gamecore.gui.components.LayoutComponent; |
|
||||||
import mightypork.gamecore.gui.components.LinearComponent; |
|
||||||
import mightypork.utils.math.AlignX; |
|
||||||
import mightypork.utils.math.constraints.num.Num; |
|
||||||
import mightypork.utils.math.constraints.num.batch.NumSum; |
|
||||||
import mightypork.utils.math.constraints.rect.RectBound; |
|
||||||
import mightypork.utils.math.constraints.vect.Vect; |
|
||||||
import mightypork.utils.math.constraints.vect.proxy.VectAdapter; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Layout that aligns elements while taking into account their actual |
|
||||||
* dimensions.<br> |
|
||||||
* Useful eg. for buttons that stretch based on text length. |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public class LinearLayout extends LayoutComponent { |
|
||||||
|
|
||||||
public LinearLayout(AlignX align) { |
|
||||||
this.align = align; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public LinearLayout(RectBound context, AlignX align) { |
|
||||||
super(context); |
|
||||||
this.align = align; |
|
||||||
} |
|
||||||
|
|
||||||
private final NumSum totalWidth = new NumSum(); |
|
||||||
|
|
||||||
private final Vect leftAlignOrigin = LinearLayout.this.origin(); |
|
||||||
private final Vect centerAlignOrigin = LinearLayout.this.topCenter().sub(totalWidth.half(), Num.ZERO); |
|
||||||
private final Vect rightAlignOrigin = LinearLayout.this.topRight().sub(totalWidth, Num.ZERO); |
|
||||||
|
|
||||||
private final Vect leftMostOrigin = new VectAdapter() { |
|
||||||
|
|
||||||
@Override |
|
||||||
protected Vect getSource() |
|
||||||
{ |
|
||||||
switch (align) { |
|
||||||
default: |
|
||||||
case LEFT: |
|
||||||
return leftAlignOrigin; |
|
||||||
case CENTER: |
|
||||||
return centerAlignOrigin; |
|
||||||
case RIGHT: |
|
||||||
return rightAlignOrigin; |
|
||||||
} |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
private Vect nextOrigin = leftMostOrigin; |
|
||||||
|
|
||||||
private AlignX align = AlignX.LEFT; |
|
||||||
|
|
||||||
|
|
||||||
public void add(DynamicWidthComponent dwcomp) |
|
||||||
{ |
|
||||||
add(new LinearWrapper(dwcomp)); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public void add(LinearComponent lincomp) |
|
||||||
{ |
|
||||||
lincomp.setHeight(height()); |
|
||||||
lincomp.setOrigin(nextOrigin); |
|
||||||
nextOrigin = nextOrigin.add(lincomp.width(), Num.ZERO); |
|
||||||
totalWidth.addSummand(lincomp.width()); |
|
||||||
attach(lincomp); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public void setAlign(AlignX align) |
|
||||||
{ |
|
||||||
this.align = align; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Add a gap. |
|
||||||
* |
|
||||||
* @param heightPercent percent of height for gap width |
|
||||||
*/ |
|
||||||
public void gap(double heightPercent) |
|
||||||
{ |
|
||||||
add(new LinearGap(heightPercent)); |
|
||||||
} |
|
||||||
} |
|
@ -1,31 +0,0 @@ |
|||||||
package mightypork.gamecore.gui.components.layout.linear; |
|
||||||
|
|
||||||
|
|
||||||
import mightypork.gamecore.gui.components.Component; |
|
||||||
import mightypork.utils.math.constraints.num.Num; |
|
||||||
|
|
||||||
|
|
||||||
public class LinearRectangle extends AbstractLinearWrapper { |
|
||||||
|
|
||||||
private Num width; |
|
||||||
|
|
||||||
|
|
||||||
public LinearRectangle(Component wrapped, Num width) { |
|
||||||
super(wrapped); |
|
||||||
this.width = width; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public void setWidth(Num width) |
|
||||||
{ |
|
||||||
this.width = width; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public double computeWidth(double height) |
|
||||||
{ |
|
||||||
return this.width.value(); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -1,20 +0,0 @@ |
|||||||
package mightypork.gamecore.gui.components.layout.linear; |
|
||||||
|
|
||||||
|
|
||||||
import mightypork.gamecore.gui.components.Component; |
|
||||||
|
|
||||||
|
|
||||||
public class LinearSquare extends AbstractLinearWrapper { |
|
||||||
|
|
||||||
public LinearSquare(Component wrapped) { |
|
||||||
super(wrapped); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public double computeWidth(double height) |
|
||||||
{ |
|
||||||
return height; |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -1,20 +0,0 @@ |
|||||||
package mightypork.gamecore.gui.components.layout.linear; |
|
||||||
|
|
||||||
|
|
||||||
import mightypork.gamecore.gui.components.DynamicWidthComponent; |
|
||||||
|
|
||||||
|
|
||||||
public class LinearWrapper extends AbstractLinearWrapper { |
|
||||||
|
|
||||||
public LinearWrapper(DynamicWidthComponent wrapped) { |
|
||||||
super(wrapped); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public double computeWidth(double height) |
|
||||||
{ |
|
||||||
return ((DynamicWidthComponent) wrapped).computeWidth(height); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -1,46 +0,0 @@ |
|||||||
package mightypork.gamecore.gui.components.painters; |
|
||||||
|
|
||||||
|
|
||||||
import mightypork.gamecore.core.App; |
|
||||||
import mightypork.gamecore.graphics.textures.TxQuad; |
|
||||||
import mightypork.gamecore.gui.components.BaseComponent; |
|
||||||
import mightypork.gamecore.gui.components.DynamicWidthComponent; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Draws image in given rect |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public class ImagePainter extends BaseComponent implements DynamicWidthComponent { |
|
||||||
|
|
||||||
private TxQuad txQuad; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* @param txQuad drawn image |
|
||||||
*/ |
|
||||||
public ImagePainter(TxQuad txQuad) { |
|
||||||
this.txQuad = txQuad; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void renderComponent() |
|
||||||
{ |
|
||||||
App.gfx().quad(this, txQuad); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public double computeWidth(double height) |
|
||||||
{ |
|
||||||
return (height / txQuad.uvs.height().value()) * txQuad.uvs.width().value(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public void setTxQuad(TxQuad txQuad) |
|
||||||
{ |
|
||||||
this.txQuad = txQuad; |
|
||||||
} |
|
||||||
} |
|
@ -1,62 +0,0 @@ |
|||||||
package mightypork.gamecore.gui.components.painters; |
|
||||||
|
|
||||||
|
|
||||||
import mightypork.gamecore.core.App; |
|
||||||
import mightypork.gamecore.gui.components.BaseComponent; |
|
||||||
import mightypork.utils.annotations.FactoryMethod; |
|
||||||
import mightypork.utils.math.color.Color; |
|
||||||
import mightypork.utils.math.color.Grad; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Draws image in given rect |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public class QuadPainter extends BaseComponent { |
|
||||||
|
|
||||||
@FactoryMethod |
|
||||||
public static QuadPainter gradH(Color colorLeft, Color colorRight) |
|
||||||
{ |
|
||||||
return new QuadPainter(colorLeft, colorRight, colorRight, colorLeft); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@FactoryMethod |
|
||||||
public static QuadPainter gradV(Color colorTop, Color colorBottom) |
|
||||||
{ |
|
||||||
return new QuadPainter(colorTop, colorTop, colorBottom, colorBottom); |
|
||||||
} |
|
||||||
|
|
||||||
private final Grad grad; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Painter with solid color |
|
||||||
* |
|
||||||
* @param color |
|
||||||
*/ |
|
||||||
public QuadPainter(Color color) { |
|
||||||
this.grad = new Grad(color, color, color, color); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Painter with coloured vertices. |
|
||||||
* |
|
||||||
* @param leftTop |
|
||||||
* @param rightTop |
|
||||||
* @param leftBottom |
|
||||||
* @param rightBottom |
|
||||||
*/ |
|
||||||
public QuadPainter(Color leftTop, Color rightTop, Color leftBottom, Color rightBottom) { |
|
||||||
this.grad = new Grad(leftTop, rightTop, rightBottom, leftBottom); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void renderComponent() |
|
||||||
{ |
|
||||||
App.gfx().quad(getRect(), grad); |
|
||||||
} |
|
||||||
} |
|
@ -1,163 +0,0 @@ |
|||||||
package mightypork.gamecore.gui.components.painters; |
|
||||||
|
|
||||||
|
|
||||||
import mightypork.gamecore.core.App; |
|
||||||
import mightypork.gamecore.graphics.fonts.FontRenderer; |
|
||||||
import mightypork.gamecore.graphics.fonts.IFont; |
|
||||||
import mightypork.gamecore.gui.components.BaseComponent; |
|
||||||
import mightypork.gamecore.gui.components.DynamicWidthComponent; |
|
||||||
import mightypork.utils.math.AlignX; |
|
||||||
import mightypork.utils.math.color.Color; |
|
||||||
import mightypork.utils.math.color.pal.RGB; |
|
||||||
import mightypork.utils.math.constraints.num.Num; |
|
||||||
import mightypork.utils.math.constraints.rect.Rect; |
|
||||||
import mightypork.utils.math.constraints.vect.Vect; |
|
||||||
import mightypork.utils.string.StringProvider; |
|
||||||
import mightypork.utils.string.StringWrapper; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Text painting component. |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public class TextPainter extends BaseComponent implements DynamicWidthComponent { |
|
||||||
|
|
||||||
private static final boolean DEBUG_FONT_RENDER = false; |
|
||||||
private final FontRenderer font; |
|
||||||
private Color color; |
|
||||||
private AlignX align; |
|
||||||
private StringProvider text; |
|
||||||
private boolean shadow; |
|
||||||
|
|
||||||
private double yPaddingPerc = 0; |
|
||||||
|
|
||||||
private Color shadowColor = RGB.BLACK; |
|
||||||
private Vect shadowOffset = Vect.make(2, 2); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* @param font font to use |
|
||||||
*/ |
|
||||||
public TextPainter(IFont font) { |
|
||||||
this(font, AlignX.LEFT, RGB.WHITE); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public TextPainter(IFont font, Color color, String text) { |
|
||||||
this(font, AlignX.LEFT, color, new StringWrapper(text)); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public TextPainter(IFont font, Color color, StringProvider text) { |
|
||||||
this(font, AlignX.LEFT, color, text); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public TextPainter(IFont font, Color color) { |
|
||||||
this(font, AlignX.LEFT, color, (StringProvider) null); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public TextPainter(IFont font, AlignX align, Color color, String text) { |
|
||||||
this(font, align, color, new StringWrapper(text)); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public TextPainter(IFont font, AlignX align, Color color, StringProvider text) { |
|
||||||
this.font = new FontRenderer(font); |
|
||||||
this.color = color; |
|
||||||
this.align = align; |
|
||||||
this.text = text; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public TextPainter(IFont font, AlignX align, Color color) { |
|
||||||
this(font, align, color, (StringProvider) null); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void renderComponent() |
|
||||||
{ |
|
||||||
if (text == null) return; |
|
||||||
|
|
||||||
final String str = text.getString(); |
|
||||||
|
|
||||||
final Num shrY = height().perc(yPaddingPerc); |
|
||||||
|
|
||||||
final Rect rect = getRect().shrink(Num.ZERO, shrY); |
|
||||||
|
|
||||||
if (shadow) { |
|
||||||
font.draw(str, rect.round(), align, shadowColor); |
|
||||||
} |
|
||||||
|
|
||||||
final Rect r = (shadow ? rect.move(shadowOffset.neg()) : rect).round(); |
|
||||||
font.draw(str, r, align, color); |
|
||||||
|
|
||||||
if (DEBUG_FONT_RENDER) App.gfx().quad(r, RGB.PINK.withAlpha(0.4)); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public void setShadow(Color color, Vect offset) |
|
||||||
{ |
|
||||||
setShadow(true); |
|
||||||
setShadowColor(color); |
|
||||||
setShadowOffset(offset); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public void setShadow(boolean shadow) |
|
||||||
{ |
|
||||||
this.shadow = shadow; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public void setShadowColor(Color shadowColor) |
|
||||||
{ |
|
||||||
this.shadowColor = shadowColor; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public void setShadowOffset(Vect shadowOffset) |
|
||||||
{ |
|
||||||
this.shadowOffset = shadowOffset; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public void setColor(Color color) |
|
||||||
{ |
|
||||||
this.color = color; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public void setAlign(AlignX align) |
|
||||||
{ |
|
||||||
this.align = align; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public void setText(String text) |
|
||||||
{ |
|
||||||
this.text = new StringWrapper(text); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public void setText(StringProvider text) |
|
||||||
{ |
|
||||||
this.text = text; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public void setVPaddingPercent(double percY) |
|
||||||
{ |
|
||||||
yPaddingPerc = percY; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public double computeWidth(double height) |
|
||||||
{ |
|
||||||
return font.getWidth(this.text.getString(), height * ((100 - yPaddingPerc * 2) / 100D)); |
|
||||||
} |
|
||||||
} |
|
@ -1,30 +0,0 @@ |
|||||||
package mightypork.gamecore.gui.events; |
|
||||||
|
|
||||||
|
|
||||||
import mightypork.utils.eventbus.BusEvent; |
|
||||||
import mightypork.utils.eventbus.events.flags.DirectEvent; |
|
||||||
import mightypork.utils.eventbus.events.flags.NonConsumableEvent; |
|
||||||
import mightypork.utils.eventbus.events.flags.NonRejectableEvent; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Intended use is to notify UI component sub-clients that they should poll |
|
||||||
* their cached constraints. |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
@DirectEvent |
|
||||||
@NonConsumableEvent |
|
||||||
@NonRejectableEvent |
|
||||||
public class LayoutChangeEvent extends BusEvent<LayoutChangeListener> { |
|
||||||
|
|
||||||
public LayoutChangeEvent() { |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void handleBy(LayoutChangeListener handler) |
|
||||||
{ |
|
||||||
handler.onLayoutChanged(); |
|
||||||
} |
|
||||||
} |
|
@ -1,7 +0,0 @@ |
|||||||
package mightypork.gamecore.gui.events; |
|
||||||
|
|
||||||
|
|
||||||
public interface LayoutChangeListener { |
|
||||||
|
|
||||||
public void onLayoutChanged(); |
|
||||||
} |
|
@ -1,33 +0,0 @@ |
|||||||
package mightypork.gamecore.gui.events; |
|
||||||
|
|
||||||
|
|
||||||
import mightypork.utils.eventbus.BusEvent; |
|
||||||
import mightypork.utils.eventbus.events.flags.SingleReceiverEvent; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Request to change screen |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
@SingleReceiverEvent |
|
||||||
public class ScreenRequest extends BusEvent<ScreenRequestListener> { |
|
||||||
|
|
||||||
private final String scrName; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* @param screenKey screen name |
|
||||||
*/ |
|
||||||
public ScreenRequest(String screenKey) { |
|
||||||
scrName = screenKey; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void handleBy(ScreenRequestListener handler) |
|
||||||
{ |
|
||||||
handler.showScreen(scrName); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -1,15 +0,0 @@ |
|||||||
package mightypork.gamecore.gui.events; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* {@link ScreenRequest} listener |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public interface ScreenRequestListener { |
|
||||||
|
|
||||||
/** |
|
||||||
* @param key screen to show |
|
||||||
*/ |
|
||||||
void showScreen(String key); |
|
||||||
} |
|
@ -1,44 +0,0 @@ |
|||||||
package mightypork.gamecore.gui.events; |
|
||||||
|
|
||||||
|
|
||||||
import mightypork.utils.eventbus.BusEvent; |
|
||||||
import mightypork.utils.eventbus.events.flags.NonConsumableEvent; |
|
||||||
import mightypork.utils.eventbus.events.flags.NotLoggedEvent; |
|
||||||
import mightypork.utils.math.constraints.vect.Vect; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Screen resolution or mode was changed |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
@NonConsumableEvent |
|
||||||
@NotLoggedEvent |
|
||||||
public class ViewportChangeEvent extends BusEvent<ViewportChangeListener> { |
|
||||||
|
|
||||||
private final Vect screenSize; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* @param size new screen size |
|
||||||
*/ |
|
||||||
public ViewportChangeEvent(Vect size) { |
|
||||||
this.screenSize = size; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* @return new screen size |
|
||||||
*/ |
|
||||||
public Vect getScreenSize() |
|
||||||
{ |
|
||||||
return screenSize; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void handleBy(ViewportChangeListener handler) |
|
||||||
{ |
|
||||||
handler.onViewportChanged(this); |
|
||||||
} |
|
||||||
} |
|
@ -1,17 +0,0 @@ |
|||||||
package mightypork.gamecore.gui.events; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* {@link ViewportChangeEvent} listener |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public interface ViewportChangeListener { |
|
||||||
|
|
||||||
/** |
|
||||||
* Handle event |
|
||||||
* |
|
||||||
* @param event |
|
||||||
*/ |
|
||||||
void onViewportChanged(ViewportChangeEvent event); |
|
||||||
} |
|
@ -1,112 +0,0 @@ |
|||||||
package mightypork.gamecore.gui.screens; |
|
||||||
|
|
||||||
|
|
||||||
import java.util.ArrayList; |
|
||||||
import java.util.Collection; |
|
||||||
import java.util.Collections; |
|
||||||
import java.util.Comparator; |
|
||||||
import java.util.List; |
|
||||||
|
|
||||||
import mightypork.utils.eventbus.clients.DelegatingClient; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Screen with multiple instances of {@link ScreenLayer} |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public abstract class LayeredScreen extends Screen { |
|
||||||
|
|
||||||
/** |
|
||||||
* Wrapper for delegating client, to use custom client ordering. |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
private class LayersClient implements DelegatingClient { |
|
||||||
|
|
||||||
@SuppressWarnings({ "unchecked", "rawtypes" }) |
|
||||||
@Override |
|
||||||
public Collection getChildClients() |
|
||||||
{ |
|
||||||
return layersByEventPriority; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public boolean doesDelegate() |
|
||||||
{ |
|
||||||
return true; |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
private final List<ScreenLayer> layersByZIndex = new ArrayList<>(); |
|
||||||
private final List<ScreenLayer> layersByEventPriority = new ArrayList<>(); |
|
||||||
|
|
||||||
private final LayersClient layersClient = new LayersClient(); |
|
||||||
|
|
||||||
|
|
||||||
public LayeredScreen() { |
|
||||||
addChildClient(layersClient); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
protected void renderScreen() |
|
||||||
{ |
|
||||||
for (final ScreenLayer layer : layersByZIndex) { |
|
||||||
if (layer.isVisible()) layer.render(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Add a layer to the screen. |
|
||||||
* |
|
||||||
* @param layer |
|
||||||
*/ |
|
||||||
protected void addLayer(ScreenLayer layer) |
|
||||||
{ |
|
||||||
this.layersByZIndex.add(layer); |
|
||||||
this.layersByEventPriority.add(layer); |
|
||||||
|
|
||||||
Collections.sort(layersByEventPriority, new Comparator<Overlay>() { |
|
||||||
|
|
||||||
@Override |
|
||||||
public int compare(Overlay o1, Overlay o2) |
|
||||||
{ |
|
||||||
return o2.getEventPriority() - o1.getEventPriority(); |
|
||||||
} |
|
||||||
|
|
||||||
}); |
|
||||||
|
|
||||||
Collections.sort(layersByZIndex, new Comparator<Overlay>() { |
|
||||||
|
|
||||||
@Override |
|
||||||
public int compare(Overlay o1, Overlay o2) |
|
||||||
{ |
|
||||||
return o1.getZIndex() - o2.getZIndex(); |
|
||||||
} |
|
||||||
|
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
protected void onScreenEnter() |
|
||||||
{ |
|
||||||
for (final ScreenLayer layer : layersByEventPriority) { |
|
||||||
layer.onScreenEnter(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
protected void onScreenLeave() |
|
||||||
{ |
|
||||||
for (final ScreenLayer layer : layersByEventPriority) { |
|
||||||
layer.onScreenLeave(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -1,222 +0,0 @@ |
|||||||
package mightypork.gamecore.gui.screens; |
|
||||||
|
|
||||||
|
|
||||||
import java.util.ArrayList; |
|
||||||
import java.util.Collection; |
|
||||||
|
|
||||||
import mightypork.gamecore.core.App; |
|
||||||
import mightypork.gamecore.graphics.Renderable; |
|
||||||
import mightypork.gamecore.gui.components.layout.ConstraintLayout; |
|
||||||
import mightypork.gamecore.gui.events.LayoutChangeListener; |
|
||||||
import mightypork.gamecore.input.KeyBinder; |
|
||||||
import mightypork.gamecore.input.KeyBindingPool; |
|
||||||
import mightypork.gamecore.input.KeyStroke; |
|
||||||
import mightypork.gamecore.input.Trigger; |
|
||||||
import mightypork.utils.annotations.Stub; |
|
||||||
import mightypork.utils.eventbus.clients.BusNode; |
|
||||||
import mightypork.utils.interfaces.Enableable; |
|
||||||
import mightypork.utils.interfaces.Hideable; |
|
||||||
import mightypork.utils.interfaces.Updateable; |
|
||||||
import mightypork.utils.math.color.Color; |
|
||||||
import mightypork.utils.math.constraints.num.Num; |
|
||||||
import mightypork.utils.math.constraints.vect.Vect; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Abstract overlay.<br> |
|
||||||
* Overlay is connected to event bus and is renderable. |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public abstract class Overlay extends BusNode implements Comparable<Overlay>, Updateable, Renderable, KeyBinder, Hideable, Enableable, LayoutChangeListener { |
|
||||||
|
|
||||||
private boolean visible = true; |
|
||||||
private boolean enabled = true; |
|
||||||
|
|
||||||
private final KeyBindingPool keybindings = new KeyBindingPool(); |
|
||||||
|
|
||||||
/** Root layout, rendered and attached to the event bus. */ |
|
||||||
protected final ConstraintLayout root; |
|
||||||
|
|
||||||
/** Constraint: Mouse position. */ |
|
||||||
protected final Vect mouse; |
|
||||||
|
|
||||||
/** Extra rendered items (outside root) */ |
|
||||||
protected final Collection<Renderable> rendered = new ArrayList<>(); |
|
||||||
|
|
||||||
/** Extra updated items (outside root - those can just implement Updateable) */ |
|
||||||
protected final Collection<Updateable> updated = new ArrayList<>(); |
|
||||||
private Num alphaMul = Num.ONE; |
|
||||||
|
|
||||||
|
|
||||||
public Overlay() { |
|
||||||
|
|
||||||
this.mouse = App.input().getMousePos(); |
|
||||||
|
|
||||||
this.root = new ConstraintLayout(App.gfx().getRect()); |
|
||||||
addChildClient(root); |
|
||||||
addChildClient(keybindings); |
|
||||||
|
|
||||||
rendered.add(root); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public final void bindKey(KeyStroke stroke, Trigger edge, Runnable task) |
|
||||||
{ |
|
||||||
keybindings.bindKey(stroke, edge, task); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public final void unbindKey(KeyStroke stroke) |
|
||||||
{ |
|
||||||
keybindings.unbindKey(stroke); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public final boolean isVisible() |
|
||||||
{ |
|
||||||
return visible; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void setVisible(boolean visible) |
|
||||||
{ |
|
||||||
if (visible != this.visible) { |
|
||||||
this.visible = visible; |
|
||||||
root.setVisible(visible); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void setEnabled(boolean yes) |
|
||||||
{ |
|
||||||
if (enabled != yes) { |
|
||||||
this.enabled = yes; |
|
||||||
root.setEnabled(yes); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public boolean isEnabled() |
|
||||||
{ |
|
||||||
return enabled; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Get rendering layer |
|
||||||
* |
|
||||||
* @return higher = on top. |
|
||||||
*/ |
|
||||||
@Stub |
|
||||||
public abstract int getZIndex(); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Get event bus listening priority - useful to block incoming events. |
|
||||||
* |
|
||||||
* @return higher = first. |
|
||||||
*/ |
|
||||||
public int getEventPriority() |
|
||||||
{ |
|
||||||
return getZIndex(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Render the overlay. The caller MUST check for visibility himself. |
|
||||||
*/ |
|
||||||
@Override |
|
||||||
public void render() |
|
||||||
{ |
|
||||||
if (!isVisible()) return; |
|
||||||
|
|
||||||
Color.pushAlpha(alphaMul); |
|
||||||
for (final Renderable r : rendered) { |
|
||||||
r.render(); |
|
||||||
} |
|
||||||
|
|
||||||
Color.popAlpha(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void update(double delta) |
|
||||||
{ |
|
||||||
if (!isEnabled()) return; |
|
||||||
|
|
||||||
for (final Updateable u : updated) { |
|
||||||
u.update(delta); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public int compareTo(Overlay o) |
|
||||||
{ |
|
||||||
return o.getEventPriority() - getEventPriority(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* <p> |
|
||||||
* Screen size changed. |
|
||||||
* </p> |
|
||||||
* <p> |
|
||||||
* Layouts / components should listen for this event and update their cached |
|
||||||
* constraints; components added to root or directly to this overlay as |
|
||||||
* child clients will receive the event. |
|
||||||
* </p> |
|
||||||
*/ |
|
||||||
@Override |
|
||||||
@Stub |
|
||||||
public void onLayoutChanged() |
|
||||||
{ |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public void setAlpha(Num alpha) |
|
||||||
{ |
|
||||||
this.alphaMul = alpha; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public void setAlpha(double alpha) |
|
||||||
{ |
|
||||||
this.alphaMul = Num.make(alpha); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public void show() |
|
||||||
{ |
|
||||||
setVisible(true); |
|
||||||
setEnabled(true); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public void hide() |
|
||||||
{ |
|
||||||
setVisible(false); |
|
||||||
setEnabled(false); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public boolean isListening() |
|
||||||
{ |
|
||||||
return (isVisible() || isEnabled()); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public boolean doesDelegate() |
|
||||||
{ |
|
||||||
return isListening(); |
|
||||||
} |
|
||||||
} |
|
@ -1,153 +0,0 @@ |
|||||||
package mightypork.gamecore.gui.screens; |
|
||||||
|
|
||||||
|
|
||||||
import mightypork.gamecore.core.App; |
|
||||||
import mightypork.gamecore.graphics.Renderable; |
|
||||||
import mightypork.gamecore.gui.events.LayoutChangeEvent; |
|
||||||
import mightypork.gamecore.gui.events.LayoutChangeListener; |
|
||||||
import mightypork.gamecore.input.KeyBinder; |
|
||||||
import mightypork.gamecore.input.KeyBindingPool; |
|
||||||
import mightypork.gamecore.input.KeyStroke; |
|
||||||
import mightypork.gamecore.input.Trigger; |
|
||||||
import mightypork.utils.annotations.Stub; |
|
||||||
import mightypork.utils.eventbus.clients.BusNode; |
|
||||||
import mightypork.utils.math.constraints.rect.Rect; |
|
||||||
import mightypork.utils.math.constraints.rect.RectBound; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Screen class. |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public abstract class Screen extends BusNode implements Renderable, RectBound, KeyBinder, LayoutChangeListener { |
|
||||||
|
|
||||||
private final KeyBindingPool keybindings = new KeyBindingPool(); |
|
||||||
|
|
||||||
private volatile boolean active; |
|
||||||
private volatile boolean needSetupViewport = false; |
|
||||||
|
|
||||||
|
|
||||||
public Screen() { |
|
||||||
|
|
||||||
// disable events initially
|
|
||||||
setListening(false); |
|
||||||
|
|
||||||
addChildClient(keybindings); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
private void fireLayoutChangeEvent() |
|
||||||
{ |
|
||||||
App.bus().sendDirectToChildren(this, new LayoutChangeEvent()); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public final void bindKey(KeyStroke stroke, Trigger edge, Runnable task) |
|
||||||
{ |
|
||||||
keybindings.bindKey(stroke, edge, task); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public final void unbindKey(KeyStroke stroke) |
|
||||||
{ |
|
||||||
keybindings.unbindKey(stroke); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Prepare for being shown |
|
||||||
* |
|
||||||
* @param shown true to show, false to hide |
|
||||||
*/ |
|
||||||
public final void setActive(boolean shown) |
|
||||||
{ |
|
||||||
if (shown) { |
|
||||||
active = true; |
|
||||||
needSetupViewport = true; |
|
||||||
|
|
||||||
fireLayoutChangeEvent(); |
|
||||||
onScreenEnter(); |
|
||||||
|
|
||||||
// enable events
|
|
||||||
setListening(true); |
|
||||||
|
|
||||||
} else { |
|
||||||
onScreenLeave(); |
|
||||||
|
|
||||||
active = false; |
|
||||||
|
|
||||||
// disable events
|
|
||||||
setListening(false); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* @return true if screen is the current screen |
|
||||||
*/ |
|
||||||
public final boolean isActive() |
|
||||||
{ |
|
||||||
return active; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void onLayoutChanged() |
|
||||||
{ |
|
||||||
if (!isActive()) return; |
|
||||||
|
|
||||||
needSetupViewport = true; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public final Rect getRect() |
|
||||||
{ |
|
||||||
return App.gfx().getRect(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void render() |
|
||||||
{ |
|
||||||
if (!isActive()) return; |
|
||||||
|
|
||||||
if (needSetupViewport) { |
|
||||||
App.gfx().setupProjection(); |
|
||||||
} |
|
||||||
|
|
||||||
App.gfx().pushState(); |
|
||||||
|
|
||||||
renderScreen(); |
|
||||||
|
|
||||||
App.gfx().popState(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Called when the screen becomes active |
|
||||||
*/ |
|
||||||
@Stub |
|
||||||
protected void onScreenEnter() |
|
||||||
{ |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Called when the screen is no longer active |
|
||||||
*/ |
|
||||||
@Stub |
|
||||||
protected void onScreenLeave() |
|
||||||
{ |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Render screen contents (context is ready for 2D rendering) |
|
||||||
*/ |
|
||||||
protected abstract void renderScreen(); |
|
||||||
|
|
||||||
} |
|
@ -1,50 +0,0 @@ |
|||||||
package mightypork.gamecore.gui.screens; |
|
||||||
|
|
||||||
|
|
||||||
import mightypork.utils.annotations.Stub; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Screen display layer |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public abstract class ScreenLayer extends Overlay { |
|
||||||
|
|
||||||
private final Screen screen; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* @param screen parent screen |
|
||||||
*/ |
|
||||||
public ScreenLayer(Screen screen) { |
|
||||||
this.screen = screen; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* @return parent screen instance |
|
||||||
*/ |
|
||||||
protected final Screen getScreen() |
|
||||||
{ |
|
||||||
return screen; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Called when the screen becomes active |
|
||||||
*/ |
|
||||||
@Stub |
|
||||||
protected void onScreenEnter() |
|
||||||
{ |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Called when the screen is no longer active |
|
||||||
*/ |
|
||||||
@Stub |
|
||||||
protected void onScreenLeave() |
|
||||||
{ |
|
||||||
} |
|
||||||
} |
|
@ -1,106 +0,0 @@ |
|||||||
package mightypork.gamecore.gui.screens; |
|
||||||
|
|
||||||
|
|
||||||
import java.util.Collection; |
|
||||||
import java.util.HashMap; |
|
||||||
import java.util.Map; |
|
||||||
import java.util.TreeSet; |
|
||||||
|
|
||||||
import mightypork.gamecore.core.App; |
|
||||||
import mightypork.gamecore.graphics.Renderable; |
|
||||||
import mightypork.gamecore.gui.events.LayoutChangeEvent; |
|
||||||
import mightypork.gamecore.gui.events.ScreenRequestListener; |
|
||||||
import mightypork.gamecore.gui.events.ViewportChangeEvent; |
|
||||||
import mightypork.gamecore.gui.events.ViewportChangeListener; |
|
||||||
import mightypork.utils.eventbus.clients.BusNode; |
|
||||||
import mightypork.utils.logging.Log; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Game screens holder; Takes care of rendering and screen requests. |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public class ScreenRegistry extends BusNode implements ScreenRequestListener, ViewportChangeListener, Renderable { |
|
||||||
|
|
||||||
private final Map<String, Screen> screens = new HashMap<>(); |
|
||||||
private final Collection<Overlay> overlays = new TreeSet<>(); |
|
||||||
private volatile Screen active = null; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Add a screen |
|
||||||
* |
|
||||||
* @param name screen key for calling |
|
||||||
* @param screen added screen |
|
||||||
*/ |
|
||||||
public void addScreen(String name, Screen screen) |
|
||||||
{ |
|
||||||
screens.put(name, screen); |
|
||||||
addChildClient(screen); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Add an overlay |
|
||||||
* |
|
||||||
* @param overlay added overlay |
|
||||||
*/ |
|
||||||
public void addOverlay(Overlay overlay) |
|
||||||
{ |
|
||||||
overlays.add(overlay); |
|
||||||
addChildClient(overlay); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void showScreen(String key) |
|
||||||
{ |
|
||||||
Log.f3("Request to show screen \"" + key + "\""); |
|
||||||
|
|
||||||
// find screen to show
|
|
||||||
final Screen toShow = screens.get(key); |
|
||||||
if (toShow == null) { |
|
||||||
throw new RuntimeException("Screen " + key + " not defined."); |
|
||||||
} |
|
||||||
|
|
||||||
// deactivate last screen
|
|
||||||
if (active != null) { |
|
||||||
active.setActive(false); |
|
||||||
} |
|
||||||
|
|
||||||
// activate new screen
|
|
||||||
toShow.setActive(true); |
|
||||||
|
|
||||||
active = toShow; |
|
||||||
|
|
||||||
fireLayoutUpdateEvent(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void render() |
|
||||||
{ |
|
||||||
if (active != null) { |
|
||||||
active.render(); |
|
||||||
|
|
||||||
for (final Overlay overlay : overlays) { |
|
||||||
if (overlay.isVisible()) overlay.render(); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void onViewportChanged(ViewportChangeEvent event) |
|
||||||
{ |
|
||||||
if (active != null) fireLayoutUpdateEvent(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
private void fireLayoutUpdateEvent() |
|
||||||
{ |
|
||||||
App.bus().sendDirectToChildren(this, new LayoutChangeEvent()); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -1,83 +0,0 @@ |
|||||||
package mightypork.gamecore.gui.screens.impl; |
|
||||||
|
|
||||||
|
|
||||||
import mightypork.gamecore.core.App; |
|
||||||
import mightypork.gamecore.gui.components.painters.QuadPainter; |
|
||||||
import mightypork.gamecore.gui.events.ScreenRequest; |
|
||||||
import mightypork.gamecore.gui.screens.Overlay; |
|
||||||
import mightypork.utils.math.animation.Easing; |
|
||||||
import mightypork.utils.math.animation.NumAnimated; |
|
||||||
import mightypork.utils.math.color.pal.RGB; |
|
||||||
import mightypork.utils.math.timing.TimedTask; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Overlay used for cross-fading between screens |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public class CrossfadeOverlay extends Overlay { |
|
||||||
|
|
||||||
private static final double T_IN = 0.4; |
|
||||||
private static final double T_OUT = 0.6; |
|
||||||
|
|
||||||
NumAnimated alpha = new NumAnimated(0); |
|
||||||
String requestedScreenName; |
|
||||||
|
|
||||||
TimedTask revealTask = new TimedTask() { |
|
||||||
|
|
||||||
@Override |
|
||||||
public void run() |
|
||||||
{ |
|
||||||
if (requestedScreenName == null) { |
|
||||||
App.shutdown(); |
|
||||||
} else { |
|
||||||
App.bus().send(new ScreenRequest(requestedScreenName)); |
|
||||||
} |
|
||||||
alpha.setEasing(Easing.SINE_OUT); |
|
||||||
alpha.fadeOut(T_OUT); |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
|
|
||||||
public CrossfadeOverlay() { |
|
||||||
final QuadPainter qp = new QuadPainter(RGB.BLACK); // TODO allow custom colors
|
|
||||||
qp.setRect(root); |
|
||||||
root.add(qp); |
|
||||||
|
|
||||||
updated.add(alpha); |
|
||||||
updated.add(revealTask); |
|
||||||
|
|
||||||
setAlpha(alpha); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public int getZIndex() |
|
||||||
{ |
|
||||||
return 10000; // not too high, so app can put something on top
|
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public void goToScreen(String screen, boolean fromDark) |
|
||||||
{ |
|
||||||
requestedScreenName = screen; |
|
||||||
|
|
||||||
if (screen == null) { |
|
||||||
// going for halt
|
|
||||||
App.audio().fadeOutAllLoops(); |
|
||||||
} |
|
||||||
|
|
||||||
if (fromDark) { |
|
||||||
alpha.setTo(1); |
|
||||||
revealTask.run(); |
|
||||||
} else { |
|
||||||
revealTask.start(T_IN); |
|
||||||
|
|
||||||
alpha.setEasing(Easing.SINE_IN); |
|
||||||
alpha.fadeIn(T_IN); |
|
||||||
|
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -1,45 +0,0 @@ |
|||||||
package mightypork.gamecore.gui.screens.impl; |
|
||||||
|
|
||||||
|
|
||||||
import mightypork.utils.eventbus.BusEvent; |
|
||||||
import mightypork.utils.eventbus.events.flags.SingleReceiverEvent; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
@SingleReceiverEvent |
|
||||||
public class CrossfadeRequest extends BusEvent<CrossfadeOverlay> { |
|
||||||
|
|
||||||
private final String screen; |
|
||||||
private final boolean fromDark; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* @param screen screen key to show. Null = exit the app. |
|
||||||
* @param fromDark true to fade from full black (ie. start of the game) |
|
||||||
*/ |
|
||||||
public CrossfadeRequest(String screen, boolean fromDark) { |
|
||||||
super(); |
|
||||||
this.screen = screen; |
|
||||||
this.fromDark = fromDark; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* @param screen screen key to show. Null = exit the app. |
|
||||||
*/ |
|
||||||
public CrossfadeRequest(String screen) { |
|
||||||
super(); |
|
||||||
this.screen = screen; |
|
||||||
this.fromDark = false; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void handleBy(CrossfadeOverlay handler) |
|
||||||
{ |
|
||||||
handler.goToScreen(screen, fromDark); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -1,151 +0,0 @@ |
|||||||
package mightypork.gamecore.gui.screens.impl; |
|
||||||
|
|
||||||
|
|
||||||
import mightypork.gamecore.gui.screens.Screen; |
|
||||||
import mightypork.gamecore.gui.screens.ScreenLayer; |
|
||||||
import mightypork.utils.annotations.Stub; |
|
||||||
import mightypork.utils.math.animation.Easing; |
|
||||||
import mightypork.utils.math.animation.NumAnimated; |
|
||||||
import mightypork.utils.math.timing.TimedTask; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Layer that smoothly appears/disappears when shown/hidden |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public abstract class FadingLayer extends ScreenLayer { |
|
||||||
|
|
||||||
private final NumAnimated numa; |
|
||||||
private final TimedTask hideTimer = new TimedTask() { |
|
||||||
|
|
||||||
@Override |
|
||||||
public void run() |
|
||||||
{ |
|
||||||
FadingLayer.super.hide(); |
|
||||||
fadingOut = false; |
|
||||||
onHideFinished(); |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
private final TimedTask showTimer = new TimedTask() { |
|
||||||
|
|
||||||
@Override |
|
||||||
public void run() |
|
||||||
{ |
|
||||||
fadingIn = false; |
|
||||||
onShowFinished(); |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
private boolean fadingIn = false; |
|
||||||
private boolean fadingOut = false; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Create with default fading time and effect |
|
||||||
* |
|
||||||
* @param screen |
|
||||||
*/ |
|
||||||
public FadingLayer(Screen screen) { |
|
||||||
this(screen, new NumAnimated(1, Easing.QUADRATIC_OUT, 0.3)); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* @param screen |
|
||||||
* @param easingAnim the animation num |
|
||||||
*/ |
|
||||||
public FadingLayer(Screen screen, NumAnimated easingAnim) { |
|
||||||
super(screen); |
|
||||||
|
|
||||||
numa = easingAnim; |
|
||||||
|
|
||||||
updated.add(numa); |
|
||||||
updated.add(hideTimer); |
|
||||||
updated.add(showTimer); |
|
||||||
|
|
||||||
setAlpha(numa); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Called after the fade-out was completed |
|
||||||
*/ |
|
||||||
@Stub |
|
||||||
protected void onHideFinished() |
|
||||||
{ |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Called after the fade-in was completed |
|
||||||
*/ |
|
||||||
@Stub |
|
||||||
protected void onShowFinished() |
|
||||||
{ |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Show with fading |
|
||||||
*/ |
|
||||||
@Override |
|
||||||
public void show() |
|
||||||
{ |
|
||||||
if (fadingIn) return; |
|
||||||
|
|
||||||
if (!isVisible() || fadingOut) { |
|
||||||
super.show(); |
|
||||||
numa.fadeIn(); |
|
||||||
hideTimer.stop(); |
|
||||||
showTimer.start(numa.getDefaultDuration()); |
|
||||||
|
|
||||||
fadingOut = false; |
|
||||||
fadingIn = true; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Hide without fading |
|
||||||
*/ |
|
||||||
public void hideImmediate() |
|
||||||
{ |
|
||||||
hideTimer.stop(); |
|
||||||
numa.setTo(0); |
|
||||||
super.hide(); |
|
||||||
onHideFinished(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Show without fading |
|
||||||
*/ |
|
||||||
public void showImmediate() |
|
||||||
{ |
|
||||||
hideTimer.stop(); |
|
||||||
numa.setTo(1); |
|
||||||
super.show(); |
|
||||||
onShowFinished(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Hide with fading |
|
||||||
*/ |
|
||||||
@Override |
|
||||||
public void hide() |
|
||||||
{ |
|
||||||
if (fadingOut) return; |
|
||||||
|
|
||||||
if (isVisible()) { |
|
||||||
numa.fadeOut(); |
|
||||||
hideTimer.start(numa.getDefaultDuration()); |
|
||||||
|
|
||||||
fadingOut = true; |
|
||||||
fadingIn = false; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -1,31 +0,0 @@ |
|||||||
package mightypork.gamecore.gui.screens.impl; |
|
||||||
|
|
||||||
|
|
||||||
import mightypork.gamecore.gui.components.painters.QuadPainter; |
|
||||||
import mightypork.gamecore.gui.screens.Screen; |
|
||||||
import mightypork.gamecore.gui.screens.ScreenLayer; |
|
||||||
import mightypork.utils.math.color.Color; |
|
||||||
|
|
||||||
|
|
||||||
public class LayerColor extends ScreenLayer { |
|
||||||
|
|
||||||
private final int zIndex; |
|
||||||
|
|
||||||
|
|
||||||
public LayerColor(Screen screen, Color color, int zIndex) { |
|
||||||
super(screen); |
|
||||||
|
|
||||||
final QuadPainter qp = new QuadPainter(color); |
|
||||||
qp.setRect(root); |
|
||||||
root.add(qp); |
|
||||||
this.zIndex = zIndex; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public int getZIndex() |
|
||||||
{ |
|
||||||
return this.zIndex; |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -1,101 +0,0 @@ |
|||||||
package mightypork.gamecore.input; |
|
||||||
|
|
||||||
|
|
||||||
import mightypork.gamecore.core.BackendModule; |
|
||||||
import mightypork.utils.math.constraints.vect.Vect; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Abstract input module.<br> |
|
||||||
* An input module takes care of dispatching mouse and keyboard events, provides |
|
||||||
* access to mouse position, key states etc.<br> |
|
||||||
* The input module also takes care of calling App.shutdown() when the user |
|
||||||
* requests exit (eg. clicks the titlebar close button) |
|
||||||
* |
|
||||||
* @author Ondřej Hruška (MightyPork) |
|
||||||
*/ |
|
||||||
public abstract class InputModule extends BackendModule implements KeyBinder { |
|
||||||
|
|
||||||
protected KeyBindingPool keybindings; |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public final void init() |
|
||||||
{ |
|
||||||
initKeyCodes(); |
|
||||||
initDevices(); |
|
||||||
|
|
||||||
keybindings = new KeyBindingPool(); |
|
||||||
addChildClient(keybindings); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Initialize key codes for keys in {@link Keys} |
|
||||||
*/ |
|
||||||
protected abstract void initKeyCodes(); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Initialize input devices (set up infrastructure for getting the input) |
|
||||||
*/ |
|
||||||
protected abstract void initDevices(); |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void bindKey(KeyStroke stroke, Trigger edge, Runnable task) |
|
||||||
{ |
|
||||||
keybindings.bindKey(stroke, edge, task); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void unbindKey(KeyStroke stroke) |
|
||||||
{ |
|
||||||
keybindings.unbindKey(stroke); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Get absolute mouse position. Should always return the same Vect instance |
|
||||||
* (use a VectVar or similar). |
|
||||||
* |
|
||||||
* @return mouse position |
|
||||||
*/ |
|
||||||
public abstract Vect getMousePos(); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Check if mouse is inside window |
|
||||||
* |
|
||||||
* @return true if mouse is inside window. |
|
||||||
*/ |
|
||||||
public abstract boolean isMouseInside(); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Trap mouse cursor in the window / release it |
|
||||||
* |
|
||||||
* @param grab true to grab, false to release |
|
||||||
*/ |
|
||||||
public abstract void grabMouse(boolean grab); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Check if key is down. The key comes from the Keys class, so the code is |
|
||||||
* the one assigned in initKeyCodes() |
|
||||||
* |
|
||||||
* @param key key to check |
|
||||||
* @return is down |
|
||||||
*/ |
|
||||||
public abstract boolean isKeyDown(Key key); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Check mouse button state |
|
||||||
* |
|
||||||
* @param button button to test (0 left, 1 right, 2 middle, 3,4,5... extra) |
|
||||||
* @return true if the button exists and is down |
|
||||||
*/ |
|
||||||
public abstract boolean isMouseButtonDown(int button); |
|
||||||
} |
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue