Fixed some javadoc
This commit is contained in:
@@ -16,88 +16,88 @@ 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;
|
||||
@@ -105,26 +105,26 @@ public class AppInitOptions {
|
||||
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;
|
||||
|
||||
+43
-43
@@ -6,37 +6,37 @@ import java.lang.Thread.UncaughtExceptionHandler;
|
||||
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.files.WorkDir;
|
||||
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()
|
||||
@@ -44,17 +44,17 @@ public abstract class BaseApp extends App implements UncaughtExceptionHandler {
|
||||
if (started) {
|
||||
throw new IllegalStateException("Cannot alter init options after starting the App.");
|
||||
}
|
||||
|
||||
|
||||
return opt;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public BaseApp(AppBackend backend)
|
||||
{
|
||||
super(backend);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Start the application
|
||||
*/
|
||||
@@ -62,64 +62,64 @@ public abstract class BaseApp extends App implements UncaughtExceptionHandler {
|
||||
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);
|
||||
|
||||
WorkDir.setBaseDir(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
|
||||
*/
|
||||
@@ -127,55 +127,55 @@ public abstract class BaseApp extends App implements UncaughtExceptionHandler {
|
||||
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);
|
||||
opt.resourceLoader.setBaseDir(this);
|
||||
}
|
||||
|
||||
Res.init(this);
|
||||
|
||||
|
||||
Res.setBaseDir(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()
|
||||
{
|
||||
// ???
|
||||
|
||||
+62
-62
@@ -24,67 +24,67 @@
|
||||
//
|
||||
///**
|
||||
// * 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
|
||||
@@ -99,22 +99,22 @@
|
||||
// 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
|
||||
// */
|
||||
@@ -122,17 +122,17 @@
|
||||
// {
|
||||
// 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();
|
||||
@@ -141,9 +141,9 @@
|
||||
// Display.setDisplayMode(windowDisplayMode);
|
||||
// Display.update();
|
||||
// }
|
||||
//
|
||||
//
|
||||
// getEventBus().send(new ViewportChangeEvent(getSize()));
|
||||
//
|
||||
//
|
||||
// } catch (final Throwable t) {
|
||||
// Log.e("Failed to toggle fullscreen mode.", t);
|
||||
// try {
|
||||
@@ -154,12 +154,12 @@
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
// /**
|
||||
// * Take screenshot (expensive processing is done on-demand when screenshot
|
||||
// * is processed).
|
||||
// *
|
||||
// *
|
||||
// * @return screenshot object
|
||||
// */
|
||||
// public static AwtScreenshot prepareScreenshot()
|
||||
@@ -170,13 +170,13 @@
|
||||
// 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)
|
||||
// */
|
||||
@@ -184,41 +184,41 @@
|
||||
// {
|
||||
// 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
|
||||
// */
|
||||
@@ -226,8 +226,8 @@
|
||||
// {
|
||||
// return screenSize.xi();
|
||||
// }
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
// /**
|
||||
// * @return screen height
|
||||
// */
|
||||
@@ -235,8 +235,8 @@
|
||||
// {
|
||||
// return screenSize.yi();
|
||||
// }
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
// /**
|
||||
// * Start a OpenGL frame
|
||||
// */
|
||||
@@ -246,18 +246,18 @@
|
||||
// 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.
|
||||
// */
|
||||
@@ -266,8 +266,8 @@
|
||||
// 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.
|
||||
// */
|
||||
@@ -276,8 +276,8 @@
|
||||
// {
|
||||
// return getBounds();
|
||||
// }
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
// /**
|
||||
// * @return current FPS
|
||||
// */
|
||||
@@ -285,11 +285,11 @@
|
||||
// {
|
||||
// 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()
|
||||
|
||||
+133
-133
@@ -24,31 +24,31 @@
|
||||
//
|
||||
///**
|
||||
// * 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
|
||||
// */
|
||||
@@ -56,11 +56,11 @@
|
||||
// {
|
||||
// if (color != null) glColor4d(color.r(), color.g(), color.b(), color.a() * alpha);
|
||||
// }
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
// /**
|
||||
// * Translate
|
||||
// *
|
||||
// *
|
||||
// * @param x
|
||||
// * @param y
|
||||
// */
|
||||
@@ -68,11 +68,11 @@
|
||||
// {
|
||||
// glTranslated(x, y, 0);
|
||||
// }
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
// /**
|
||||
// * Translate
|
||||
// *
|
||||
// *
|
||||
// * @param x
|
||||
// * @param y
|
||||
// * @param z
|
||||
@@ -81,33 +81,33 @@
|
||||
// {
|
||||
// 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
|
||||
// */
|
||||
@@ -115,11 +115,11 @@
|
||||
// {
|
||||
// glScaled(x, y, 0);
|
||||
// }
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
// /**
|
||||
// * Scale
|
||||
// *
|
||||
// *
|
||||
// * @param x
|
||||
// * @param y
|
||||
// * @param z
|
||||
@@ -128,99 +128,99 @@
|
||||
// {
|
||||
// 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
|
||||
// */
|
||||
@@ -229,23 +229,23 @@
|
||||
// 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);
|
||||
@@ -254,8 +254,8 @@
|
||||
// GL11.glPushMatrix();
|
||||
// GL11.glMatrixMode(GL11.GL_MODELVIEW);
|
||||
// }
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
// /**
|
||||
// * Restore Gl state
|
||||
// */
|
||||
@@ -264,9 +264,9 @@
|
||||
// if (pushed == 0) {
|
||||
// Log.w("Pop without push.");
|
||||
// }
|
||||
//
|
||||
//
|
||||
// pushed--;
|
||||
//
|
||||
//
|
||||
// GL11.glMatrixMode(GL11.GL_PROJECTION);
|
||||
// GL11.glPopMatrix();
|
||||
// GL11.glMatrixMode(GL11.GL_MODELVIEW);
|
||||
@@ -274,8 +274,8 @@
|
||||
// GL11.glPopClientAttrib();
|
||||
// GL11.glPopAttrib();
|
||||
// }
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
// /**
|
||||
// * Store matrix
|
||||
// */
|
||||
@@ -283,8 +283,8 @@
|
||||
// {
|
||||
// GL11.glPushMatrix();
|
||||
// }
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
// /**
|
||||
// * Restore Gl state
|
||||
// */
|
||||
@@ -292,41 +292,41 @@
|
||||
// {
|
||||
// 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
|
||||
// */
|
||||
@@ -335,21 +335,21 @@
|
||||
// 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);
|
||||
@@ -358,11 +358,11 @@
|
||||
// glVertex2d(q.left, q.top);
|
||||
// glEnd();
|
||||
// }
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
// /**
|
||||
// * Draw quad with horizontal gradient
|
||||
// *
|
||||
// *
|
||||
// * @param quad drawn quad bounds
|
||||
// * @param color1 left color
|
||||
// * @param color2 right color
|
||||
@@ -371,17 +371,17 @@
|
||||
// {
|
||||
// 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
|
||||
@@ -391,30 +391,30 @@
|
||||
// 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
|
||||
@@ -423,11 +423,11 @@
|
||||
// {
|
||||
// quadColor(quad, color1, color1, color2, color2);
|
||||
// }
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
// /**
|
||||
// * Render textured rect
|
||||
// *
|
||||
// *
|
||||
// * @param quad rectangle (px)
|
||||
// * @param txquad texture quad
|
||||
// */
|
||||
@@ -435,11 +435,11 @@
|
||||
// {
|
||||
// quadTextured(quad, txquad, RGB.WHITE);
|
||||
// }
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
// /**
|
||||
// * Render textured rect
|
||||
// *
|
||||
// *
|
||||
// * @param quad rectangle (px)
|
||||
// * @param txquad texture instance
|
||||
// * @param tint color tint
|
||||
@@ -452,50 +452,50 @@
|
||||
// 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)
|
||||
@@ -505,35 +505,35 @@
|
||||
// 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();
|
||||
|
||||
+52
-52
@@ -28,22 +28,22 @@ package junk;
|
||||
//
|
||||
///**
|
||||
// * 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)
|
||||
@@ -61,8 +61,8 @@ package junk;
|
||||
// BufferHelper.fill(buf6, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f);
|
||||
// AL10.alListener(AL10.AL_ORIENTATION, buf6);
|
||||
// }
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
// /**
|
||||
// * @return listener coordinate
|
||||
// */
|
||||
@@ -70,50 +70,50 @@ package junk;
|
||||
// {
|
||||
// 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)
|
||||
// {
|
||||
@@ -121,11 +121,11 @@ package junk;
|
||||
// lp.update(delta);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
// /**
|
||||
// * Create effect resource
|
||||
// *
|
||||
// *
|
||||
// * @param resource resource path
|
||||
// * @param pitch default pitch (1 = unchanged)
|
||||
// * @param gain default gain (0-1)
|
||||
@@ -135,11 +135,11 @@ package junk;
|
||||
// {
|
||||
// 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)
|
||||
@@ -154,11 +154,11 @@ package junk;
|
||||
// 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
|
||||
@@ -170,8 +170,8 @@ package junk;
|
||||
// resources.add(a);
|
||||
// return a;
|
||||
// }
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
// /**
|
||||
// * Fade out all loops (ie. for screen transitions)
|
||||
// */
|
||||
@@ -181,8 +181,8 @@ package junk;
|
||||
// p.fadeOut();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
// /**
|
||||
// * Pause all loops (leave volume unchanged)
|
||||
// */
|
||||
@@ -192,66 +192,66 @@ package junk;
|
||||
// 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()
|
||||
|
||||
@@ -15,54 +15,54 @@ 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)
|
||||
{
|
||||
@@ -70,11 +70,11 @@ public abstract class AudioModule extends BackendModule implements Updateable {
|
||||
lp.update(delta);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create effect resource
|
||||
*
|
||||
*
|
||||
* @param resource resource path
|
||||
* @param pitch default pitch (1 = unchanged)
|
||||
* @param gain default gain (0-1)
|
||||
@@ -82,13 +82,13 @@ public abstract class AudioModule extends BackendModule implements Updateable {
|
||||
*/
|
||||
public EffectPlayer createEffect(String resource, double pitch, double gain)
|
||||
{
|
||||
return new EffectPlayer(createResource(resource), pitch, gain, effectsVolume);
|
||||
return new EffectPlayer(createAudio(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)
|
||||
@@ -98,39 +98,39 @@ public abstract class AudioModule extends BackendModule implements Updateable {
|
||||
*/
|
||||
public LoopPlayer createLoop(String resource, double pitch, double gain, double fadeIn, double fadeOut)
|
||||
{
|
||||
final LoopPlayer p = new LoopPlayer(createResource(resource), pitch, gain, loopsVolume);
|
||||
final LoopPlayer p = new LoopPlayer(createAudio(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)
|
||||
protected DeferredAudio createAudio(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)
|
||||
*/
|
||||
@@ -140,8 +140,8 @@ public abstract class AudioModule extends BackendModule implements Updateable {
|
||||
p.fadeOut();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Pause all loops (leave volume unchanged)
|
||||
*/
|
||||
@@ -151,66 +151,66 @@ public abstract class AudioModule extends BackendModule implements Updateable {
|
||||
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()
|
||||
|
||||
@@ -9,37 +9,37 @@ 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)
|
||||
{
|
||||
|
||||
@@ -7,63 +7,63 @@ 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
|
||||
@@ -71,11 +71,11 @@ public interface IAudio extends Destroyable {
|
||||
* @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
|
||||
@@ -84,16 +84,16 @@ public interface IAudio extends Destroyable {
|
||||
* @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);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -6,17 +6,17 @@ 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
|
||||
@@ -25,8 +25,8 @@ public class JointVolume extends Volume {
|
||||
super(1D);
|
||||
this.volumes = volumes;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get combined gain (multiplied)
|
||||
*/
|
||||
@@ -36,11 +36,11 @@ public class JointVolume extends Volume {
|
||||
double d = super.get();
|
||||
for (final Volume v : volumes)
|
||||
d *= v.get();
|
||||
|
||||
|
||||
return Calc.clamp(d, 0, 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set master gain
|
||||
*/
|
||||
|
||||
@@ -11,18 +11,18 @@ 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)
|
||||
@@ -32,11 +32,11 @@ public class SoundRegistry {
|
||||
{
|
||||
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)
|
||||
@@ -48,11 +48,11 @@ public class SoundRegistry {
|
||||
{
|
||||
loops.put(key, App.audio().createLoop(resource, pitch, gain, fadeIn, fadeOut));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get a loop player for key
|
||||
*
|
||||
*
|
||||
* @param key sound key
|
||||
* @return loop player
|
||||
*/
|
||||
@@ -64,11 +64,11 @@ public class SoundRegistry {
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get a effect player for key
|
||||
*
|
||||
*
|
||||
* @param key sound key
|
||||
* @return effect player
|
||||
*/
|
||||
|
||||
@@ -7,11 +7,11 @@ 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
|
||||
*/
|
||||
@@ -19,12 +19,12 @@ public class Volume extends Mutable<Double> {
|
||||
{
|
||||
super(d);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void set(Double d)
|
||||
{
|
||||
super.set(Calc.clamp(d, 0, 1));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -8,24 +8,24 @@ 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)
|
||||
@@ -35,23 +35,23 @@ public abstract class BaseAudioPlayer implements Destroyable {
|
||||
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
|
||||
*/
|
||||
@@ -59,11 +59,11 @@ public abstract class BaseAudioPlayer implements Destroyable {
|
||||
{
|
||||
return audio;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get play gain, computed based on volume and given multiplier
|
||||
*
|
||||
*
|
||||
* @param multiplier extra volume adjustment
|
||||
* @return computed gain
|
||||
*/
|
||||
@@ -71,11 +71,11 @@ public abstract class BaseAudioPlayer implements Destroyable {
|
||||
{
|
||||
return baseGain * gainMultiplier.get() * multiplier;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get pitch
|
||||
*
|
||||
*
|
||||
* @param multiplier pitch adjustment
|
||||
* @return computed pitch
|
||||
*/
|
||||
@@ -83,19 +83,19 @@ public abstract class BaseAudioPlayer implements Destroyable {
|
||||
{
|
||||
return basePitch * multiplier;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get if audio is valid
|
||||
*
|
||||
*
|
||||
* @return is valid
|
||||
*/
|
||||
protected boolean hasAudio()
|
||||
{
|
||||
return (audio != null);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* force load the resource
|
||||
*/
|
||||
|
||||
@@ -8,11 +8,11 @@ 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)
|
||||
@@ -23,36 +23,36 @@ public class EffectPlayer extends BaseAudioPlayer {
|
||||
{
|
||||
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
|
||||
@@ -60,8 +60,8 @@ public class EffectPlayer extends BaseAudioPlayer {
|
||||
public void play(double pitch, double gain, Vect pos)
|
||||
{
|
||||
if (!hasAudio()) return;
|
||||
|
||||
|
||||
getAudio().play(computePitch(pitch), computeGain(gain), false, pos);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -10,28 +10,26 @@ 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 final 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)
|
||||
@@ -41,14 +39,14 @@ public class LoopPlayer extends BaseAudioPlayer implements Updateable, Pauseable
|
||||
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
|
||||
*/
|
||||
@@ -57,96 +55,96 @@ public class LoopPlayer extends BaseAudioPlayer implements Updateable, Pauseable
|
||||
inTime = in;
|
||||
outTime = out;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private void initLoop()
|
||||
{
|
||||
if (hasAudio() && sourceID == -1) {
|
||||
if (hasAudio()) {
|
||||
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
|
||||
*
|
||||
* @param fadeTime fade time (s)
|
||||
*/
|
||||
public void fadeIn(double secs)
|
||||
public void fadeIn(double fadeTime)
|
||||
{
|
||||
if (!hasAudio()) return;
|
||||
|
||||
|
||||
if (isPaused()) fadeAnim.setTo(0);
|
||||
resume();
|
||||
fadeAnim.fadeIn(secs);
|
||||
fadeAnim.fadeIn(fadeTime);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Fade out and pause when reached zero volume
|
||||
*
|
||||
* @param secs fade duration
|
||||
*
|
||||
* @param fadeTime fade time (s)
|
||||
*/
|
||||
public void fadeOut(double secs)
|
||||
public void fadeOut(double fadeTime)
|
||||
{
|
||||
if (!hasAudio()) return;
|
||||
if (isPaused()) return;
|
||||
fadeAnim.fadeOut(secs);
|
||||
fadeAnim.fadeOut(fadeTime);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Fade in with default duration
|
||||
*/
|
||||
@@ -154,8 +152,8 @@ public class LoopPlayer extends BaseAudioPlayer implements Updateable, Pauseable
|
||||
{
|
||||
fadeIn(inTime);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Fade out with default duration
|
||||
*/
|
||||
@@ -163,5 +161,5 @@ public class LoopPlayer extends BaseAudioPlayer implements Updateable, Pauseable
|
||||
{
|
||||
fadeOut(outTime);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ import mightypork.utils.logging.Log;
|
||||
|
||||
/**
|
||||
* Game base class & static subsystem access
|
||||
*
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
public class App extends BusNode {
|
||||
@@ -30,14 +30,16 @@ public class App extends BusNode {
|
||||
private final EventBus eventBus = new EventBus();
|
||||
private boolean started = false;
|
||||
|
||||
/** List of installed App plugins */
|
||||
protected final DelegatingList plugins = new DelegatingList();
|
||||
/** List of initializers */
|
||||
protected final List<InitTask> initializers = new ArrayList<>();
|
||||
|
||||
|
||||
/**
|
||||
* Create an app with given backend.
|
||||
*
|
||||
* @param backend
|
||||
*
|
||||
* @param backend the backend to use
|
||||
*/
|
||||
public App(AppBackend backend)
|
||||
{
|
||||
@@ -56,8 +58,8 @@ public class App extends BusNode {
|
||||
|
||||
// initialize and use backend
|
||||
this.backend = backend;
|
||||
this.eventBus.subscribe(backend);
|
||||
this.backend.bind(this);
|
||||
this.eventBus.subscribe(backend);
|
||||
this.backend.initialize();
|
||||
}
|
||||
|
||||
@@ -65,7 +67,7 @@ public class App extends BusNode {
|
||||
/**
|
||||
* 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)
|
||||
@@ -83,8 +85,8 @@ public class App extends BusNode {
|
||||
|
||||
/**
|
||||
* Add an initializer to the app.
|
||||
*
|
||||
* @param initializer
|
||||
*
|
||||
* @param initializer the added init task
|
||||
*/
|
||||
public void addInitTask(InitTask initializer)
|
||||
{
|
||||
@@ -98,7 +100,7 @@ public class App extends BusNode {
|
||||
|
||||
/**
|
||||
* Get current backend
|
||||
*
|
||||
*
|
||||
* @return the backend
|
||||
*/
|
||||
public AppBackend getBackend()
|
||||
@@ -128,11 +130,21 @@ public class App extends BusNode {
|
||||
// sort initializers by order.
|
||||
final List<InitTask> orderedInitializers = InitTask.inOrder(initializers);
|
||||
|
||||
for (final InitTask initializer : orderedInitializers) {
|
||||
Log.f1("Running init task \"" + initializer.getName() + "\"...");
|
||||
initializer.bind(this);
|
||||
initializer.init();
|
||||
initializer.run();
|
||||
for (final InitTask initTask : orderedInitializers) {
|
||||
Log.f1("Running init task \"" + initTask.getName() + "\"...");
|
||||
|
||||
initTask.bind(this);
|
||||
|
||||
// set the task options
|
||||
initTask.init();
|
||||
|
||||
initTask.before();
|
||||
|
||||
// main task action
|
||||
initTask.run();
|
||||
|
||||
// after hook for extra actions immeditaely after the task completes
|
||||
initTask.after();
|
||||
}
|
||||
|
||||
Log.i("=== Initialization sequence completed ===");
|
||||
@@ -199,7 +211,7 @@ public class App extends BusNode {
|
||||
|
||||
/**
|
||||
* Get the currently running App instance.
|
||||
*
|
||||
*
|
||||
* @return app instance
|
||||
*/
|
||||
public static App instance()
|
||||
@@ -210,7 +222,7 @@ public class App extends BusNode {
|
||||
|
||||
/**
|
||||
* Get graphics module from the running app's backend
|
||||
*
|
||||
*
|
||||
* @return graphics module
|
||||
*/
|
||||
public static GraphicsModule gfx()
|
||||
@@ -221,7 +233,7 @@ public class App extends BusNode {
|
||||
|
||||
/**
|
||||
* Get audio module from the running app's backend
|
||||
*
|
||||
*
|
||||
* @return audio module
|
||||
*/
|
||||
public static AudioModule audio()
|
||||
@@ -232,7 +244,7 @@ public class App extends BusNode {
|
||||
|
||||
/**
|
||||
* Get input module from the running app's backend
|
||||
*
|
||||
*
|
||||
* @return input module
|
||||
*/
|
||||
public static InputModule input()
|
||||
@@ -243,7 +255,7 @@ public class App extends BusNode {
|
||||
|
||||
/**
|
||||
* Get event bus instance.
|
||||
*
|
||||
*
|
||||
* @return event bus
|
||||
*/
|
||||
public static EventBus bus()
|
||||
@@ -254,7 +266,7 @@ public class App extends BusNode {
|
||||
|
||||
/**
|
||||
* Get the main config, if initialized.
|
||||
*
|
||||
*
|
||||
* @return main config
|
||||
* @throws IllegalArgumentException if there is no such config.
|
||||
*/
|
||||
@@ -266,7 +278,7 @@ public class App extends BusNode {
|
||||
|
||||
/**
|
||||
* Get a config by alias.
|
||||
*
|
||||
*
|
||||
* @param alias config alias
|
||||
* @return the config
|
||||
* @throws IllegalArgumentException if there is no such config.
|
||||
|
||||
@@ -12,17 +12,18 @@ import mightypork.utils.eventbus.clients.BusNode;
|
||||
* 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 {
|
||||
|
||||
/** App instance assigned using <code>bind()</code> */
|
||||
protected App app;
|
||||
|
||||
|
||||
/**
|
||||
* Assign an app instance.
|
||||
*
|
||||
* Assign the initialized app instance to an "app" field.
|
||||
*
|
||||
* @param app app
|
||||
*/
|
||||
public void bind(App app)
|
||||
@@ -42,7 +43,7 @@ public abstract class AppBackend extends BusNode {
|
||||
|
||||
/**
|
||||
* Get graphics module (screen manager, texture and font loader, renderer)
|
||||
*
|
||||
*
|
||||
* @return graphics module
|
||||
*/
|
||||
public abstract GraphicsModule getGraphics();
|
||||
@@ -50,7 +51,7 @@ public abstract class AppBackend extends BusNode {
|
||||
|
||||
/**
|
||||
* Get audio module (
|
||||
*
|
||||
*
|
||||
* @return audio module
|
||||
*/
|
||||
public abstract AudioModule getAudio();
|
||||
@@ -58,7 +59,7 @@ public abstract class AppBackend extends BusNode {
|
||||
|
||||
/**
|
||||
* Get input module
|
||||
*
|
||||
*
|
||||
* @return input module
|
||||
*/
|
||||
public abstract InputModule getInput();
|
||||
|
||||
@@ -9,20 +9,26 @@ 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 {
|
||||
|
||||
|
||||
/** App instance assigned using <code>bind()</code> */
|
||||
protected App app;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Assign the initialized app instance to an "app" field.
|
||||
*
|
||||
* @param 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.
|
||||
|
||||
@@ -8,14 +8,20 @@ import mightypork.utils.interfaces.Destroyable;
|
||||
|
||||
/**
|
||||
* Abstract application backend module.
|
||||
*
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
public abstract class BackendModule extends BusNode implements Destroyable {
|
||||
|
||||
|
||||
/**
|
||||
* Initialize the backend module.<br>
|
||||
* Any initialization that would normally be done in constructor shall be
|
||||
* done here, to avoid pitfalls with
|
||||
* "call to overridable method from constructor"
|
||||
*/
|
||||
public abstract void init();
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
@Stub
|
||||
public void destroy()
|
||||
|
||||
@@ -16,57 +16,81 @@ 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 {
|
||||
|
||||
/** App instance assigned using <code>bind()</code> */
|
||||
protected App app;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Assign the initialized app instance to a protected "app" field.
|
||||
*
|
||||
* Assign the initialized app instance to an "app" field.
|
||||
*
|
||||
* @param app app
|
||||
*/
|
||||
void bind(App app)
|
||||
final void bind(App app)
|
||||
{
|
||||
this.app = app;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* An intialization method that is called before the run() method.<br>
|
||||
* An init method that is called before the <code>run()</code> 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.
|
||||
* Hook for extra action before the main task action.<br>
|
||||
* Can be overridden during app configuration to "bake-in" extra actions.
|
||||
*/
|
||||
@Stub
|
||||
public void before()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Run the initializer on app.
|
||||
*/
|
||||
public abstract void run();
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Hook executed after the "run()" method.<br>
|
||||
* Can be overridden during app configuration to "bake-in" extra actions.
|
||||
*/
|
||||
@Stub
|
||||
public void after()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
@@ -74,37 +98,37 @@ public abstract class InitTask {
|
||||
{
|
||||
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)
|
||||
{
|
||||
final List<InitTask> remaining = new ArrayList<>(tasks);
|
||||
|
||||
|
||||
final List<InitTask> ordered = new ArrayList<>();
|
||||
final Set<String> loaded = new HashSet<>();
|
||||
|
||||
|
||||
// resolve task order
|
||||
int addedThisIteration = 0;
|
||||
do {
|
||||
for (final Iterator<InitTask> i = remaining.iterator(); i.hasNext();) {
|
||||
final InitTask task = i.next();
|
||||
|
||||
|
||||
String[] deps = task.getDependencies();
|
||||
if (deps == null) deps = new String[] {};
|
||||
|
||||
|
||||
int unmetDepsCount = deps.length;
|
||||
|
||||
|
||||
for (final String d : deps) {
|
||||
if (loaded.contains(d)) unmetDepsCount--;
|
||||
}
|
||||
|
||||
|
||||
if (unmetDepsCount == 0) {
|
||||
ordered.add(task);
|
||||
loaded.add(task.getName());
|
||||
@@ -113,38 +137,38 @@ public abstract class InitTask {
|
||||
}
|
||||
}
|
||||
} 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 (final InitTask task : remaining) {
|
||||
if (Reflect.hasAnnotation(task.getClass(), OptionalInitTask.class)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
badInitializers++;
|
||||
|
||||
|
||||
String notSatisfied = "";
|
||||
|
||||
|
||||
for (final 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,23 +17,31 @@ 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)
|
||||
|
||||
|
||||
/**
|
||||
* Max time spent on main loop tasks per cycle (s)
|
||||
*/
|
||||
protected double MAX_TIME_TASKS = 1 / 30D;
|
||||
|
||||
/**
|
||||
* Max delta time (s) per frame.<br>
|
||||
* If delta is larger than this, it's clamped to it.
|
||||
*/
|
||||
protected double MAX_DELTA = 1 / 20D;
|
||||
|
||||
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}
|
||||
*/
|
||||
@@ -41,50 +49,54 @@ public class MainLoop extends BusNode implements Destroyable {
|
||||
{
|
||||
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);
|
||||
Log.f3("(timing) Clamping delta: was " + delta + " s, MAX_DELTA = " + MAX_DELTA + " s");
|
||||
delta = MAX_DELTA;
|
||||
}
|
||||
|
||||
|
||||
// dispatch update event
|
||||
App.bus().sendDirect(new UpdateEvent(delta));
|
||||
|
||||
|
||||
// run main loop tasks
|
||||
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.");
|
||||
Log.f3("! Time's up, postponing task to next cycle.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
beforeRender();
|
||||
|
||||
|
||||
if (rootRenderable != null) {
|
||||
rootRenderable.render();
|
||||
}
|
||||
|
||||
|
||||
afterRender();
|
||||
|
||||
|
||||
App.gfx().endFrame();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Called before render
|
||||
*/
|
||||
@@ -93,8 +105,8 @@ public class MainLoop extends BusNode implements Destroyable {
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Called after render
|
||||
*/
|
||||
@@ -103,28 +115,29 @@ public class MainLoop extends BusNode implements Destroyable {
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@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
|
||||
* Add a task to queue to be executed in the main loop (in rendering
|
||||
* context)
|
||||
*
|
||||
* @param task task
|
||||
* @param skipQueue true to skip the queue
|
||||
*/
|
||||
public synchronized void queueTask(Runnable request, boolean priority)
|
||||
public synchronized void queueTask(Runnable task, boolean skipQueue)
|
||||
{
|
||||
if (priority) {
|
||||
tasks.addFirst(request);
|
||||
if (skipQueue) {
|
||||
tasks.addFirst(task);
|
||||
} else {
|
||||
tasks.addLast(request);
|
||||
tasks.addLast(task);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ import java.lang.annotation.Target;
|
||||
/**
|
||||
* 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)
|
||||
@@ -20,5 +20,5 @@ import java.lang.annotation.Target;
|
||||
@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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,51 +4,52 @@ 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.files.WorkDir;
|
||||
import mightypork.utils.logging.Log;
|
||||
|
||||
|
||||
/**
|
||||
* Settings repository.
|
||||
*
|
||||
*
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public class Config {
|
||||
|
||||
|
||||
/** Array of configs registered for the app */
|
||||
protected static Map<String, Config> configs = new HashMap<>();
|
||||
|
||||
|
||||
private final Map<String, KeyStrokeProperty> strokes = new HashMap<>();
|
||||
|
||||
|
||||
private final PropertyManager propertyManager;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get a config from the static map, by given alias
|
||||
*
|
||||
*
|
||||
* @param alias alias
|
||||
* @return the config
|
||||
*/
|
||||
public static Config forAlias(String alias)
|
||||
{
|
||||
final 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
|
||||
*/
|
||||
@@ -57,14 +58,14 @@ public class 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
|
||||
*/
|
||||
@@ -72,22 +73,22 @@ public class Config {
|
||||
{
|
||||
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)
|
||||
{
|
||||
{
|
||||
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
|
||||
@@ -98,11 +99,11 @@ public class Config {
|
||||
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
|
||||
@@ -111,11 +112,11 @@ public class Config {
|
||||
{
|
||||
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
|
||||
@@ -124,11 +125,11 @@ public class Config {
|
||||
{
|
||||
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
|
||||
@@ -137,11 +138,11 @@ public class Config {
|
||||
{
|
||||
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
|
||||
@@ -150,19 +151,19 @@ public class Config {
|
||||
{
|
||||
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
|
||||
*/
|
||||
@@ -170,8 +171,8 @@ public class Config {
|
||||
{
|
||||
propertyManager.load();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Save config to file
|
||||
*/
|
||||
@@ -180,13 +181,13 @@ public class Config {
|
||||
Log.f3("Saving config.");
|
||||
propertyManager.save();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get an option for key
|
||||
*
|
||||
* @param key
|
||||
* @return option value
|
||||
*
|
||||
* @param key config key
|
||||
* @return option values
|
||||
*/
|
||||
public <T> T getValue(String key)
|
||||
{
|
||||
@@ -194,18 +195,18 @@ public class Config {
|
||||
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
|
||||
*/
|
||||
@@ -214,14 +215,14 @@ public class Config {
|
||||
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
|
||||
*/
|
||||
@@ -229,11 +230,11 @@ public class Config {
|
||||
{
|
||||
return "key." + cfgKey;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get keystroke for name
|
||||
*
|
||||
*
|
||||
* @param cfgKey stroke identifier in config file
|
||||
* @return the stroke
|
||||
*/
|
||||
@@ -243,14 +244,14 @@ public class Config {
|
||||
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
|
||||
@@ -261,7 +262,7 @@ public class Config {
|
||||
if (kp == null) {
|
||||
throw new IllegalArgumentException("No such stroke: " + cfgKey);
|
||||
}
|
||||
|
||||
|
||||
kp.getValue().setTo(key, mod);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,14 +9,14 @@ 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
|
||||
*/
|
||||
@@ -24,16 +24,16 @@ public abstract class InitTaskConfig extends InitTask {
|
||||
{
|
||||
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.
|
||||
@@ -42,34 +42,34 @@ public abstract class InitTaskConfig extends InitTask {
|
||||
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" };
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -12,41 +12,48 @@ import mightypork.utils.config.propmgr.Property;
|
||||
* 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> {
|
||||
|
||||
|
||||
/**
|
||||
* Make a keystroke property
|
||||
*
|
||||
* @param key config key
|
||||
* @param defaultValue default keystroke value
|
||||
* @param comment property comment
|
||||
*/
|
||||
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)
|
||||
{
|
||||
|
||||
@@ -8,16 +8,16 @@ 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
|
||||
*/
|
||||
@@ -25,8 +25,8 @@ public class MainLoopRequest extends BusEvent<MainLoop> {
|
||||
{
|
||||
this(task, false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param task task to run on main thread in rendering context
|
||||
* @param priority if true, skip other tasks in queue
|
||||
@@ -36,8 +36,8 @@ public class MainLoopRequest extends BusEvent<MainLoop> {
|
||||
this.task = task;
|
||||
this.priority = priority;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void handleBy(MainLoop handler)
|
||||
{
|
||||
|
||||
@@ -10,10 +10,8 @@ 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.
|
||||
*
|
||||
* This is a way to allow clients to abort the shutdown (ie. ask to save game).
|
||||
*
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public class ShutdownEvent extends BusEvent<ShutdownListener> {
|
||||
@@ -21,6 +19,11 @@ public class ShutdownEvent extends BusEvent<ShutdownListener> {
|
||||
private final Runnable shutdownTask;
|
||||
|
||||
|
||||
/**
|
||||
* Make a shutdown event
|
||||
*
|
||||
* @param doShutdown Task that does the actual shutdown
|
||||
*/
|
||||
public ShutdownEvent(Runnable doShutdown)
|
||||
{
|
||||
this.shutdownTask = doShutdown;
|
||||
|
||||
@@ -3,15 +3,15 @@ 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);
|
||||
|
||||
@@ -13,18 +13,18 @@ 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)
|
||||
@@ -32,8 +32,8 @@ public class InitTaskCrashHandler extends InitTask implements UncaughtExceptionH
|
||||
Log.e("The game has crashed.", throwable);
|
||||
App.shutdown();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String getName()
|
||||
{
|
||||
|
||||
@@ -7,19 +7,19 @@ 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)
|
||||
*/
|
||||
@@ -28,70 +28,70 @@ public class InitTaskDisplay extends InitTask {
|
||||
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()
|
||||
{
|
||||
final 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";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -15,24 +15,24 @@ 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
|
||||
{
|
||||
@@ -40,19 +40,19 @@ public class InitTaskIonizables extends InitTask {
|
||||
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
|
||||
{
|
||||
@@ -60,15 +60,15 @@ public class InitTaskIonizables extends InitTask {
|
||||
final int y = in.readInt();
|
||||
return new Move(x, y);
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String getName()
|
||||
{
|
||||
return "ion";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import java.io.File;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import mightypork.gamecore.core.InitTask;
|
||||
import mightypork.gamecore.core.WorkDir;
|
||||
import mightypork.utils.files.WorkDir;
|
||||
import mightypork.utils.logging.Log;
|
||||
import mightypork.utils.logging.writers.LogWriter;
|
||||
import mightypork.utils.string.StringUtil;
|
||||
@@ -14,36 +14,36 @@ 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)
|
||||
@@ -51,28 +51,28 @@ public class InitTaskLog extends InitTask {
|
||||
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
|
||||
*/
|
||||
@@ -81,8 +81,8 @@ public class InitTaskLog extends InitTask {
|
||||
this.levelWrite = levelWrite;
|
||||
this.levelPrint = levelPrint;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
@@ -91,15 +91,15 @@ public class InitTaskLog extends InitTask {
|
||||
Log.setLevel(levelWrite);
|
||||
Log.setSysoutLevel(levelPrint);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String getName()
|
||||
{
|
||||
return "log";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String[] getDependencies()
|
||||
{
|
||||
|
||||
@@ -5,47 +5,47 @@ import java.io.IOException;
|
||||
|
||||
import mightypork.gamecore.core.InitTask;
|
||||
import mightypork.gamecore.core.OptionalInitTask;
|
||||
import mightypork.gamecore.core.WorkDir;
|
||||
import mightypork.utils.files.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";
|
||||
txt += " Workdir ....... " + WorkDir.getBaseDir().getCanonicalPath() + "\n";
|
||||
} catch (final IOException e) {
|
||||
Log.e(e);
|
||||
}
|
||||
|
||||
|
||||
Log.i(txt);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String getName()
|
||||
{
|
||||
return "log_header";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String[] getDependencies()
|
||||
{
|
||||
|
||||
@@ -10,25 +10,25 @@ 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.files.WorkDir;
|
||||
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 final Map<String, String> namedPaths = new HashMap<>();
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param workdir path to the working directory
|
||||
* @param lock whether to lock the directory (single instance mode)
|
||||
@@ -38,45 +38,45 @@ public class InitTaskWorkdir extends InitTask {
|
||||
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
|
||||
*
|
||||
* @param lock true to use lock
|
||||
*/
|
||||
public void setInstanceLock(boolean lock)
|
||||
{
|
||||
this.doLock = lock;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set name of the lock file.
|
||||
*
|
||||
* @param lockFile
|
||||
*
|
||||
* @param lockFile lock file name
|
||||
*/
|
||||
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)
|
||||
*/
|
||||
@@ -84,13 +84,13 @@ public class InitTaskWorkdir extends InitTask {
|
||||
{
|
||||
namedPaths.put(alias, path);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
WorkDir.init(workdirPath);
|
||||
|
||||
WorkDir.setBaseDir(workdirPath);
|
||||
|
||||
// lock working directory
|
||||
if (doLock) {
|
||||
final File lock = WorkDir.getFile(lockFile);
|
||||
@@ -99,13 +99,13 @@ public class InitTaskWorkdir extends InitTask {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (final 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>
|
||||
@@ -115,20 +115,20 @@ public class InitTaskWorkdir extends InitTask {
|
||||
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()
|
||||
{
|
||||
|
||||
@@ -2,19 +2,19 @@ package mightypork.gamecore.core.plugins.screenshot;
|
||||
|
||||
|
||||
import mightypork.gamecore.core.InitTask;
|
||||
import mightypork.gamecore.core.WorkDir;
|
||||
import mightypork.utils.files.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
|
||||
*/
|
||||
@@ -22,49 +22,49 @@ public class InitTaskPluginScreenshot extends InitTask {
|
||||
{
|
||||
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" };
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -11,18 +11,18 @@ 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()
|
||||
{
|
||||
|
||||
@@ -7,16 +7,16 @@ 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();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -5,9 +5,9 @@ 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.files.WorkDir;
|
||||
import mightypork.utils.logging.Log;
|
||||
|
||||
|
||||
@@ -15,14 +15,14 @@ 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.
|
||||
*/
|
||||
@@ -30,16 +30,16 @@ public class TaskTakeScreenshot implements Runnable {
|
||||
{
|
||||
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);
|
||||
@@ -47,8 +47,8 @@ public class TaskTakeScreenshot implements Runnable {
|
||||
Log.e("Failed to save screenshot.", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return File to save the screenshot to.
|
||||
*/
|
||||
@@ -57,8 +57,8 @@ public class TaskTakeScreenshot implements Runnable {
|
||||
final String fname = getBaseFilename();
|
||||
return findFreeFile(fname);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return directory for screenshots
|
||||
*/
|
||||
@@ -66,23 +66,23 @@ public class TaskTakeScreenshot implements Runnable {
|
||||
{
|
||||
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
|
||||
*/
|
||||
@@ -97,5 +97,5 @@ public class TaskTakeScreenshot implements Runnable {
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -5,6 +5,12 @@ import mightypork.utils.eventbus.BusEvent;
|
||||
import mightypork.utils.eventbus.events.flags.SingleReceiverEvent;
|
||||
|
||||
|
||||
/**
|
||||
* Event that will request fullscreen toggle in the graphics module.<br>
|
||||
* FIXME the usefullness of this event is dubious.
|
||||
*
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
@SingleReceiverEvent
|
||||
public class FullscreenToggleRequest extends BusEvent<GraphicsModule> {
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package mightypork.gamecore.graphics;
|
||||
|
||||
|
||||
import mightypork.gamecore.core.BackendModule;
|
||||
import mightypork.gamecore.graphics.fonts.DeferredFont;
|
||||
import mightypork.gamecore.graphics.textures.DeferredTexture;
|
||||
import mightypork.gamecore.graphics.textures.TxQuad;
|
||||
import mightypork.gamecore.gui.events.ViewportChangeEvent;
|
||||
@@ -17,388 +18,400 @@ 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 {
|
||||
|
||||
|
||||
/** X axis vector */
|
||||
protected static final VectConst AXIS_X = Vect.make(1, 0, 0);
|
||||
/** Y axis vector */
|
||||
protected static final VectConst AXIS_Y = Vect.make(0, 1, 0);
|
||||
/** Z axis vector */
|
||||
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
|
||||
* Setup projection for 2D graphics, using current screen size
|
||||
*/
|
||||
public abstract void setupProjection();
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get backend-flavoured lazy texture
|
||||
*
|
||||
* Get backend-flavoured deferred texture. This should support PNG images.
|
||||
*
|
||||
* @param path path to texture
|
||||
* @return the lazy texture
|
||||
* @return the deferred font
|
||||
*/
|
||||
public abstract DeferredTexture getLazyTexture(String path);
|
||||
|
||||
|
||||
public abstract DeferredTexture createDeferredTexture(String path);
|
||||
|
||||
|
||||
/**
|
||||
* Get backend-flavoured deferred font. This should support TTF fonts.
|
||||
*
|
||||
* @param path path to font, or font name in the system
|
||||
* @return the deferred font
|
||||
*/
|
||||
public abstract DeferredFont createDeferredFont(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.
|
||||
*
|
||||
* Get screen center. Should always return the same {@link Vect} instance.
|
||||
*
|
||||
* @return screen center.
|
||||
*/
|
||||
public abstract Vect getCenter();
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get screen size. Should always return the same Vect instance.
|
||||
*
|
||||
* Get screen size. Should always return the same {@link Vect} instance.
|
||||
*
|
||||
* @return size
|
||||
*/
|
||||
public abstract Vect getSize();
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return screen width
|
||||
*/
|
||||
public abstract int getWidth();
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return screen height
|
||||
*/
|
||||
|
||||
@@ -3,14 +3,14 @@ package mightypork.gamecore.graphics;
|
||||
|
||||
/**
|
||||
* Can be rendered
|
||||
*
|
||||
*
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public interface Renderable {
|
||||
|
||||
|
||||
/**
|
||||
* Render on screen.
|
||||
*/
|
||||
void render();
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -18,15 +18,15 @@ import java.io.IOException;
|
||||
* 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
|
||||
*/
|
||||
|
||||
@@ -6,22 +6,33 @@ import mightypork.gamecore.resources.BaseDeferredResource;
|
||||
|
||||
|
||||
/**
|
||||
* Abstract deferred font stub.
|
||||
*
|
||||
* Deferred font stub.
|
||||
*
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public abstract class DeferredFont extends BaseDeferredResource implements IFont {
|
||||
|
||||
/**
|
||||
* Font style enum
|
||||
*/
|
||||
public static enum FontStyle
|
||||
{
|
||||
PLAIN(0), BOLD(1), ITALIC(2), BOLD_ITALIC(3);
|
||||
/** Plan style */
|
||||
PLAIN(0),
|
||||
/** Bold style */
|
||||
BOLD(1),
|
||||
/** Italic style */
|
||||
ITALIC(2),
|
||||
/** Bond and italic together */
|
||||
BOLD_ITALIC(1 + 2);
|
||||
|
||||
/** Number associated with the style */
|
||||
public int numval;
|
||||
|
||||
|
||||
/**
|
||||
* Font style
|
||||
*
|
||||
*
|
||||
* @param style style index as in awt Font. Not using constants to be
|
||||
* independent on awt.
|
||||
*/
|
||||
@@ -31,53 +42,111 @@ public abstract class DeferredFont extends BaseDeferredResource implements IFont
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Requested font size. For bitmap fonts, this should match the actual font
|
||||
* size (in pixels). The font can be scaled after loaded, but it may be
|
||||
* cached with this size.
|
||||
*/
|
||||
protected double size = 12;
|
||||
|
||||
/** Requested font style. If not applicable, fall back to PLAIN */
|
||||
protected FontStyle style = FontStyle.PLAIN;
|
||||
|
||||
/**
|
||||
* Chars that are required to be loaded in the font. A space glyph must be
|
||||
* also added when loading.
|
||||
*/
|
||||
protected String chars = Glyphs.basic;
|
||||
|
||||
/** Requested filtering mode */
|
||||
protected FilterMode filter = FilterMode.NEAREST;
|
||||
|
||||
/** Whether to use anti-aliasing for the font. */
|
||||
protected boolean antialias = false;
|
||||
|
||||
/**
|
||||
* Ratio of the font to discard at the top (how much of the glyphs height is
|
||||
* blank from top)
|
||||
*/
|
||||
protected double discardTop = 0;
|
||||
|
||||
/**
|
||||
* Ratio of the font to discard at the bottom (how much of the glyphs height
|
||||
* is blank from bottom)
|
||||
*/
|
||||
protected double discardBottom = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Make a font from resource
|
||||
*
|
||||
* @param resource the font resource
|
||||
*/
|
||||
public DeferredFont(String resource)
|
||||
{
|
||||
super(resource);
|
||||
}
|
||||
|
||||
|
||||
public void setSize(double size)
|
||||
/**
|
||||
* Set font size. If the font is backed by a texture, this is the size at
|
||||
* which the font is rendered to the texture. For bitmap fonts, this should
|
||||
* match the font height in px.
|
||||
*
|
||||
* @param size font size
|
||||
*/
|
||||
public final void setSize(double size)
|
||||
{
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
|
||||
public void setStyle(FontStyle style)
|
||||
/**
|
||||
* Set desired font style
|
||||
*
|
||||
* @param style style
|
||||
*/
|
||||
public final void setStyle(FontStyle style)
|
||||
{
|
||||
this.style = style;
|
||||
}
|
||||
|
||||
|
||||
public void setChars(String chars)
|
||||
/**
|
||||
* Set what chars are to be loaded. The space glyph will be loaded always.
|
||||
*
|
||||
* @param chars String containing chars to load (duplicates are ignored)
|
||||
*/
|
||||
public final void setChars(String chars)
|
||||
{
|
||||
this.chars = chars;
|
||||
}
|
||||
|
||||
|
||||
public void setFilter(FilterMode filter)
|
||||
/**
|
||||
* Set texture filtering mode. For bitmap fonts, set to NEAREST.
|
||||
*
|
||||
* @param filter filter mode.
|
||||
*/
|
||||
public final void setFilter(FilterMode filter)
|
||||
{
|
||||
this.filter = filter;
|
||||
}
|
||||
|
||||
|
||||
public void setAntialias(boolean antialias)
|
||||
/**
|
||||
* Set whether to use antialiasing.
|
||||
*
|
||||
* @param antialias antialias
|
||||
*/
|
||||
public final void setAntialias(boolean antialias)
|
||||
{
|
||||
this.antialias = antialias;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setDiscardRatio(double top, double bottom)
|
||||
public final void setDiscardRatio(double top, double bottom)
|
||||
{
|
||||
discardTop = top;
|
||||
discardBottom = bottom;
|
||||
@@ -85,14 +154,14 @@ public abstract class DeferredFont extends BaseDeferredResource implements IFont
|
||||
|
||||
|
||||
@Override
|
||||
public double getTopDiscardRatio()
|
||||
public final double getTopDiscardRatio()
|
||||
{
|
||||
return discardTop;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public double getBottomDiscardRatio()
|
||||
public final double getBottomDiscardRatio()
|
||||
{
|
||||
return discardBottom;
|
||||
}
|
||||
|
||||
@@ -10,32 +10,32 @@ import mightypork.utils.eventbus.clients.BusNode;
|
||||
|
||||
/**
|
||||
* 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}
|
||||
*
|
||||
* Load a {@link DeferredFont}
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
@@ -43,11 +43,11 @@ public class FontRegistry extends BusNode {
|
||||
{
|
||||
fonts.put(key, font);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Add a font alias.
|
||||
*
|
||||
*
|
||||
* @param alias_key alias key
|
||||
* @param font_key font key
|
||||
*/
|
||||
@@ -55,25 +55,25 @@ public class FontRegistry extends BusNode {
|
||||
{
|
||||
aliases.put(alias_key, font_key);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get a loaded {@link Texture}
|
||||
*
|
||||
* Get a loaded {@link IFont}
|
||||
*
|
||||
* @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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -11,16 +11,16 @@ 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
|
||||
*/
|
||||
@@ -28,8 +28,8 @@ public class FontRenderer {
|
||||
{
|
||||
this(font, RGB.WHITE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param font used font
|
||||
* @param color drawing color
|
||||
@@ -39,11 +39,11 @@ public class FontRenderer {
|
||||
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)
|
||||
@@ -52,11 +52,11 @@ public class FontRenderer {
|
||||
{
|
||||
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
|
||||
@@ -65,39 +65,39 @@ public class FontRenderer {
|
||||
{
|
||||
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
|
||||
@@ -106,21 +106,21 @@ public class FontRenderer {
|
||||
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)
|
||||
@@ -130,11 +130,11 @@ public class FontRenderer {
|
||||
{
|
||||
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)
|
||||
@@ -144,29 +144,29 @@ public class FontRenderer {
|
||||
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
|
||||
@@ -176,11 +176,11 @@ public class FontRenderer {
|
||||
{
|
||||
draw(text, pos, height, align, this.color);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Draw on screen
|
||||
*
|
||||
*
|
||||
* @param text text to draw
|
||||
* @param pos origin (min coord)
|
||||
* @param height drawing height
|
||||
@@ -189,27 +189,27 @@ public class FontRenderer {
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -2,22 +2,41 @@ package mightypork.gamecore.graphics.fonts;
|
||||
|
||||
|
||||
/**
|
||||
* Glyph tables, can be used for font loading.
|
||||
*
|
||||
* Glyph tables, can be used for font loading.<br>
|
||||
* The font should also always add a space glyph.
|
||||
*
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public class Glyphs {
|
||||
|
||||
|
||||
/** A-Z a-z */
|
||||
public static final String latin = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||
|
||||
/** Extra variants of latin glyphs */
|
||||
public static final String latin_extra = "ŒÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜŸÝßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿĚŠČŘŽŤŇĎŮěščřžťňďůŁłđ";
|
||||
|
||||
/** 0-9 */
|
||||
public static final String numbers = "0123456789";
|
||||
|
||||
/** Commonly used punctuation symbols */
|
||||
public static final String punctuation = ".-,.?!:;\"'";
|
||||
|
||||
/** Less common punctuation symbols */
|
||||
public static final String punctuation_extra = "()¿¡»«›‹“”‘’„…";
|
||||
|
||||
/** Commonly used symbols (that are not included in punctuation) */
|
||||
public static final String symbols = "[]{}#$%&§*+/<=>@\\^_|~°";
|
||||
|
||||
/** Less common symbols */
|
||||
public static final String symbols_extra = "¥€£¢`ƒ†‡ˆ‰•¤¦¨ªº¹²³¬¯±´µ¶·¸¼½¾×÷™©®→↓←↑";
|
||||
|
||||
|
||||
/** Latin, numbers, punctuation and symbols */
|
||||
public static final String basic = latin + numbers + punctuation + symbols;
|
||||
|
||||
/** Extra glyphs to accompany "basic" */
|
||||
public static final String extra = latin_extra + punctuation_extra + symbols_extra;
|
||||
|
||||
/** Basic + Extra */
|
||||
public static final String all = basic + extra;
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -7,69 +7,69 @@ 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();
|
||||
|
||||
@@ -9,14 +9,16 @@ 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 {
|
||||
|
||||
/** Used filtering mode */
|
||||
protected FilterMode filter = FilterMode.NEAREST;
|
||||
/** Used wrapping mode */
|
||||
protected WrapMode wrap = WrapMode.CLAMP;
|
||||
|
||||
|
||||
|
||||
@@ -3,10 +3,13 @@ package mightypork.gamecore.graphics.textures;
|
||||
|
||||
/**
|
||||
* Texture filtering mode
|
||||
*
|
||||
*
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public enum FilterMode
|
||||
{
|
||||
LINEAR, NEAREST;
|
||||
/** Smoothing, useful for photos */
|
||||
LINEAR,
|
||||
/** Sharp, useful for pixel art graphics */
|
||||
NEAREST;
|
||||
}
|
||||
|
||||
@@ -7,56 +7,56 @@ 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
|
||||
*/
|
||||
|
||||
@@ -5,8 +5,9 @@ import mightypork.utils.math.constraints.rect.Rect;
|
||||
|
||||
|
||||
/**
|
||||
* {@link TxQuad} and {@link TxSheet} building utility
|
||||
*
|
||||
* {@link TxQuad} and {@link TxSheet} building utility, that cuts a texture into
|
||||
* equally sized quads.
|
||||
*
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public class QuadGrid {
|
||||
@@ -18,6 +19,11 @@ public class QuadGrid {
|
||||
private final double tileH;
|
||||
|
||||
|
||||
/**
|
||||
* @param tx backing texture
|
||||
* @param tilesX number of tile columns
|
||||
* @param tilesY number of tile rows
|
||||
*/
|
||||
public QuadGrid(ITexture tx, int tilesX, int tilesY)
|
||||
{
|
||||
this.tx = tx;
|
||||
@@ -30,7 +36,7 @@ public class QuadGrid {
|
||||
|
||||
/**
|
||||
* Make square quad at given coords (one grid cell)
|
||||
*
|
||||
*
|
||||
* @param x x coordinate (cells)
|
||||
* @param y y coordinate (cells)
|
||||
* @return the quad
|
||||
@@ -48,7 +54,7 @@ public class QuadGrid {
|
||||
/**
|
||||
* 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)
|
||||
@@ -71,7 +77,7 @@ public class QuadGrid {
|
||||
|
||||
/**
|
||||
* Make a sheet.
|
||||
*
|
||||
*
|
||||
* @param x x origin coordinate (cells)
|
||||
* @param y y origin coordinate (cells)
|
||||
* @param width width (cells)
|
||||
|
||||
@@ -13,91 +13,91 @@ 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
|
||||
* @param filter filtering mode
|
||||
* @param wrap wrapping mode
|
||||
* @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
|
||||
* @param filter filtering mode
|
||||
* @param wrap wrapping mode
|
||||
* @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);
|
||||
|
||||
final DeferredTexture texture = App.gfx().createDeferredTexture(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
|
||||
*/
|
||||
@@ -105,39 +105,39 @@ public class TextureRegistry {
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import mightypork.utils.math.constraints.rect.RectConst;
|
||||
|
||||
/**
|
||||
* Texture Quad (describing a part of a texture)
|
||||
*
|
||||
*
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public class TxQuad {
|
||||
@@ -23,7 +23,7 @@ public class TxQuad {
|
||||
|
||||
/**
|
||||
* TxQuad from origin and size in pixels
|
||||
*
|
||||
*
|
||||
* @param tx texture
|
||||
* @param xPx left top X (0-1)
|
||||
* @param yPx left top Y (0-1)
|
||||
@@ -42,7 +42,7 @@ public class TxQuad {
|
||||
|
||||
/**
|
||||
* TxQuad from origin and size 0-1
|
||||
*
|
||||
*
|
||||
* @param tx texture
|
||||
* @param x1 left top X (0-1)
|
||||
* @param y1 left top Y (0-1)
|
||||
@@ -58,7 +58,7 @@ public class TxQuad {
|
||||
|
||||
/**
|
||||
* Make of coords
|
||||
*
|
||||
*
|
||||
* @param tx texture
|
||||
* @param x1 left top X (0-1)
|
||||
* @param y1 left top Y (0-1)
|
||||
@@ -84,7 +84,7 @@ public class TxQuad {
|
||||
|
||||
/**
|
||||
* Clone another
|
||||
*
|
||||
*
|
||||
* @param txQuad a copied quad
|
||||
*/
|
||||
public TxQuad(TxQuad txQuad)
|
||||
@@ -98,7 +98,7 @@ public class TxQuad {
|
||||
|
||||
/**
|
||||
* Get copy
|
||||
*
|
||||
*
|
||||
* @return copy of this
|
||||
*/
|
||||
public TxQuad copy()
|
||||
@@ -109,7 +109,7 @@ public class TxQuad {
|
||||
|
||||
/**
|
||||
* Make a sheet starting with this quad, spannign to right and down.
|
||||
*
|
||||
*
|
||||
* @param width sheet width
|
||||
* @param height sheet height
|
||||
* @return sheet
|
||||
@@ -142,12 +142,18 @@ public class TxQuad {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return true if the quad is to be rendered flipped vertically
|
||||
*/
|
||||
public boolean isFlippedY()
|
||||
{
|
||||
return flipY;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return true if the quad is to be rendered flipped horizontally
|
||||
*/
|
||||
public boolean isFlippedX()
|
||||
{
|
||||
return flipX;
|
||||
@@ -156,8 +162,8 @@ public class TxQuad {
|
||||
|
||||
/**
|
||||
* Use the same flit/other attributes as the original txQuad
|
||||
*
|
||||
* @param original
|
||||
*
|
||||
* @param original quad to copy attributes from
|
||||
*/
|
||||
public void dupeAttrs(TxQuad original)
|
||||
{
|
||||
|
||||
@@ -7,8 +7,9 @@ import mightypork.utils.logging.Log;
|
||||
|
||||
|
||||
/**
|
||||
* Basic sprite sheet
|
||||
*
|
||||
* Basic sprite sheet (cuts a {@link TxQuad} to a number of same-sized
|
||||
* sub-quads)
|
||||
*
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public class TxSheet {
|
||||
@@ -22,6 +23,13 @@ public class TxSheet {
|
||||
private final int count;
|
||||
|
||||
|
||||
/**
|
||||
* Make a sprite sheet
|
||||
*
|
||||
* @param tx backing texture quad
|
||||
* @param width number of tiles horizontally
|
||||
* @param height number of tiles vertically
|
||||
*/
|
||||
public TxSheet(TxQuad tx, int width, int height)
|
||||
{
|
||||
this.original = tx;
|
||||
@@ -43,7 +51,7 @@ public class TxSheet {
|
||||
|
||||
/**
|
||||
* Get a quad based on ratio 0-1 (0: first, 1: last)
|
||||
*
|
||||
*
|
||||
* @param ratio ratio
|
||||
* @return quad
|
||||
*/
|
||||
@@ -55,7 +63,7 @@ public class TxSheet {
|
||||
|
||||
/**
|
||||
* Get quad of index
|
||||
*
|
||||
*
|
||||
* @param index index
|
||||
* @return the quad
|
||||
*/
|
||||
@@ -86,7 +94,7 @@ public class TxSheet {
|
||||
|
||||
/**
|
||||
* Get entirely random TxQuad from this sheet
|
||||
*
|
||||
*
|
||||
* @return the picked quad
|
||||
*/
|
||||
public TxQuad getRandomQuad()
|
||||
@@ -97,7 +105,7 @@ public class TxSheet {
|
||||
|
||||
/**
|
||||
* Get random TxQuad from this sheet
|
||||
*
|
||||
*
|
||||
* @param seed random number generator seed
|
||||
* @return the picked quad
|
||||
*/
|
||||
@@ -110,7 +118,7 @@ public class TxSheet {
|
||||
|
||||
/**
|
||||
* Get random TxQuad from this sheet
|
||||
*
|
||||
*
|
||||
* @param seed random number generator seed (double will be converted to
|
||||
* long)
|
||||
* @return the picked quad
|
||||
|
||||
@@ -2,11 +2,15 @@ package mightypork.gamecore.graphics.textures;
|
||||
|
||||
|
||||
/**
|
||||
* Texture wrap mode
|
||||
*
|
||||
* Texture wrap mode (policy when rendered on larger area than can be covered by
|
||||
* the texture)
|
||||
*
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public enum WrapMode
|
||||
{
|
||||
CLAMP, REPEAT;
|
||||
/** transparent in the overlap area */
|
||||
CLAMP,
|
||||
/** repeat the texture (tiling) */
|
||||
REPEAT;
|
||||
}
|
||||
|
||||
@@ -5,8 +5,8 @@ import mightypork.utils.interfaces.Enableable;
|
||||
|
||||
|
||||
/**
|
||||
* Triggered action
|
||||
*
|
||||
* An {@link Enableable} runnable.
|
||||
*
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public abstract class Action implements Runnable, Enableable {
|
||||
@@ -16,7 +16,7 @@ public abstract class Action implements Runnable, Enableable {
|
||||
|
||||
/**
|
||||
* Enable the action
|
||||
*
|
||||
*
|
||||
* @param enable true to enable
|
||||
*/
|
||||
@Override
|
||||
|
||||
@@ -7,6 +7,12 @@ import java.util.Set;
|
||||
import mightypork.utils.interfaces.Enableable;
|
||||
|
||||
|
||||
/**
|
||||
* A group of enableable objects that propagates it's "enable" state to them
|
||||
* all.
|
||||
*
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public class ActionGroup implements Enableable {
|
||||
|
||||
private boolean enabled = true;
|
||||
@@ -30,9 +36,25 @@ public class ActionGroup implements Enableable {
|
||||
}
|
||||
|
||||
|
||||
public void add(Enableable action)
|
||||
/**
|
||||
* Add an {@link Enableable} to the group
|
||||
*
|
||||
* @param member the object to add
|
||||
*/
|
||||
public void add(Enableable member)
|
||||
{
|
||||
groupMembers.add(action);
|
||||
groupMembers.add(member);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove a group member
|
||||
*
|
||||
* @param member the object to remove
|
||||
*/
|
||||
public void remove(Enableable member)
|
||||
{
|
||||
groupMembers.remove(member);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+4
-4
@@ -3,14 +3,14 @@ package mightypork.gamecore.gui;
|
||||
|
||||
/**
|
||||
* Element that can be assigned an action (ie. button);
|
||||
*
|
||||
*
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public interface ActionTrigger {
|
||||
|
||||
public interface HasAction {
|
||||
|
||||
/**
|
||||
* Assign an action
|
||||
*
|
||||
*
|
||||
* @param action action
|
||||
*/
|
||||
void setAction(Action action);
|
||||
@@ -7,7 +7,6 @@ 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;
|
||||
@@ -20,64 +19,69 @@ 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 {
|
||||
|
||||
public abstract class BaseComponent extends AbstractRectCache implements Component, LayoutChangeListener {
|
||||
|
||||
private Rect source;
|
||||
private boolean visible = true;
|
||||
private boolean enabled = true;
|
||||
private int indirectDisableLevel = 0;
|
||||
|
||||
|
||||
private Num alphaMul = Num.ONE;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create a base component.<br>
|
||||
* By default, disable caching to avoid problems with updating. Caching can
|
||||
* be enabled by individual components.
|
||||
*/
|
||||
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()
|
||||
{
|
||||
@@ -87,63 +91,63 @@ public abstract class BaseComponent extends AbstractRectCache implements Compone
|
||||
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)
|
||||
{
|
||||
@@ -153,15 +157,15 @@ public abstract class BaseComponent extends AbstractRectCache implements Compone
|
||||
if (indirectDisableLevel > 0) indirectDisableLevel--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isIndirectlyEnabled()
|
||||
{
|
||||
return indirectDisableLevel == 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isDirectlyEnabled()
|
||||
{
|
||||
|
||||
@@ -8,86 +8,86 @@ 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
|
||||
|
||||
@@ -1,7 +1,19 @@
|
||||
package mightypork.gamecore.gui.components;
|
||||
|
||||
|
||||
/**
|
||||
* Component whose width is derived from content.<br>
|
||||
* Used for Linear components.
|
||||
*
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public interface DynamicWidthComponent extends Component {
|
||||
|
||||
|
||||
/**
|
||||
* Get current width, if the element has specified height
|
||||
*
|
||||
* @param height current height
|
||||
* @return current width
|
||||
*/
|
||||
double computeWidth(double height);
|
||||
}
|
||||
|
||||
@@ -2,11 +2,15 @@ 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 {
|
||||
|
||||
/**
|
||||
* Component used for user input, such as buttons.
|
||||
*
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public abstract class InputComponent extends BaseComponent implements ToggleableClient {
|
||||
|
||||
@Override
|
||||
public boolean isListening()
|
||||
{
|
||||
|
||||
@@ -9,77 +9,91 @@ import mightypork.utils.eventbus.clients.DelegatingList;
|
||||
import mightypork.utils.math.constraints.rect.RectBound;
|
||||
|
||||
|
||||
/**
|
||||
* Component that provides positioning to member components
|
||||
*
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public abstract class LayoutComponent extends BaseComponent implements ClientHub {
|
||||
|
||||
|
||||
private final DelegatingList clientList;
|
||||
final LinkedList<Component> components = new LinkedList<>();
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Layout component with the given context (container)
|
||||
*
|
||||
* @param context context
|
||||
*/
|
||||
public LayoutComponent(RectBound context)
|
||||
{
|
||||
this.clientList = new DelegatingList();
|
||||
setRect(context);
|
||||
enableCaching(true); // layout is typically updated only when screen resizes.
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Component without context (can be assigned a context using
|
||||
* <code>setRect()</code>)
|
||||
*/
|
||||
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)
|
||||
@@ -88,12 +102,12 @@ public abstract class LayoutComponent extends BaseComponent implements ClientHub
|
||||
if (component == this) {
|
||||
throw new IllegalArgumentException("Uruboros. (infinite recursion evaded)");
|
||||
}
|
||||
|
||||
|
||||
components.add(component);
|
||||
addChildClient(component);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void renderComponent()
|
||||
{
|
||||
@@ -101,8 +115,8 @@ public abstract class LayoutComponent extends BaseComponent implements ClientHub
|
||||
cmp.render();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void updateLayout()
|
||||
{
|
||||
@@ -110,13 +124,13 @@ public abstract class LayoutComponent extends BaseComponent implements ClientHub
|
||||
cmp.updateLayout();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void setIndirectlyEnabled(boolean yes)
|
||||
{
|
||||
super.setIndirectlyEnabled(yes);
|
||||
|
||||
|
||||
for (final Component cmp : components) {
|
||||
cmp.setIndirectlyEnabled(yes);
|
||||
}
|
||||
|
||||
@@ -8,37 +8,43 @@ import mightypork.utils.math.constraints.vect.Vect;
|
||||
import mightypork.utils.math.constraints.vect.proxy.VectAdapter;
|
||||
|
||||
|
||||
/**
|
||||
* A linear component, one whose height and origin can be set and it's width is
|
||||
* adjusted accordingly.
|
||||
*
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
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()
|
||||
{
|
||||
@@ -47,30 +53,43 @@ public abstract class LinearComponent extends BaseComponent implements DynamicWi
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
private Vect origin;
|
||||
private Num height;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create a linear component
|
||||
*/
|
||||
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.");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set component's height
|
||||
*
|
||||
* @param height the height
|
||||
*/
|
||||
public void setHeight(Num height)
|
||||
{
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set component's origin
|
||||
*
|
||||
* @param origin origin
|
||||
*/
|
||||
public void setOrigin(Vect origin)
|
||||
{
|
||||
this.origin = origin;
|
||||
|
||||
@@ -9,20 +9,20 @@ 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);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -2,47 +2,47 @@ package mightypork.gamecore.gui.components.input;
|
||||
|
||||
|
||||
import mightypork.gamecore.gui.Action;
|
||||
import mightypork.gamecore.gui.ActionTrigger;
|
||||
import mightypork.gamecore.gui.HasAction;
|
||||
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 {
|
||||
|
||||
public abstract class ClickableComponent extends InputComponent implements HasAction, 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,41 +9,41 @@ 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)
|
||||
{
|
||||
@@ -52,13 +52,13 @@ public class ClickableWrapper extends ClickableComponent implements DelegatingCl
|
||||
wrapped.setIndirectlyEnabled(yes);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void setIndirectlyEnabled(boolean yes)
|
||||
{
|
||||
super.setIndirectlyEnabled(yes);
|
||||
wrapped.setIndirectlyEnabled(yes);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -14,35 +14,35 @@ 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()
|
||||
{
|
||||
@@ -55,11 +55,11 @@ public class TextButton extends ClickableComponent implements DynamicWidthCompon
|
||||
} else {
|
||||
offset.setTo(offsetPassive);
|
||||
}
|
||||
|
||||
|
||||
textPainter.render();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Disable offset change on hover
|
||||
*/
|
||||
@@ -67,12 +67,12 @@ public class TextButton extends ClickableComponent implements DynamicWidthCompon
|
||||
{
|
||||
hoverMove = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public double computeWidth(double height)
|
||||
{
|
||||
return textPainter.computeWidth(height);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -6,37 +6,37 @@ 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;
|
||||
|
||||
@@ -8,31 +8,31 @@ 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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -11,16 +11,16 @@ 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
|
||||
@@ -31,17 +31,17 @@ public class FlowColumnLayout extends LayoutComponent {
|
||||
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.
|
||||
*/
|
||||
@@ -49,19 +49,19 @@ public class FlowColumnLayout extends LayoutComponent {
|
||||
{
|
||||
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++));
|
||||
@@ -72,16 +72,16 @@ public class FlowColumnLayout extends LayoutComponent {
|
||||
default:
|
||||
throw new IllegalArgumentException("Bad align.");
|
||||
}
|
||||
|
||||
|
||||
elem.setRect(r);
|
||||
|
||||
|
||||
attach(elem);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public void setElementWidth(Num elementWidth)
|
||||
{
|
||||
this.elementWidth = elementWidth;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -11,16 +11,16 @@ 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
|
||||
@@ -31,17 +31,17 @@ public class FlowRowLayout extends LayoutComponent {
|
||||
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.
|
||||
*/
|
||||
@@ -49,19 +49,19 @@ public class FlowRowLayout extends LayoutComponent {
|
||||
{
|
||||
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++));
|
||||
@@ -72,13 +72,13 @@ public class FlowRowLayout extends LayoutComponent {
|
||||
default:
|
||||
throw new IllegalArgumentException("Bad align.");
|
||||
}
|
||||
|
||||
|
||||
elem.setRect(r);
|
||||
|
||||
|
||||
attach(elem);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public void setElementHeight(Num elementHeight)
|
||||
{
|
||||
this.elementHeight = elementHeight;
|
||||
|
||||
@@ -9,14 +9,14 @@ 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
|
||||
@@ -27,12 +27,12 @@ public class GridLayout extends LayoutComponent {
|
||||
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
|
||||
*/
|
||||
@@ -40,11 +40,11 @@ public class GridLayout extends LayoutComponent {
|
||||
{
|
||||
this(null, rows, cols);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Add a row to the holder.
|
||||
*
|
||||
*
|
||||
* @param row row (one-based)
|
||||
* @param column column (one-based)
|
||||
* @param elem added component
|
||||
@@ -52,16 +52,16 @@ public class GridLayout extends LayoutComponent {
|
||||
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
|
||||
@@ -71,10 +71,10 @@ public class GridLayout extends LayoutComponent {
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -6,11 +6,11 @@ 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()
|
||||
{
|
||||
|
||||
@@ -6,37 +6,37 @@ 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;
|
||||
|
||||
@@ -11,15 +11,15 @@ 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.
|
||||
*/
|
||||
@@ -34,32 +34,32 @@ public abstract class AbstractLinearWrapper extends LinearComponent implements D
|
||||
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)
|
||||
{
|
||||
@@ -68,8 +68,8 @@ public abstract class AbstractLinearWrapper extends LinearComponent implements D
|
||||
wrapped.setIndirectlyEnabled(yes);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void setIndirectlyEnabled(boolean yes)
|
||||
{
|
||||
|
||||
@@ -7,17 +7,17 @@ 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);
|
||||
|
||||
@@ -16,31 +16,31 @@ 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()
|
||||
{
|
||||
@@ -55,18 +55,18 @@ public class LinearLayout extends LayoutComponent {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
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());
|
||||
@@ -75,17 +75,17 @@ public class LinearLayout extends LayoutComponent {
|
||||
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)
|
||||
|
||||
@@ -6,27 +6,27 @@ 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();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -5,17 +5,17 @@ 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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -5,17 +5,17 @@ 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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import mightypork.gamecore.gui.components.DynamicWidthComponent;
|
||||
|
||||
/**
|
||||
* Draws image in given rect
|
||||
*
|
||||
*
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public class ImagePainter extends BaseComponent implements DynamicWidthComponent {
|
||||
@@ -40,6 +40,11 @@ public class ImagePainter extends BaseComponent implements DynamicWidthComponent
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set drawn {@link TxQuad}
|
||||
*
|
||||
* @param txQuad the drawn quad
|
||||
*/
|
||||
public void setTxQuad(TxQuad txQuad)
|
||||
{
|
||||
this.txQuad = txQuad;
|
||||
|
||||
@@ -10,41 +10,41 @@ 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
|
||||
@@ -54,8 +54,8 @@ public class QuadPainter extends BaseComponent {
|
||||
{
|
||||
this.grad = new Grad(leftTop, rightTop, rightBottom, leftBottom);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void renderComponent()
|
||||
{
|
||||
|
||||
@@ -18,24 +18,24 @@ 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
|
||||
*/
|
||||
@@ -43,32 +43,32 @@ public class TextPainter extends BaseComponent implements DynamicWidthComponent
|
||||
{
|
||||
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);
|
||||
@@ -76,92 +76,92 @@ public class TextPainter extends BaseComponent implements DynamicWidthComponent
|
||||
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)
|
||||
{
|
||||
|
||||
@@ -9,20 +9,17 @@ import mightypork.utils.eventbus.events.flags.NonRejectableEvent;
|
||||
|
||||
/**
|
||||
* Intended use is to notify UI component sub-clients that they should poll
|
||||
* their cached constraints.
|
||||
*
|
||||
* their cached constraints.<br>
|
||||
* Is {@link NonRejectableEvent} to force update even of hidden screens and
|
||||
* layers.
|
||||
*
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
@DirectEvent
|
||||
@NonConsumableEvent
|
||||
@NonRejectableEvent
|
||||
public class LayoutChangeEvent extends BusEvent<LayoutChangeListener> {
|
||||
|
||||
public LayoutChangeEvent()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void handleBy(LayoutChangeListener handler)
|
||||
{
|
||||
|
||||
@@ -1,7 +1,15 @@
|
||||
package mightypork.gamecore.gui.events;
|
||||
|
||||
|
||||
/**
|
||||
* Receives notifications about layout change
|
||||
*
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public interface LayoutChangeListener {
|
||||
|
||||
/**
|
||||
* Triggered when display size changed and GUI should be recalculated.
|
||||
*/
|
||||
public void onLayoutChanged();
|
||||
}
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
package mightypork.gamecore.gui.events;
|
||||
|
||||
|
||||
import mightypork.gamecore.gui.screens.ScreenRegistry;
|
||||
import mightypork.utils.eventbus.BusEvent;
|
||||
import mightypork.utils.eventbus.events.flags.SingleReceiverEvent;
|
||||
|
||||
|
||||
/**
|
||||
* Request to change screen
|
||||
*
|
||||
* Request to change screen in {@link ScreenRegistry}
|
||||
*
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
@SingleReceiverEvent
|
||||
@@ -17,6 +18,8 @@ public class ScreenRequest extends BusEvent<ScreenRequestListener> {
|
||||
|
||||
|
||||
/**
|
||||
* Create a request to change screen
|
||||
*
|
||||
* @param screenKey screen name
|
||||
*/
|
||||
public ScreenRequest(String screenKey)
|
||||
|
||||
@@ -3,11 +3,11 @@ package mightypork.gamecore.gui.events;
|
||||
|
||||
/**
|
||||
* {@link ScreenRequest} listener
|
||||
*
|
||||
*
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public interface ScreenRequestListener {
|
||||
|
||||
|
||||
/**
|
||||
* @param key screen to show
|
||||
*/
|
||||
|
||||
@@ -9,16 +9,16 @@ 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
|
||||
*/
|
||||
@@ -26,8 +26,8 @@ public class ViewportChangeEvent extends BusEvent<ViewportChangeListener> {
|
||||
{
|
||||
this.screenSize = size;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return new screen size
|
||||
*/
|
||||
@@ -35,8 +35,8 @@ public class ViewportChangeEvent extends BusEvent<ViewportChangeListener> {
|
||||
{
|
||||
return screenSize;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void handleBy(ViewportChangeListener handler)
|
||||
{
|
||||
|
||||
@@ -3,14 +3,14 @@ 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);
|
||||
|
||||
@@ -11,47 +11,51 @@ import mightypork.utils.eventbus.clients.DelegatingClient;
|
||||
|
||||
|
||||
/**
|
||||
* Screen with multiple instances of {@link ScreenLayer}
|
||||
*
|
||||
* Screen with multiple instances of {@link ScreenLayer}. Layers specify their
|
||||
* rendering and event priority.
|
||||
*
|
||||
* @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();
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create a layered screen
|
||||
*/
|
||||
public LayeredScreen()
|
||||
{
|
||||
addChildClient(layersClient);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
protected void renderScreen()
|
||||
{
|
||||
@@ -59,40 +63,40 @@ public abstract class LayeredScreen extends Screen {
|
||||
if (layer.isVisible()) layer.render();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Add a layer to the screen.
|
||||
*
|
||||
* @param layer
|
||||
*
|
||||
* @param layer the layer to add
|
||||
*/
|
||||
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()
|
||||
{
|
||||
@@ -100,8 +104,8 @@ public abstract class LayeredScreen extends Screen {
|
||||
layer.onScreenEnter();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
protected void onScreenLeave()
|
||||
{
|
||||
@@ -109,5 +113,5 @@ public abstract class LayeredScreen extends Screen {
|
||||
layer.onScreenLeave();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -25,64 +25,66 @@ 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) */
|
||||
|
||||
/** Extra updated items (not members of the component tree) */
|
||||
protected final Collection<Updateable> updated = new ArrayList<>();
|
||||
private Num alphaMul = Num.ONE;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create an overlay over the screen
|
||||
*/
|
||||
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)
|
||||
{
|
||||
@@ -91,8 +93,8 @@ public abstract class Overlay extends BusNode implements Comparable<Overlay>, Up
|
||||
root.setVisible(visible);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void setEnabled(boolean yes)
|
||||
{
|
||||
@@ -101,35 +103,35 @@ public abstract class Overlay extends BusNode implements Comparable<Overlay>, Up
|
||||
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.
|
||||
*/
|
||||
@@ -137,34 +139,34 @@ public abstract class Overlay extends BusNode implements Comparable<Overlay>, Up
|
||||
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.
|
||||
@@ -180,41 +182,57 @@ public abstract class Overlay extends BusNode implements Comparable<Overlay>, Up
|
||||
public void onLayoutChanged()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set overlay's alpha multiplier
|
||||
*
|
||||
* @param alpha alpha multiplier
|
||||
*/
|
||||
public void setAlpha(Num alpha)
|
||||
{
|
||||
this.alphaMul = alpha;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set overlay's alpha multiplier
|
||||
*
|
||||
* @param alpha alpha multiplier
|
||||
*/
|
||||
public void setAlpha(double alpha)
|
||||
{
|
||||
this.alphaMul = Num.make(alpha);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Show and set enabled
|
||||
*/
|
||||
public void show()
|
||||
{
|
||||
setVisible(true);
|
||||
setEnabled(true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Hide and set disabled
|
||||
*/
|
||||
public void hide()
|
||||
{
|
||||
setVisible(false);
|
||||
setEnabled(false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isListening()
|
||||
{
|
||||
return (isVisible() || isEnabled());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean doesDelegate()
|
||||
{
|
||||
|
||||
@@ -17,7 +17,7 @@ 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 {
|
||||
@@ -28,9 +28,12 @@ public abstract class Screen extends BusNode implements Renderable, RectBound, K
|
||||
private volatile boolean needSetupViewport = false;
|
||||
|
||||
|
||||
/**
|
||||
* Make a screen. The screen will initially not listen to the bus, which is
|
||||
* changed once the setActive method is set to true.
|
||||
*/
|
||||
public Screen()
|
||||
{
|
||||
|
||||
// disable events initially
|
||||
setListening(false);
|
||||
|
||||
@@ -60,7 +63,7 @@ public abstract class Screen extends BusNode implements Renderable, RectBound, K
|
||||
|
||||
/**
|
||||
* Prepare for being shown
|
||||
*
|
||||
*
|
||||
* @param shown true to show, false to hide
|
||||
*/
|
||||
public final void setActive(boolean shown)
|
||||
@@ -134,6 +137,7 @@ public abstract class Screen extends BusNode implements Renderable, RectBound, K
|
||||
@Stub
|
||||
protected void onScreenEnter()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
|
||||
@@ -143,6 +147,7 @@ public abstract class Screen extends BusNode implements Renderable, RectBound, K
|
||||
@Stub
|
||||
protected void onScreenLeave()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -6,14 +6,14 @@ 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
|
||||
*/
|
||||
@@ -21,8 +21,8 @@ public abstract class ScreenLayer extends Overlay {
|
||||
{
|
||||
this.screen = screen;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return parent screen instance
|
||||
*/
|
||||
@@ -30,8 +30,8 @@ public abstract class ScreenLayer extends Overlay {
|
||||
{
|
||||
return screen;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Called when the screen becomes active
|
||||
*/
|
||||
@@ -39,8 +39,8 @@ public abstract class ScreenLayer extends Overlay {
|
||||
protected void onScreenEnter()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Called when the screen is no longer active
|
||||
*/
|
||||
|
||||
@@ -18,19 +18,19 @@ 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
|
||||
*/
|
||||
@@ -39,11 +39,11 @@ public class ScreenRegistry extends BusNode implements ScreenRequestListener, Vi
|
||||
screens.put(name, screen);
|
||||
addChildClient(screen);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Add an overlay
|
||||
*
|
||||
*
|
||||
* @param overlay added overlay
|
||||
*/
|
||||
public void addOverlay(Overlay overlay)
|
||||
@@ -51,56 +51,56 @@ public class ScreenRegistry extends BusNode implements ScreenRequestListener, Vi
|
||||
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());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ 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.gamecore.gui.screens.ScreenRegistry;
|
||||
import mightypork.utils.math.animation.Easing;
|
||||
import mightypork.utils.math.animation.NumAnimated;
|
||||
import mightypork.utils.math.color.pal.RGB;
|
||||
@@ -12,20 +13,20 @@ import mightypork.utils.math.timing.TimedTask;
|
||||
|
||||
|
||||
/**
|
||||
* Overlay used for cross-fading between screens
|
||||
*
|
||||
* Overlay used for cross-fading between screens in {@link ScreenRegistry}
|
||||
*
|
||||
* @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()
|
||||
{
|
||||
@@ -38,47 +39,55 @@ public class CrossfadeOverlay extends Overlay {
|
||||
alpha.fadeOut(T_OUT);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create new crossfade overlay
|
||||
*/
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Go to specified screen
|
||||
*
|
||||
* @param screen screen alias
|
||||
* @param fromDark true to fade from dark (ie. first screen in application)
|
||||
*/
|
||||
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);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -10,11 +10,11 @@ import mightypork.utils.eventbus.events.flags.SingleReceiverEvent;
|
||||
*/
|
||||
@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)
|
||||
@@ -25,8 +25,8 @@ public class CrossfadeRequest extends BusEvent<CrossfadeOverlay> {
|
||||
this.screen = screen;
|
||||
this.fromDark = fromDark;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param screen screen key to show. Null = exit the app.
|
||||
*/
|
||||
@@ -36,12 +36,12 @@ public class CrossfadeRequest extends BusEvent<CrossfadeOverlay> {
|
||||
this.screen = screen;
|
||||
this.fromDark = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void handleBy(CrossfadeOverlay handler)
|
||||
{
|
||||
handler.goToScreen(screen, fromDark);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ 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 {
|
||||
@@ -44,8 +44,8 @@ public abstract class FadingLayer extends ScreenLayer {
|
||||
|
||||
/**
|
||||
* Create with default fading time and effect
|
||||
*
|
||||
* @param screen
|
||||
*
|
||||
* @param screen the parent screen
|
||||
*/
|
||||
public FadingLayer(Screen screen)
|
||||
{
|
||||
@@ -54,7 +54,9 @@ public abstract class FadingLayer extends ScreenLayer {
|
||||
|
||||
|
||||
/**
|
||||
* @param screen
|
||||
* Create with custom animator
|
||||
*
|
||||
* @param screen the parent screen
|
||||
* @param easingAnim the animation num
|
||||
*/
|
||||
public FadingLayer(Screen screen, NumAnimated easingAnim)
|
||||
|
||||
@@ -7,11 +7,23 @@ import mightypork.gamecore.gui.screens.ScreenLayer;
|
||||
import mightypork.utils.math.color.Color;
|
||||
|
||||
|
||||
/**
|
||||
* Screen overlay with a given color.
|
||||
*
|
||||
* @author Ondřej Hruška (MightyPork)
|
||||
*/
|
||||
public class LayerColor extends ScreenLayer {
|
||||
|
||||
private final int zIndex;
|
||||
|
||||
|
||||
/**
|
||||
* Overlay with color
|
||||
*
|
||||
* @param screen the parent screen
|
||||
* @param color the used color
|
||||
* @param zIndex z-index in the screen
|
||||
*/
|
||||
public LayerColor(Screen screen, Color color, int zIndex)
|
||||
{
|
||||
super(screen);
|
||||
|
||||
@@ -11,89 +11,89 @@ import mightypork.utils.math.constraints.vect.Vect;
|
||||
* 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
|
||||
*/
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user