diff --git a/src/junk/AppInitOptions.java b/src/junk/AppInitOptions.java index 3066eb1..22ac9ee 100644 --- a/src/junk/AppInitOptions.java +++ b/src/junk/AppInitOptions.java @@ -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 resourceLists = new ArrayList<>(); final List keyLists = new ArrayList<>(); final List 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.
* 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; diff --git a/src/junk/BaseApp.java b/src/junk/BaseApp.java index b1a38a3..50a9728 100644 --- a/src/junk/BaseApp.java +++ b/src/junk/BaseApp.java @@ -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.
* 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() { // ??? diff --git a/src/junk/DisplaySystem.java b/src/junk/DisplaySystem.java index ddd089c..da8fee4 100644 --- a/src/junk/DisplaySystem.java +++ b/src/junk/DisplaySystem.java @@ -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).
// * 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() diff --git a/src/junk/Render.java b/src/junk/Render.java index 7182d30..16e451c 100644 --- a/src/junk/Render.java +++ b/src/junk/Render.java @@ -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(); diff --git a/src/junk/SoundSystem.java b/src/junk/SoundSystem.java index da75ea4..1357671 100644 --- a/src/junk/SoundSystem.java +++ b/src/junk/SoundSystem.java @@ -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 loopPlayers = new ArrayList<>(); // private final List 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() diff --git a/src/mightypork/gamecore/audio/AudioModule.java b/src/mightypork/gamecore/audio/AudioModule.java index 9112fd3..eb0f3e6 100644 --- a/src/mightypork/gamecore/audio/AudioModule.java +++ b/src/mightypork/gamecore/audio/AudioModule.java @@ -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 loopPlayers = new ArrayList<>(); private final List resources = new ArrayList<>(); - - + + @Override public void destroy() { for (final DeferredAudio r : resources) { r.destroy(); } - + deinitSoundSystem(); } - - + + /** * Deinitialize the soud system, release resources etc.
* 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() diff --git a/src/mightypork/gamecore/audio/DeferredAudio.java b/src/mightypork/gamecore/audio/DeferredAudio.java index b9b0f4f..c33f30f 100644 --- a/src/mightypork/gamecore/audio/DeferredAudio.java +++ b/src/mightypork/gamecore/audio/DeferredAudio.java @@ -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) { diff --git a/src/mightypork/gamecore/audio/IAudio.java b/src/mightypork/gamecore/audio/IAudio.java index a89d2c1..f4533fd 100644 --- a/src/mightypork/gamecore/audio/IAudio.java +++ b/src/mightypork/gamecore/audio/IAudio.java @@ -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); - + } diff --git a/src/mightypork/gamecore/audio/JointVolume.java b/src/mightypork/gamecore/audio/JointVolume.java index 7d8f8db..ba79708 100644 --- a/src/mightypork/gamecore/audio/JointVolume.java +++ b/src/mightypork/gamecore/audio/JointVolume.java @@ -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 */ diff --git a/src/mightypork/gamecore/audio/SoundRegistry.java b/src/mightypork/gamecore/audio/SoundRegistry.java index 1aaf03d..cdaa153 100644 --- a/src/mightypork/gamecore/audio/SoundRegistry.java +++ b/src/mightypork/gamecore/audio/SoundRegistry.java @@ -11,18 +11,18 @@ import mightypork.gamecore.core.App; /** * Audio resource storage - * + * * @author Ondřej Hruška (MightyPork) */ public class SoundRegistry { - + private final Map effects = new HashMap<>(); private final Map 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 */ diff --git a/src/mightypork/gamecore/audio/Volume.java b/src/mightypork/gamecore/audio/Volume.java index fde5224..731a355 100644 --- a/src/mightypork/gamecore/audio/Volume.java +++ b/src/mightypork/gamecore/audio/Volume.java @@ -7,11 +7,11 @@ import mightypork.utils.struct.Mutable; /** * Mutable volume 0-1 - * + * * @author Ondřej Hruška (MightyPork) */ public class Volume extends Mutable { - + /** * @param d initial value */ @@ -19,12 +19,12 @@ public class Volume extends Mutable { { super(d); } - - + + @Override public void set(Double d) { super.set(Calc.clamp(d, 0, 1)); } - + } diff --git a/src/mightypork/gamecore/audio/players/BaseAudioPlayer.java b/src/mightypork/gamecore/audio/players/BaseAudioPlayer.java index 99ff14d..a6c21b5 100644 --- a/src/mightypork/gamecore/audio/players/BaseAudioPlayer.java +++ b/src/mightypork/gamecore/audio/players/BaseAudioPlayer.java @@ -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 */ diff --git a/src/mightypork/gamecore/audio/players/EffectPlayer.java b/src/mightypork/gamecore/audio/players/EffectPlayer.java index 6f1977c..eeaf526 100644 --- a/src/mightypork/gamecore/audio/players/EffectPlayer.java +++ b/src/mightypork/gamecore/audio/players/EffectPlayer.java @@ -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); } - + } diff --git a/src/mightypork/gamecore/audio/players/LoopPlayer.java b/src/mightypork/gamecore/audio/players/LoopPlayer.java index 4a607b8..3440cf7 100644 --- a/src/mightypork/gamecore/audio/players/LoopPlayer.java +++ b/src/mightypork/gamecore/audio/players/LoopPlayer.java @@ -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); } - + } diff --git a/src/mightypork/gamecore/core/App.java b/src/mightypork/gamecore/core/App.java index f0a61aa..7cf9054 100644 --- a/src/mightypork/gamecore/core/App.java +++ b/src/mightypork/gamecore/core/App.java @@ -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 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 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. diff --git a/src/mightypork/gamecore/core/AppBackend.java b/src/mightypork/gamecore/core/AppBackend.java index f2f03ed..9d7bb72 100644 --- a/src/mightypork/gamecore/core/AppBackend.java +++ b/src/mightypork/gamecore/core/AppBackend.java @@ -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 bind() */ 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(); diff --git a/src/mightypork/gamecore/core/AppPlugin.java b/src/mightypork/gamecore/core/AppPlugin.java index ff9783a..043e1d3 100644 --- a/src/mightypork/gamecore/core/AppPlugin.java +++ b/src/mightypork/gamecore/core/AppPlugin.java @@ -9,20 +9,26 @@ import mightypork.utils.eventbus.clients.BusNode; * App plugin. Plugins are an easy way to extend app functionality.
* 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 bind() */ 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.
* The plugin is already attached to the event bus. diff --git a/src/mightypork/gamecore/core/BackendModule.java b/src/mightypork/gamecore/core/BackendModule.java index a4dd870..038343e 100644 --- a/src/mightypork/gamecore/core/BackendModule.java +++ b/src/mightypork/gamecore/core/BackendModule.java @@ -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.
+ * 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() diff --git a/src/mightypork/gamecore/core/InitTask.java b/src/mightypork/gamecore/core/InitTask.java index ff0ec41..cd3923a 100644 --- a/src/mightypork/gamecore/core/InitTask.java +++ b/src/mightypork/gamecore/core/InitTask.java @@ -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 bind() */ 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.
+ * An init method that is called before the run() method.
* 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.
+ * 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.
+ * Can be overridden during app configuration to "bake-in" extra actions. + */ + @Stub + public void after() + { + // + } + + /** * Get name of this initializer (for dependency resolver).
* 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.
* Depending on itself or creating a circular dependency will cause error.
* 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 inOrder(List tasks) { final List remaining = new ArrayList<>(tasks); - + final List ordered = new ArrayList<>(); final Set loaded = new HashSet<>(); - + // resolve task order int addedThisIteration = 0; do { for (final Iterator 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; } } diff --git a/src/mightypork/gamecore/core/MainLoop.java b/src/mightypork/gamecore/core/MainLoop.java index b215045..f5edbdc 100644 --- a/src/mightypork/gamecore/core/MainLoop.java +++ b/src/mightypork/gamecore/core/MainLoop.java @@ -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.
+ * If delta is larger than this, it's clamped to it. + */ + protected double MAX_DELTA = 1 / 20D; + private final Deque 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); } } - + } diff --git a/src/mightypork/gamecore/core/OptionalInitTask.java b/src/mightypork/gamecore/core/OptionalInitTask.java index c5e3748..b6dbab2 100644 --- a/src/mightypork/gamecore/core/OptionalInitTask.java +++ b/src/mightypork/gamecore/core/OptionalInitTask.java @@ -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 { - + } diff --git a/src/mightypork/gamecore/core/WorkDir.java b/src/mightypork/gamecore/core/WorkDir.java deleted file mode 100644 index 12bdf51..0000000 --- a/src/mightypork/gamecore/core/WorkDir.java +++ /dev/null @@ -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 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; - } - -} diff --git a/src/mightypork/gamecore/core/config/Config.java b/src/mightypork/gamecore/core/config/Config.java index 8a6dad2..e88bcec 100644 --- a/src/mightypork/gamecore/core/config/Config.java +++ b/src/mightypork/gamecore/core/config/Config.java @@ -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 configs = new HashMap<>(); - + private final Map 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 void addProperty(Property 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 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); } } diff --git a/src/mightypork/gamecore/core/config/InitTaskConfig.java b/src/mightypork/gamecore/core/config/InitTaskConfig.java index 0ced5e9..0f65c89 100644 --- a/src/mightypork/gamecore/core/config/InitTaskConfig.java +++ b/src/mightypork/gamecore/core/config/InitTaskConfig.java @@ -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.
* 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" }; } - + } diff --git a/src/mightypork/gamecore/core/config/KeyStrokeProperty.java b/src/mightypork/gamecore/core/config/KeyStrokeProperty.java index 86c9cba..381266d 100644 --- a/src/mightypork/gamecore/core/config/KeyStrokeProperty.java +++ b/src/mightypork/gamecore/core/config/KeyStrokeProperty.java @@ -12,41 +12,48 @@ import mightypork.utils.config.propmgr.Property; * The stored value must stay the same instance ({@link KeyStroke} is mutable).
* 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 { - + + /** + * 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) { diff --git a/src/mightypork/gamecore/core/events/MainLoopRequest.java b/src/mightypork/gamecore/core/events/MainLoopRequest.java index 520a967..e21a64e 100644 --- a/src/mightypork/gamecore/core/events/MainLoopRequest.java +++ b/src/mightypork/gamecore/core/events/MainLoopRequest.java @@ -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 { - + 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 { { 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 { this.task = task; this.priority = priority; } - - + + @Override public void handleBy(MainLoop handler) { diff --git a/src/mightypork/gamecore/core/events/ShutdownEvent.java b/src/mightypork/gamecore/core/events/ShutdownEvent.java index f0b9cea..8653b29 100644 --- a/src/mightypork/gamecore/core/events/ShutdownEvent.java +++ b/src/mightypork/gamecore/core/events/ShutdownEvent.java @@ -10,10 +10,8 @@ import mightypork.utils.logging.Log; * Shutdown event.
* This event is dispatched when the App.shutdown() method is * called. If no client consumes it, the shutdown will immediately follow.
- * This is a way to allow clients to abort the shutdown (ie. ask user to save - * game). After the game is saved, the App.shutdown() 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 { @@ -21,6 +19,11 @@ public class ShutdownEvent extends BusEvent { private final Runnable shutdownTask; + /** + * Make a shutdown event + * + * @param doShutdown Task that does the actual shutdown + */ public ShutdownEvent(Runnable doShutdown) { this.shutdownTask = doShutdown; diff --git a/src/mightypork/gamecore/core/events/ShutdownListener.java b/src/mightypork/gamecore/core/events/ShutdownListener.java index 00ebc10..38a9733 100644 --- a/src/mightypork/gamecore/core/events/ShutdownListener.java +++ b/src/mightypork/gamecore/core/events/ShutdownListener.java @@ -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.
* Consume the event to abort shutdown (ie. ask user to save) - * + * * @param event quit request event. */ void onShutdown(ShutdownEvent event); diff --git a/src/mightypork/gamecore/core/init/InitTaskCrashHandler.java b/src/mightypork/gamecore/core/init/InitTaskCrashHandler.java index dcf8122..0abea2c 100644 --- a/src/mightypork/gamecore/core/init/InitTaskCrashHandler.java +++ b/src/mightypork/gamecore/core/init/InitTaskCrashHandler.java @@ -13,18 +13,18 @@ import mightypork.utils.logging.Log; * Add a crash handler to the app.
* 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() { diff --git a/src/mightypork/gamecore/core/init/InitTaskDisplay.java b/src/mightypork/gamecore/core/init/InitTaskDisplay.java index aefdf1b..2b38350 100644 --- a/src/mightypork/gamecore/core/init/InitTaskDisplay.java +++ b/src/mightypork/gamecore/core/init/InitTaskDisplay.java @@ -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"; } - + } diff --git a/src/mightypork/gamecore/core/init/InitTaskIonizables.java b/src/mightypork/gamecore/core/init/InitTaskIonizables.java index f686da0..b9abd49 100644 --- a/src/mightypork/gamecore/core/init/InitTaskIonizables.java +++ b/src/mightypork/gamecore/core/init/InitTaskIonizables.java @@ -15,24 +15,24 @@ import mightypork.utils.math.algo.Move; /** * Register extra ionizables added by the game library (non-native ION types).
* 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() { - + @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() { - + @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"; } - + } diff --git a/src/mightypork/gamecore/core/init/InitTaskLog.java b/src/mightypork/gamecore/core/init/InitTaskLog.java index 4b34e1a..7783117 100644 --- a/src/mightypork/gamecore/core/init/InitTaskLog.java +++ b/src/mightypork/gamecore/core/init/InitTaskLog.java @@ -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.
* 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).
* 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.
* Should contain only valid filename characters.
* 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.
* Set to 0 to keep just the last log, -1 to keep unlimited number of logs.
* 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)
* 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() { diff --git a/src/mightypork/gamecore/core/init/InitTaskLogHeader.java b/src/mightypork/gamecore/core/init/InitTaskLogHeader.java index 96a9788..2c62257 100644 --- a/src/mightypork/gamecore/core/init/InitTaskLogHeader.java +++ b/src/mightypork/gamecore/core/init/InitTaskLogHeader.java @@ -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.
* 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() { diff --git a/src/mightypork/gamecore/core/init/InitTaskWorkdir.java b/src/mightypork/gamecore/core/init/InitTaskWorkdir.java index 46f1eaf..4a6c9ab 100644 --- a/src/mightypork/gamecore/core/init/InitTaskWorkdir.java +++ b/src/mightypork/gamecore/core/init/InitTaskWorkdir.java @@ -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 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 e : namedPaths.entrySet()) { WorkDir.addPath(e.getKey(), e.getValue()); } } - - + + /** * Called when the lock file could not be obtained (cannot write or already * exists).
@@ -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() { diff --git a/src/mightypork/gamecore/core/plugins/screenshot/InitTaskPluginScreenshot.java b/src/mightypork/gamecore/core/plugins/screenshot/InitTaskPluginScreenshot.java index 2abbf01..e4cfa2e 100644 --- a/src/mightypork/gamecore/core/plugins/screenshot/InitTaskPluginScreenshot.java +++ b/src/mightypork/gamecore/core/plugins/screenshot/InitTaskPluginScreenshot.java @@ -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" }; } - + } diff --git a/src/mightypork/gamecore/core/plugins/screenshot/ScreenshotPlugin.java b/src/mightypork/gamecore/core/plugins/screenshot/ScreenshotPlugin.java index 4dd08b2..1de6c4f 100644 --- a/src/mightypork/gamecore/core/plugins/screenshot/ScreenshotPlugin.java +++ b/src/mightypork/gamecore/core/plugins/screenshot/ScreenshotPlugin.java @@ -11,18 +11,18 @@ import mightypork.utils.Support; * This plugin waits for a {@link ScreenshotRequest} event.
* 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() { diff --git a/src/mightypork/gamecore/core/plugins/screenshot/ScreenshotRequest.java b/src/mightypork/gamecore/core/plugins/screenshot/ScreenshotRequest.java index be37967..8ae207d 100644 --- a/src/mightypork/gamecore/core/plugins/screenshot/ScreenshotRequest.java +++ b/src/mightypork/gamecore/core/plugins/screenshot/ScreenshotRequest.java @@ -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 { - + @Override protected void handleBy(ScreenshotPlugin handler) { handler.takeScreenshot(); } - + } diff --git a/src/mightypork/gamecore/core/plugins/screenshot/TaskTakeScreenshot.java b/src/mightypork/gamecore/core/plugins/screenshot/TaskTakeScreenshot.java index 9ffda5f..8c5051b 100644 --- a/src/mightypork/gamecore/core/plugins/screenshot/TaskTakeScreenshot.java +++ b/src/mightypork/gamecore/core/plugins/screenshot/TaskTakeScreenshot.java @@ -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.
* 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; } - + } diff --git a/src/mightypork/gamecore/graphics/FullscreenToggleRequest.java b/src/mightypork/gamecore/graphics/FullscreenToggleRequest.java index eeff3b8..b49a6cf 100644 --- a/src/mightypork/gamecore/graphics/FullscreenToggleRequest.java +++ b/src/mightypork/gamecore/graphics/FullscreenToggleRequest.java @@ -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.
+ * FIXME the usefullness of this event is dubious. + * + * @author Ondřej Hruška (MightyPork) + */ @SingleReceiverEvent public class FullscreenToggleRequest extends BusEvent { diff --git a/src/mightypork/gamecore/graphics/GraphicsModule.java b/src/mightypork/gamecore/graphics/GraphicsModule.java index f895888..a942a6e 100644 --- a/src/mightypork/gamecore/graphics/GraphicsModule.java +++ b/src/mightypork/gamecore/graphics/GraphicsModule.java @@ -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.
* 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
* This includes pushGeometry and pushColor. */ public abstract void pushState(); - - + + /** * Restore state from stack (must be pushed first)
* 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.
* 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.
* 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).
* 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).
* 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 */ diff --git a/src/mightypork/gamecore/graphics/Renderable.java b/src/mightypork/gamecore/graphics/Renderable.java index 6c6a236..3a967d4 100644 --- a/src/mightypork/gamecore/graphics/Renderable.java +++ b/src/mightypork/gamecore/graphics/Renderable.java @@ -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(); - + } diff --git a/src/mightypork/gamecore/graphics/Screenshot.java b/src/mightypork/gamecore/graphics/Screenshot.java index 00c2a5c..f00170e 100644 --- a/src/mightypork/gamecore/graphics/Screenshot.java +++ b/src/mightypork/gamecore/graphics/Screenshot.java @@ -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. *

- * + * * @author MightyPork */ public interface Screenshot { - + /** * Process byte buffer and write image to a file.
* Image can be cached for future save. - * + * * @param file target file * @throws IOException on error writing to file */ diff --git a/src/mightypork/gamecore/graphics/fonts/DeferredFont.java b/src/mightypork/gamecore/graphics/fonts/DeferredFont.java index 9136bfc..4791138 100644 --- a/src/mightypork/gamecore/graphics/fonts/DeferredFont.java +++ b/src/mightypork/gamecore/graphics/fonts/DeferredFont.java @@ -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; } diff --git a/src/mightypork/gamecore/graphics/fonts/FontRegistry.java b/src/mightypork/gamecore/graphics/fonts/FontRegistry.java index 9c80f17..d47f395 100644 --- a/src/mightypork/gamecore/graphics/fonts/FontRegistry.java +++ b/src/mightypork/gamecore/graphics/fonts/FontRegistry.java @@ -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 fonts = new HashMap<>(); private final HashMap 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; } - + } diff --git a/src/mightypork/gamecore/graphics/fonts/FontRenderer.java b/src/mightypork/gamecore/graphics/fonts/FontRenderer.java index e2d421b..d3fa1ad 100644 --- a/src/mightypork/gamecore/graphics/fonts/FontRenderer.java +++ b/src/mightypork/gamecore/graphics/fonts/FontRenderer.java @@ -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); } - + } diff --git a/src/mightypork/gamecore/graphics/fonts/Glyphs.java b/src/mightypork/gamecore/graphics/fonts/Glyphs.java index 0b9b7a8..6646381 100644 --- a/src/mightypork/gamecore/graphics/fonts/Glyphs.java +++ b/src/mightypork/gamecore/graphics/fonts/Glyphs.java @@ -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.
+ * 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; - + } diff --git a/src/mightypork/gamecore/graphics/fonts/IFont.java b/src/mightypork/gamecore/graphics/fonts/IFont.java index ef08b1a..9a78765 100644 --- a/src/mightypork/gamecore/graphics/fonts/IFont.java +++ b/src/mightypork/gamecore/graphics/fonts/IFont.java @@ -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(); diff --git a/src/mightypork/gamecore/graphics/textures/DeferredTexture.java b/src/mightypork/gamecore/graphics/textures/DeferredTexture.java index 5512efe..f5441f6 100644 --- a/src/mightypork/gamecore/graphics/textures/DeferredTexture.java +++ b/src/mightypork/gamecore/graphics/textures/DeferredTexture.java @@ -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; diff --git a/src/mightypork/gamecore/graphics/textures/FilterMode.java b/src/mightypork/gamecore/graphics/textures/FilterMode.java index cd9c510..bac6bf5 100644 --- a/src/mightypork/gamecore/graphics/textures/FilterMode.java +++ b/src/mightypork/gamecore/graphics/textures/FilterMode.java @@ -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; } diff --git a/src/mightypork/gamecore/graphics/textures/ITexture.java b/src/mightypork/gamecore/graphics/textures/ITexture.java index 17a8856..d862319 100644 --- a/src/mightypork/gamecore/graphics/textures/ITexture.java +++ b/src/mightypork/gamecore/graphics/textures/ITexture.java @@ -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 */ diff --git a/src/mightypork/gamecore/graphics/textures/QuadGrid.java b/src/mightypork/gamecore/graphics/textures/QuadGrid.java index 4b69de1..bcd76a3 100644 --- a/src/mightypork/gamecore/graphics/textures/QuadGrid.java +++ b/src/mightypork/gamecore/graphics/textures/QuadGrid.java @@ -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) diff --git a/src/mightypork/gamecore/graphics/textures/TextureRegistry.java b/src/mightypork/gamecore/graphics/textures/TextureRegistry.java index 1d3408b..af299b4 100644 --- a/src/mightypork/gamecore/graphics/textures/TextureRegistry.java +++ b/src/mightypork/gamecore/graphics/textures/TextureRegistry.java @@ -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 textures = new HashMap<>(); private final Map 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; } - + } diff --git a/src/mightypork/gamecore/graphics/textures/TxQuad.java b/src/mightypork/gamecore/graphics/textures/TxQuad.java index a2ac9ba..ef042f1 100644 --- a/src/mightypork/gamecore/graphics/textures/TxQuad.java +++ b/src/mightypork/gamecore/graphics/textures/TxQuad.java @@ -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) { diff --git a/src/mightypork/gamecore/graphics/textures/TxSheet.java b/src/mightypork/gamecore/graphics/textures/TxSheet.java index d1be58e..0017739 100644 --- a/src/mightypork/gamecore/graphics/textures/TxSheet.java +++ b/src/mightypork/gamecore/graphics/textures/TxSheet.java @@ -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 diff --git a/src/mightypork/gamecore/graphics/textures/WrapMode.java b/src/mightypork/gamecore/graphics/textures/WrapMode.java index bd6ce41..8bbe09c 100644 --- a/src/mightypork/gamecore/graphics/textures/WrapMode.java +++ b/src/mightypork/gamecore/graphics/textures/WrapMode.java @@ -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; } diff --git a/src/mightypork/gamecore/gui/Action.java b/src/mightypork/gamecore/gui/Action.java index e8ac2d2..a9edad2 100644 --- a/src/mightypork/gamecore/gui/Action.java +++ b/src/mightypork/gamecore/gui/Action.java @@ -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 diff --git a/src/mightypork/gamecore/gui/ActionGroup.java b/src/mightypork/gamecore/gui/ActionGroup.java index b7dc37c..6544423 100644 --- a/src/mightypork/gamecore/gui/ActionGroup.java +++ b/src/mightypork/gamecore/gui/ActionGroup.java @@ -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); } } diff --git a/src/mightypork/gamecore/gui/ActionTrigger.java b/src/mightypork/gamecore/gui/HasAction.java similarity index 83% rename from src/mightypork/gamecore/gui/ActionTrigger.java rename to src/mightypork/gamecore/gui/HasAction.java index e12d4db..d8e156d 100644 --- a/src/mightypork/gamecore/gui/ActionTrigger.java +++ b/src/mightypork/gamecore/gui/HasAction.java @@ -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); diff --git a/src/mightypork/gamecore/gui/components/BaseComponent.java b/src/mightypork/gamecore/gui/components/BaseComponent.java index 81363c3..00239d5 100644 --- a/src/mightypork/gamecore/gui/components/BaseComponent.java +++ b/src/mightypork/gamecore/gui/components/BaseComponent.java @@ -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.
+ * 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() { diff --git a/src/mightypork/gamecore/gui/components/Component.java b/src/mightypork/gamecore/gui/components/Component.java index 2375efc..8468460 100644 --- a/src/mightypork/gamecore/gui/components/Component.java +++ b/src/mightypork/gamecore/gui/components/Component.java @@ -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.
* 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 diff --git a/src/mightypork/gamecore/gui/components/DynamicWidthComponent.java b/src/mightypork/gamecore/gui/components/DynamicWidthComponent.java index 06e51b4..6a61e67 100644 --- a/src/mightypork/gamecore/gui/components/DynamicWidthComponent.java +++ b/src/mightypork/gamecore/gui/components/DynamicWidthComponent.java @@ -1,7 +1,19 @@ package mightypork.gamecore.gui.components; +/** + * Component whose width is derived from content.
+ * 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); } diff --git a/src/mightypork/gamecore/gui/components/InputComponent.java b/src/mightypork/gamecore/gui/components/InputComponent.java index 8f35f95..e44784d 100644 --- a/src/mightypork/gamecore/gui/components/InputComponent.java +++ b/src/mightypork/gamecore/gui/components/InputComponent.java @@ -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() { diff --git a/src/mightypork/gamecore/gui/components/LayoutComponent.java b/src/mightypork/gamecore/gui/components/LayoutComponent.java index e90ab1d..51bbb60 100644 --- a/src/mightypork/gamecore/gui/components/LayoutComponent.java +++ b/src/mightypork/gamecore/gui/components/LayoutComponent.java @@ -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 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 + * setRect()) + */ public LayoutComponent() { this(null); } - - + + @Override public Collection 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); } diff --git a/src/mightypork/gamecore/gui/components/LinearComponent.java b/src/mightypork/gamecore/gui/components/LinearComponent.java index 893149c..debc634 100644 --- a/src/mightypork/gamecore/gui/components/LinearComponent.java +++ b/src/mightypork/gamecore/gui/components/LinearComponent.java @@ -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; diff --git a/src/mightypork/gamecore/gui/components/PluggableRenderable.java b/src/mightypork/gamecore/gui/components/PluggableRenderable.java index e53c245..97fa698 100644 --- a/src/mightypork/gamecore/gui/components/PluggableRenderable.java +++ b/src/mightypork/gamecore/gui/components/PluggableRenderable.java @@ -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); - + } diff --git a/src/mightypork/gamecore/gui/components/input/ClickableComponent.java b/src/mightypork/gamecore/gui/components/input/ClickableComponent.java index 186c7ab..8714cd5 100644 --- a/src/mightypork/gamecore/gui/components/input/ClickableComponent.java +++ b/src/mightypork/gamecore/gui/components/input/ClickableComponent.java @@ -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; } } diff --git a/src/mightypork/gamecore/gui/components/input/ClickableWrapper.java b/src/mightypork/gamecore/gui/components/input/ClickableWrapper.java index 45dc6b7..8292e6c 100644 --- a/src/mightypork/gamecore/gui/components/input/ClickableWrapper.java +++ b/src/mightypork/gamecore/gui/components/input/ClickableWrapper.java @@ -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); } - + } diff --git a/src/mightypork/gamecore/gui/components/input/TextButton.java b/src/mightypork/gamecore/gui/components/input/TextButton.java index d630308..5a7c36e 100644 --- a/src/mightypork/gamecore/gui/components/input/TextButton.java +++ b/src/mightypork/gamecore/gui/components/input/TextButton.java @@ -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); } - + } diff --git a/src/mightypork/gamecore/gui/components/layout/ColumnLayout.java b/src/mightypork/gamecore/gui/components/layout/ColumnLayout.java index 9b3f317..c1b7cd1 100644 --- a/src/mightypork/gamecore/gui/components/layout/ColumnLayout.java +++ b/src/mightypork/gamecore/gui/components/layout/ColumnLayout.java @@ -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; diff --git a/src/mightypork/gamecore/gui/components/layout/ConstraintLayout.java b/src/mightypork/gamecore/gui/components/layout/ConstraintLayout.java index 6f4cc09..2a73a07 100644 --- a/src/mightypork/gamecore/gui/components/layout/ConstraintLayout.java +++ b/src/mightypork/gamecore/gui/components/layout/ConstraintLayout.java @@ -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.
* The component's rect must be set up manually. - * + * * @param component */ public void add(Component component) { attach(component); } - + } diff --git a/src/mightypork/gamecore/gui/components/layout/FlowColumnLayout.java b/src/mightypork/gamecore/gui/components/layout/FlowColumnLayout.java index bd6a315..3c99299 100644 --- a/src/mightypork/gamecore/gui/components/layout/FlowColumnLayout.java +++ b/src/mightypork/gamecore/gui/components/layout/FlowColumnLayout.java @@ -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.
* 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; } - + } diff --git a/src/mightypork/gamecore/gui/components/layout/FlowRowLayout.java b/src/mightypork/gamecore/gui/components/layout/FlowRowLayout.java index aa3b119..2fa9be5 100644 --- a/src/mightypork/gamecore/gui/components/layout/FlowRowLayout.java +++ b/src/mightypork/gamecore/gui/components/layout/FlowRowLayout.java @@ -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.
* 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; diff --git a/src/mightypork/gamecore/gui/components/layout/GridLayout.java b/src/mightypork/gamecore/gui/components/layout/GridLayout.java index 72e39b0..ab31c58 100644 --- a/src/mightypork/gamecore/gui/components/layout/GridLayout.java +++ b/src/mightypork/gamecore/gui/components/layout/GridLayout.java @@ -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.
* 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); } - + } diff --git a/src/mightypork/gamecore/gui/components/layout/NullComponent.java b/src/mightypork/gamecore/gui/components/layout/NullComponent.java index f04964b..ed24b2d 100644 --- a/src/mightypork/gamecore/gui/components/layout/NullComponent.java +++ b/src/mightypork/gamecore/gui/components/layout/NullComponent.java @@ -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() { diff --git a/src/mightypork/gamecore/gui/components/layout/RowLayout.java b/src/mightypork/gamecore/gui/components/layout/RowLayout.java index aed15d1..9135763 100644 --- a/src/mightypork/gamecore/gui/components/layout/RowLayout.java +++ b/src/mightypork/gamecore/gui/components/layout/RowLayout.java @@ -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; diff --git a/src/mightypork/gamecore/gui/components/layout/linear/AbstractLinearWrapper.java b/src/mightypork/gamecore/gui/components/layout/linear/AbstractLinearWrapper.java index d2142b5..e0f1863 100644 --- a/src/mightypork/gamecore/gui/components/layout/linear/AbstractLinearWrapper.java +++ b/src/mightypork/gamecore/gui/components/layout/linear/AbstractLinearWrapper.java @@ -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) { diff --git a/src/mightypork/gamecore/gui/components/layout/linear/LinearGap.java b/src/mightypork/gamecore/gui/components/layout/linear/LinearGap.java index d5f6d25..228d76f 100644 --- a/src/mightypork/gamecore/gui/components/layout/linear/LinearGap.java +++ b/src/mightypork/gamecore/gui/components/layout/linear/LinearGap.java @@ -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); diff --git a/src/mightypork/gamecore/gui/components/layout/linear/LinearLayout.java b/src/mightypork/gamecore/gui/components/layout/linear/LinearLayout.java index 8a3502d..da243c5 100644 --- a/src/mightypork/gamecore/gui/components/layout/linear/LinearLayout.java +++ b/src/mightypork/gamecore/gui/components/layout/linear/LinearLayout.java @@ -16,31 +16,31 @@ import mightypork.utils.math.constraints.vect.proxy.VectAdapter; * Layout that aligns elements while taking into account their actual * dimensions.
* 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) diff --git a/src/mightypork/gamecore/gui/components/layout/linear/LinearRectangle.java b/src/mightypork/gamecore/gui/components/layout/linear/LinearRectangle.java index 78e3f9c..6a87ea7 100644 --- a/src/mightypork/gamecore/gui/components/layout/linear/LinearRectangle.java +++ b/src/mightypork/gamecore/gui/components/layout/linear/LinearRectangle.java @@ -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(); } - + } diff --git a/src/mightypork/gamecore/gui/components/layout/linear/LinearSquare.java b/src/mightypork/gamecore/gui/components/layout/linear/LinearSquare.java index a3c37ee..ff88b08 100644 --- a/src/mightypork/gamecore/gui/components/layout/linear/LinearSquare.java +++ b/src/mightypork/gamecore/gui/components/layout/linear/LinearSquare.java @@ -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; } - + } diff --git a/src/mightypork/gamecore/gui/components/layout/linear/LinearWrapper.java b/src/mightypork/gamecore/gui/components/layout/linear/LinearWrapper.java index 2fe8896..6f5b0f9 100644 --- a/src/mightypork/gamecore/gui/components/layout/linear/LinearWrapper.java +++ b/src/mightypork/gamecore/gui/components/layout/linear/LinearWrapper.java @@ -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); } - + } diff --git a/src/mightypork/gamecore/gui/components/painters/ImagePainter.java b/src/mightypork/gamecore/gui/components/painters/ImagePainter.java index 70ad825..d40cf8e 100644 --- a/src/mightypork/gamecore/gui/components/painters/ImagePainter.java +++ b/src/mightypork/gamecore/gui/components/painters/ImagePainter.java @@ -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; diff --git a/src/mightypork/gamecore/gui/components/painters/QuadPainter.java b/src/mightypork/gamecore/gui/components/painters/QuadPainter.java index 7294668..da13cca 100644 --- a/src/mightypork/gamecore/gui/components/painters/QuadPainter.java +++ b/src/mightypork/gamecore/gui/components/painters/QuadPainter.java @@ -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() { diff --git a/src/mightypork/gamecore/gui/components/painters/TextPainter.java b/src/mightypork/gamecore/gui/components/painters/TextPainter.java index 3c8d18f..a87dabe 100644 --- a/src/mightypork/gamecore/gui/components/painters/TextPainter.java +++ b/src/mightypork/gamecore/gui/components/painters/TextPainter.java @@ -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) { diff --git a/src/mightypork/gamecore/gui/events/LayoutChangeEvent.java b/src/mightypork/gamecore/gui/events/LayoutChangeEvent.java index 99e66ec..2c6d6af 100644 --- a/src/mightypork/gamecore/gui/events/LayoutChangeEvent.java +++ b/src/mightypork/gamecore/gui/events/LayoutChangeEvent.java @@ -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.
+ * 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 { - - public LayoutChangeEvent() - { - } - - + @Override public void handleBy(LayoutChangeListener handler) { diff --git a/src/mightypork/gamecore/gui/events/LayoutChangeListener.java b/src/mightypork/gamecore/gui/events/LayoutChangeListener.java index 4daedee..d2ef4a6 100644 --- a/src/mightypork/gamecore/gui/events/LayoutChangeListener.java +++ b/src/mightypork/gamecore/gui/events/LayoutChangeListener.java @@ -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(); } diff --git a/src/mightypork/gamecore/gui/events/ScreenRequest.java b/src/mightypork/gamecore/gui/events/ScreenRequest.java index eaa7f4c..8d1a073 100644 --- a/src/mightypork/gamecore/gui/events/ScreenRequest.java +++ b/src/mightypork/gamecore/gui/events/ScreenRequest.java @@ -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 { /** + * Create a request to change screen + * * @param screenKey screen name */ public ScreenRequest(String screenKey) diff --git a/src/mightypork/gamecore/gui/events/ScreenRequestListener.java b/src/mightypork/gamecore/gui/events/ScreenRequestListener.java index e4a1d06..94612ca 100644 --- a/src/mightypork/gamecore/gui/events/ScreenRequestListener.java +++ b/src/mightypork/gamecore/gui/events/ScreenRequestListener.java @@ -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 */ diff --git a/src/mightypork/gamecore/gui/events/ViewportChangeEvent.java b/src/mightypork/gamecore/gui/events/ViewportChangeEvent.java index b648cde..dc4c551 100644 --- a/src/mightypork/gamecore/gui/events/ViewportChangeEvent.java +++ b/src/mightypork/gamecore/gui/events/ViewportChangeEvent.java @@ -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 { - + private final Vect screenSize; - - + + /** * @param size new screen size */ @@ -26,8 +26,8 @@ public class ViewportChangeEvent extends BusEvent { { this.screenSize = size; } - - + + /** * @return new screen size */ @@ -35,8 +35,8 @@ public class ViewportChangeEvent extends BusEvent { { return screenSize; } - - + + @Override public void handleBy(ViewportChangeListener handler) { diff --git a/src/mightypork/gamecore/gui/events/ViewportChangeListener.java b/src/mightypork/gamecore/gui/events/ViewportChangeListener.java index 078c177..68af308 100644 --- a/src/mightypork/gamecore/gui/events/ViewportChangeListener.java +++ b/src/mightypork/gamecore/gui/events/ViewportChangeListener.java @@ -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); diff --git a/src/mightypork/gamecore/gui/screens/LayeredScreen.java b/src/mightypork/gamecore/gui/screens/LayeredScreen.java index 5e38ed2..4fa7f0c 100644 --- a/src/mightypork/gamecore/gui/screens/LayeredScreen.java +++ b/src/mightypork/gamecore/gui/screens/LayeredScreen.java @@ -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 layersByZIndex = new ArrayList<>(); private final List 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() { - + @Override public int compare(Overlay o1, Overlay o2) { return o2.getEventPriority() - o1.getEventPriority(); } - + }); - + Collections.sort(layersByZIndex, new Comparator() { - + @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(); } } - + } diff --git a/src/mightypork/gamecore/gui/screens/Overlay.java b/src/mightypork/gamecore/gui/screens/Overlay.java index a6fdc06..a81bd4d 100644 --- a/src/mightypork/gamecore/gui/screens/Overlay.java +++ b/src/mightypork/gamecore/gui/screens/Overlay.java @@ -25,64 +25,66 @@ import mightypork.utils.math.constraints.vect.Vect; /** * Abstract overlay.
* Overlay is connected to event bus and is renderable. - * + * * @author Ondřej Hruška (MightyPork) */ public abstract class Overlay extends BusNode implements Comparable, 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 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 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, Up root.setVisible(visible); } } - - + + @Override public void setEnabled(boolean yes) { @@ -101,35 +103,35 @@ public abstract class Overlay extends BusNode implements Comparable, 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, 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(); } - - + + /** *

* Screen size changed. @@ -180,41 +182,57 @@ public abstract class Overlay extends BusNode implements Comparable, 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() { diff --git a/src/mightypork/gamecore/gui/screens/Screen.java b/src/mightypork/gamecore/gui/screens/Screen.java index f705302..d3f5fb3 100644 --- a/src/mightypork/gamecore/gui/screens/Screen.java +++ b/src/mightypork/gamecore/gui/screens/Screen.java @@ -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() { + // } diff --git a/src/mightypork/gamecore/gui/screens/ScreenLayer.java b/src/mightypork/gamecore/gui/screens/ScreenLayer.java index 09bab66..cf4b3d8 100644 --- a/src/mightypork/gamecore/gui/screens/ScreenLayer.java +++ b/src/mightypork/gamecore/gui/screens/ScreenLayer.java @@ -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 */ diff --git a/src/mightypork/gamecore/gui/screens/ScreenRegistry.java b/src/mightypork/gamecore/gui/screens/ScreenRegistry.java index 80b3ac7..311959b 100644 --- a/src/mightypork/gamecore/gui/screens/ScreenRegistry.java +++ b/src/mightypork/gamecore/gui/screens/ScreenRegistry.java @@ -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 screens = new HashMap<>(); private final Collection 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()); } - + } diff --git a/src/mightypork/gamecore/gui/screens/impl/CrossfadeOverlay.java b/src/mightypork/gamecore/gui/screens/impl/CrossfadeOverlay.java index cf79a11..02126f3 100644 --- a/src/mightypork/gamecore/gui/screens/impl/CrossfadeOverlay.java +++ b/src/mightypork/gamecore/gui/screens/impl/CrossfadeOverlay.java @@ -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); - } } - + } diff --git a/src/mightypork/gamecore/gui/screens/impl/CrossfadeRequest.java b/src/mightypork/gamecore/gui/screens/impl/CrossfadeRequest.java index ec14232..5a985d4 100644 --- a/src/mightypork/gamecore/gui/screens/impl/CrossfadeRequest.java +++ b/src/mightypork/gamecore/gui/screens/impl/CrossfadeRequest.java @@ -10,11 +10,11 @@ import mightypork.utils.eventbus.events.flags.SingleReceiverEvent; */ @SingleReceiverEvent public class CrossfadeRequest extends BusEvent { - + 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 { 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 { this.screen = screen; this.fromDark = false; } - - + + @Override public void handleBy(CrossfadeOverlay handler) { handler.goToScreen(screen, fromDark); } - + } diff --git a/src/mightypork/gamecore/gui/screens/impl/FadingLayer.java b/src/mightypork/gamecore/gui/screens/impl/FadingLayer.java index b0b84d4..aa98f49 100644 --- a/src/mightypork/gamecore/gui/screens/impl/FadingLayer.java +++ b/src/mightypork/gamecore/gui/screens/impl/FadingLayer.java @@ -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) diff --git a/src/mightypork/gamecore/gui/screens/impl/LayerColor.java b/src/mightypork/gamecore/gui/screens/impl/LayerColor.java index b4f2451..acf85e5 100644 --- a/src/mightypork/gamecore/gui/screens/impl/LayerColor.java +++ b/src/mightypork/gamecore/gui/screens/impl/LayerColor.java @@ -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); diff --git a/src/mightypork/gamecore/input/InputModule.java b/src/mightypork/gamecore/input/InputModule.java index ce83ec9..adfc01f 100644 --- a/src/mightypork/gamecore/input/InputModule.java +++ b/src/mightypork/gamecore/input/InputModule.java @@ -11,89 +11,89 @@ import mightypork.utils.math.constraints.vect.Vect; * access to mouse position, key states etc.
* 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 */ diff --git a/src/mightypork/gamecore/input/Key.java b/src/mightypork/gamecore/input/Key.java index b9f7dff..65f3c41 100644 --- a/src/mightypork/gamecore/input/Key.java +++ b/src/mightypork/gamecore/input/Key.java @@ -11,59 +11,59 @@ import mightypork.gamecore.core.App; * Abstraction above a physical keyboard key.
* Provides name, aliases, and the {@link InputModule} may assign it a numeric * code that corresponds to the underlying keyboard system. - * + * * @author Ondřej Hruška (MightyPork) */ public class Key { - + private int code = -1; private final String name; private final Set aliases = new HashSet<>(1); - - + + /** * Create a key. Note that both name and aliases are converted to uppercase, * and all underscores are ignored when the aliases are matched. - * + * * @param name key name (primary alias) * @param aliases extra aliases (used for matching) */ public Key(String name, String... aliases) { - + // assign name and aliases, converting both to uppercase - + this.name = name; this.aliases.add(prepareForMatch(name)); - + for (final String al : aliases) { this.aliases.add(prepareForMatch(al)); } } - - + + public boolean isDown() { return App.input().isKeyDown(this); } - - + + /** * Set a key code. This can be used by the {@link InputModule} to store a * numeric code in the key. - * + * * @param code a code to assign */ public void setCode(int code) { this.code = code; } - - + + /** * Check if the provided alias matches this key.
* Both the primary alias and the extra aliases are considered. - * + * * @param alias * @return true if matches (this is the key) */ @@ -72,40 +72,40 @@ public class Key { if (alias == null) return false; return aliases.contains(prepareForMatch(alias)); } - - + + private String prepareForMatch(String matched) { return matched.toUpperCase().replace("_", ""); } - - + + /** * Get key name (primary alias). - * + * * @return name (uppercase) */ public String getName() { return name; } - - + + /** * Get the numeric code assigned to this key. If none is assigned, the value * is -1. - * + * * @return numeric key code. */ public int getCode() { return code; } - - + + /** * Get if this key is not a NONE or undefined key. - * + * * @return true if the key is defined. */ public boolean isDefined() diff --git a/src/mightypork/gamecore/input/KeyBinder.java b/src/mightypork/gamecore/input/KeyBinder.java index 9730e0e..c8e8ae0 100644 --- a/src/mightypork/gamecore/input/KeyBinder.java +++ b/src/mightypork/gamecore/input/KeyBinder.java @@ -6,26 +6,26 @@ import mightypork.gamecore.gui.Action; /** * Can bind events to keys. - * + * * @author Ondřej Hruška (MightyPork) */ public interface KeyBinder { - + /** * Bind handler to a keystroke, replace current handler if any - * + * * @param edge trigger edge * @param stroke trigger keystroke * @param task handler; can be {@link Runnable} or {@link Action} */ void bindKey(KeyStroke stroke, Trigger edge, Runnable task); - - + + /** * Remove handler from a keystroke (id any) - * + * * @param stroke stroke */ void unbindKey(KeyStroke stroke); - + } diff --git a/src/mightypork/gamecore/input/KeyBinding.java b/src/mightypork/gamecore/input/KeyBinding.java index 2ae432f..7a94a09 100644 --- a/src/mightypork/gamecore/input/KeyBinding.java +++ b/src/mightypork/gamecore/input/KeyBinding.java @@ -7,17 +7,17 @@ import mightypork.gamecore.input.events.KeyEventHandler; /** * Key binding, trigger activated by a keystroke event - * + * * @author Ondřej Hruška (MightyPork) */ public class KeyBinding implements KeyEventHandler { - + private final KeyStroke keystroke; private Runnable handler; private final Trigger edge; private boolean wasDown = false; - - + + /** * @param edge trigger edge * @param stroke trigger keystroke @@ -30,11 +30,11 @@ public class KeyBinding implements KeyEventHandler { this.edge = edge; wasDown = stroke.isDown(); } - - + + /** * Check for equality of keystroke - * + * * @param stroke other keystroke * @return true if keystrokes are equal (cannot co-exist) */ @@ -42,8 +42,8 @@ public class KeyBinding implements KeyEventHandler { { return this.keystroke.equals(stroke); } - - + + /** * @param handler event handler */ @@ -51,18 +51,18 @@ public class KeyBinding implements KeyEventHandler { { this.handler = handler; } - - + + @Override public void receive(KeyEvent event) { final boolean nowDown = keystroke.isDown(); - + boolean trigger = false; trigger |= (edge == Trigger.FALLING && (!wasDown && nowDown)); trigger |= (edge == Trigger.RISING && (wasDown && !nowDown)); wasDown = nowDown; - + // run handler when event was met if (trigger) { handler.run(); diff --git a/src/mightypork/gamecore/input/KeyBindingPool.java b/src/mightypork/gamecore/input/KeyBindingPool.java index 2abcc23..53701bb 100644 --- a/src/mightypork/gamecore/input/KeyBindingPool.java +++ b/src/mightypork/gamecore/input/KeyBindingPool.java @@ -12,17 +12,17 @@ import mightypork.utils.logging.Log; /** * Key binding pool - * + * * @author Ondřej Hruška (MightyPork) */ public class KeyBindingPool implements KeyBinder, KeyEventHandler { - + private final Set bindings = new HashSet<>(); - - + + /** * Bind handler to a keystroke, replace current handler if any - * + * * @param stroke trigger keystroke * @param task handler */ @@ -36,21 +36,21 @@ public class KeyBindingPool implements KeyBinder, KeyEventHandler { return; } } - + bindings.add(new KeyBinding(stroke, edge, task)); } - - + + /** * Remove handler from keystroke (id any) - * + * * @param stroke stroke */ @Override public void unbindKey(KeyStroke stroke) { final Iterator iter = bindings.iterator(); - + while (iter.hasNext()) { final KeyBinding kb = iter.next(); if (kb.matches(stroke)) { @@ -59,8 +59,8 @@ public class KeyBindingPool implements KeyBinder, KeyEventHandler { } } } - - + + @Override public void receive(KeyEvent event) { diff --git a/src/mightypork/gamecore/input/KeyStroke.java b/src/mightypork/gamecore/input/KeyStroke.java index 26357e9..8806e78 100644 --- a/src/mightypork/gamecore/input/KeyStroke.java +++ b/src/mightypork/gamecore/input/KeyStroke.java @@ -6,18 +6,18 @@ import mightypork.utils.string.StringUtil; /** * Key stroke - * + * * @author Ondřej Hruška (MightyPork) */ public class KeyStroke { - + private byte mod; private Key key; - - + + /** * Create a Key Stroke - * + * * @param key key code * @param modmask modifiers */ @@ -25,13 +25,13 @@ public class KeyStroke { { setTo(key, modmask); } - - + + /** * Change to...
* (KeyStroke is mutable, so that upon changing it in Config, all existing * key bindings are updated automatically.) - * + * * @param key key code * @param modmask modifiers */ @@ -40,80 +40,80 @@ public class KeyStroke { this.key = key; this.mod = (byte) (modmask | Keys.keyToMod(key)); // for mods alone } - - + + /** * Create a new keystroke without modifiers - * + * * @param key key */ public KeyStroke(Key key) { this(key, Keys.MOD_NONE); } - - + + /** * Get if the key is down and modifiers match - * + * * @return true if the key is currently down & modifiers match */ public boolean isDown() { return key.isDown() && (Keys.getActiveMod() == mod); } - - + + public String saveToString() { return Keys.modToString(mod) + "+" + key.getName(); } - - + + public static KeyStroke createFromString(String dataString) { final KeyStroke ks = new KeyStroke(Keys.NONE, Keys.MOD_NONE); ks.loadFromString(dataString); return ks; } - - + + public void loadFromString(String dataString) { final String dataString1 = dataString.toUpperCase().replace('-', '+').replaceAll("[^A-Z0-9_+]", ""); - + if (dataString1.contains("+")) { - + final String keyStr = StringUtil.fromLastChar(dataString1, '+'); final String modStr = StringUtil.toLastChar(dataString1, '+'); - + setTo(Keys.stringToKey(keyStr), Keys.stringToMod(modStr)); - + } else { setTo(Keys.stringToKey(dataString1), Keys.MOD_NONE); } } - - + + public Key getKey() { return key; } - - + + public byte getMod() { return mod; } - - + + @Override public String toString() { return saveToString(); } - - + + @Override public int hashCode() { @@ -123,8 +123,8 @@ public class KeyStroke { result = prime * result + mod; return result; } - - + + @Override public boolean equals(Object obj) { diff --git a/src/mightypork/gamecore/input/Keys.java b/src/mightypork/gamecore/input/Keys.java index f972c5f..43cb16d 100644 --- a/src/mightypork/gamecore/input/Keys.java +++ b/src/mightypork/gamecore/input/Keys.java @@ -14,14 +14,14 @@ import mightypork.utils.logging.Log; /** * Key constants & translation table. - * + * * @author Ondřej Hruška (MightyPork) */ public class Keys { - + //@formatter:off public static final Key NONE = new Key("NONE", "NULL"); - + public static final Key NUM_0 = new Key("0", "ZERO"); public static final Key NUM_1 = new Key("1", "ONE"); public static final Key NUM_2 = new Key("2", "TWO"); @@ -32,7 +32,7 @@ public class Keys { public static final Key NUM_7 = new Key("7", "SEVEN"); public static final Key NUM_8 = new Key("8", "EIGHT"); public static final Key NUM_9 = new Key("9", "NINE"); - + public static final Key Q = new Key("Q"); public static final Key W = new Key("W"); public static final Key E = new Key("E"); @@ -59,7 +59,7 @@ public class Keys { public static final Key B = new Key("B"); public static final Key N = new Key("N"); public static final Key M = new Key("M"); - + public static final Key MINUS = new Key("MINUS", "DASH"); public static final Key EQUALS = new Key("EQUALS"); public static final Key SLASH = new Key("SLASH"); @@ -71,18 +71,18 @@ public class Keys { public static final Key GRAVE = new Key("GRAVE", "ACCENT"); public static final Key COMMA = new Key("COMMA"); public static final Key PERIOD = new Key("PERIOD", "DOT", "POINT"); - + public static final Key SPACE = new Key("SPACE", "SPACEBAR"); public static final Key BACKSPACE = new Key("BACKSPACE", "BACK"); public static final Key TAB = new Key("TAB", "TABULATOR", "INDENT"); public static final Key ESCAPE = new Key("ESC", "ESCAPE"); - + // those probably can't be used public static final Key APPS = new Key("APPS"); public static final Key POWER = new Key("POWER"); public static final Key SLEEP = new Key("SLEEP"); public static final Key MENU = new Key("MENU"); - + public static final Key F1 = new Key("F1"); public static final Key F2 = new Key("F2"); public static final Key F3 = new Key("F3"); @@ -98,12 +98,12 @@ public class Keys { public static final Key F13 = new Key("F13"); public static final Key F14 = new Key("F14"); public static final Key F15 = new Key("F15"); - + // probably not possible to bind to those. public static final Key CAPS_LOCK = new Key("CAPSLOCK", "CAPS", "CAPITAL"); - public static final Key SCROLL_LOCK = new Key("SCROLL", "SCROLL_LOCK"); + public static final Key SCROLL_LOCK = new Key("SCROLL", "SCROLL_LOCK"); public static final Key NUM_LOCK = new Key("NUMLOCK"); - + public static final Key NUMPAD_MINUS = new Key("SUBTRACT", "NUMPAD_MINUS", "NUMPAD_SUBTRACT"); public static final Key NUMPAD_PLUSS = new Key("ADD", "NUMPAD_PLUS", "NUMPAD_ADD"); public static final Key NUMPAD_0 = new Key("NUMPAD_0"); @@ -120,7 +120,7 @@ public class Keys { public static final Key NUMPAD_ENTER = new Key("NUMPAD_ENTER", "NUMPADRETURN", "NUMPAD_RETURN"); public static final Key NUMPAD_DIVIDE = new Key("DIVIDE", "NUMPAD_DIVIDE", "NUMPAD_SLASH"); public static final Key NUMPAD_MULTIPLY = new Key("MULTIPLY", "NUMPAD_MULTIPLY", "NUMPAD_ASTERISK"); - + public static final Key CONTROL_LEFT = new Key("LCONTROL", "LEFT_CONTROL", "LCTRL", "LEFT_CTRL"); public static final Key CONTROL_RIGHT = new Key("RCONTROL", "RIGHT_CONTROL", "RCTRL", "RIGHT_CTRL"); public static final Key ALT_LEFT = new Key("LALT", "LMENU", "LEFT_MENU"); @@ -129,24 +129,24 @@ public class Keys { public static final Key SHIFT_RIGHT = new Key("RSHIFT", "RIGHT_SHIFT"); public static final Key META_LEFT = new Key("LMETA", "LEFT_META", "LWIN", "LEFT_WIN"); public static final Key META_RIGHT = new Key("RMETA", "RIGHT_META", "RWIN", "RIGHT_WIN"); - + public static final Key UP = new Key("UP", "ARROW_UP"); public static final Key DOWN = new Key("DOWN", "ARROW_DOWN"); public static final Key LEFT = new Key("LEFT", "ARROW_LEFT"); public static final Key RIGHT = new Key("RIGHT", "ARROW_RIGHT"); - + public static final Key HOME = new Key("HOME"); public static final Key END = new Key("END"); - + public static final Key PAGE_UP = new Key("PAGE_UP", "PGUP", "PRIOR"); public static final Key PAGE_DOWN = new Key("PAGE_DOWN", "PGDN", "NEXT"); - + public static final Key RETURN = new Key("ENTER", "RETURN", "CR"); public static final Key PAUSE = new Key("PAUSE", "BREAK"); public static final Key INSERT = new Key("INSERT"); public static final Key DELETE = new Key("DELETE"); public static final Key SYSRQ = new Key("SYSRQ"); // wtf is this anyway? - + // here go modifier bits public static final byte MOD_NONE = 0; public static final byte MOD_ALT = 1; @@ -154,54 +154,54 @@ public class Keys { public static final byte MOD_SHIFT = 4; public static final byte MOD_META = 8; //@formatter:on - + private static Map lookupByCode = new HashMap<>(100); private static List keyList = new ArrayList<>(100); - + static { // define none key NONE.setCode(0); - + // Use reflection to find keys final Field[] fields = Keys.class.getFields(); try { for (final Field field : fields) { final int modifiers = field.getModifiers(); if (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers) && Modifier.isFinal(modifiers) && field.getType().equals(Key.class)) { - + keyList.add((Key) field.get(null)); } } } catch (final Exception e) {} } - - + + /** * Build lookup table by key codes */ private static void buildCodeLookupTable() { lookupByCode.clear(); - + lookupByCode.put(NONE.getCode(), NONE); - + for (final Key k : keyList) { if (!k.isDefined()) continue; if (!lookupByCode.containsKey(k.getCode())) { lookupByCode.put(k.getCode(), k); } } - + if (lookupByCode.size() == 1) { // NONE alone Log.w("Key codes are not ininitialized."); } } - - + + /** * Convert a key name to a key code. - * + * * @param keyStr key name * @return the key, or NONE if none matches */ @@ -210,128 +210,128 @@ public class Keys { for (final Key k : keyList) { if (k.matches(keyStr)) return k; } - + Log.w("No such key: " + keyStr); - + return NONE; } - - + + /** * Convert a mod description to a mod mask. A mod description is a string * containing CTRL,ALT,SHIFT,META, as in CTRL+ALT.
* If none of the mod identifiers are found in the description, a MOD_NONE * is returned.
* This method is used for parsing keystroke, together with nameToKey(). - * + * * @param modStr mod description (eg. CTRL+ALT) * @return mod mask */ public static int stringToMod(String modStr) { int mod_mask = MOD_NONE; - + modStr = modStr.toUpperCase(); - + if (modStr.contains("CTRL")) { mod_mask |= MOD_CONTROL; } - + if (modStr.contains("ALT")) { mod_mask |= MOD_ALT; } - + if (modStr.contains("SHIFT")) { mod_mask |= MOD_SHIFT; } - + if (modStr.contains("META") || modStr.contains("WIN")) { mod_mask |= MOD_META; } - + return mod_mask; } - - + + /** * Convert a mod mask to a mod description, in a format recognized by * stringToMod() - joining mods by +. - * + * * @param modMask mod mask * @return mods as string (CTRL+ALT) */ public static String modToString(int modMask) { String s = ""; - + if ((modMask & MOD_CONTROL) != 0) { s += "CTRL"; } - + if ((modMask & MOD_ALT) != 0) { if (!s.isEmpty()) s += "+"; s += "ALT"; } - + if ((modMask & MOD_SHIFT) != 0) { if (!s.isEmpty()) s += "+"; s += "SHIFT"; } - + if ((modMask & MOD_META) != 0) { if (!s.isEmpty()) s += "+"; s += "META"; } - + return s; } - - + + /** * Get a {@link Key} for key code. - * + * * @param keyCode code * @return key instance, or NONE if no key matches. */ public static Key codeToKey(int keyCode) { if (lookupByCode.isEmpty()) buildCodeLookupTable(); - + Key k = lookupByCode.get(keyCode); - + if (k == null) { Log.w("No key for code: " + keyCode); k = NONE; } - + return k; } - - + + /** * Convert a key to mod mask, in case the key is one of the mod keys. - * + * * @param key the key * @return mod mask corresponding to the key */ public static int keyToMod(Key key) { - + if (key == SHIFT_LEFT || key == SHIFT_RIGHT) return MOD_SHIFT; - + if (key == CONTROL_LEFT || key == CONTROL_RIGHT) return MOD_CONTROL; if (key == ALT_LEFT || key == ALT_RIGHT) return MOD_ALT; if (key == META_LEFT || key == META_RIGHT) return MOD_META; - + return MOD_NONE; } - - + + /** * Get if the given key is down (call it's "isDown()" method).
* This method is here just for completeness, since the getActiveMod() is * also here. - * + * * @param key the key to check * @return true if the key is down */ @@ -339,36 +339,36 @@ public class Keys { { return key.isDown(); } - - + + /** * Get currently active key modifiers - * + * * @return active mod mask (mod bits ored) */ public static int getActiveMod() { int mods = 0; - + final InputModule inp = App.input(); - + if (inp.isKeyDown(Keys.ALT_LEFT) || inp.isKeyDown(Keys.ALT_RIGHT)) { mods |= Keys.MOD_ALT; } - + if (inp.isKeyDown(Keys.SHIFT_LEFT) || inp.isKeyDown(Keys.SHIFT_RIGHT)) { mods |= Keys.MOD_SHIFT; } - + if (inp.isKeyDown(Keys.CONTROL_LEFT) || inp.isKeyDown(Keys.CONTROL_RIGHT)) { mods |= Keys.MOD_CONTROL; } - + if (inp.isKeyDown(Keys.META_LEFT) || inp.isKeyDown(Keys.META_RIGHT)) { mods |= Keys.MOD_META; } - + return mods; } - + } diff --git a/src/mightypork/gamecore/input/events/KeyEvent.java b/src/mightypork/gamecore/input/events/KeyEvent.java index 0010477..8a35e57 100644 --- a/src/mightypork/gamecore/input/events/KeyEvent.java +++ b/src/mightypork/gamecore/input/events/KeyEvent.java @@ -8,17 +8,17 @@ import mightypork.utils.eventbus.events.flags.NotLoggedEvent; /** * A keyboard event FIXME Should use Key class, not keycode. - * + * * @author Ondřej Hruška (MightyPork) */ @NotLoggedEvent public class KeyEvent extends BusEvent { - + private final int key; private final boolean down; private final char c; - - + + /** * @param key key that triggered the event. Can be KEY_NONE. * @param c typed char (can be zero char) @@ -30,8 +30,8 @@ public class KeyEvent extends BusEvent { this.c = c; this.down = down; } - - + + /** * @return key code */ @@ -39,8 +39,8 @@ public class KeyEvent extends BusEvent { { return key; } - - + + /** * @return true if key was just pressed */ @@ -48,8 +48,8 @@ public class KeyEvent extends BusEvent { { return down; } - - + + /** * @return true if key was just released */ @@ -57,8 +57,8 @@ public class KeyEvent extends BusEvent { { return !down; } - - + + /** * @return event character (if any) */ @@ -66,20 +66,20 @@ public class KeyEvent extends BusEvent { { return c; } - - + + @Override public void handleBy(KeyEventHandler keh) { keh.receive(this); } - - + + @Override public String toString() { // FIXME return Keys.codeToKey(key).getName() + ":" + (down ? "DOWN" : "UP"); } - + } diff --git a/src/mightypork/gamecore/input/events/KeyEventHandler.java b/src/mightypork/gamecore/input/events/KeyEventHandler.java index 5d781b2..67f4c61 100644 --- a/src/mightypork/gamecore/input/events/KeyEventHandler.java +++ b/src/mightypork/gamecore/input/events/KeyEventHandler.java @@ -3,14 +3,14 @@ package mightypork.gamecore.input.events; /** * {@link KeyEvent} listener - * + * * @author Ondřej Hruška (MightyPork) */ public interface KeyEventHandler { - + /** * Handle an event - * + * * @param event event */ void receive(KeyEvent event); diff --git a/src/mightypork/gamecore/input/events/MouseButtonEvent.java b/src/mightypork/gamecore/input/events/MouseButtonEvent.java index e116804..cda4fa2 100644 --- a/src/mightypork/gamecore/input/events/MouseButtonEvent.java +++ b/src/mightypork/gamecore/input/events/MouseButtonEvent.java @@ -10,25 +10,25 @@ import mightypork.utils.math.constraints.vect.VectConst; /** * Mouse button / wheel event triggered - * + * * @author Ondřej Hruška (MightyPork) */ @NotLoggedEvent public class MouseButtonEvent extends BusEvent { - + public static final int BUTTON_LEFT = 0; public static final int BUTTON_MIDDLE = 1; public static final int BUTTON_RIGHT = 2; - + private final int button; private final int wheeld; private final VectConst pos; private final boolean down; - - + + /** * Mouse button event - * + * * @param pos event position * @param button button id * @param down button pressed @@ -41,8 +41,8 @@ public class MouseButtonEvent extends BusEvent { this.pos = pos.freeze(); this.wheeld = wheeld; } - - + + /** * @return true if the event was caused by a button state change */ @@ -50,8 +50,8 @@ public class MouseButtonEvent extends BusEvent { { return button != -1; } - - + + /** * @return true if the event was caused by a wheel change */ @@ -59,8 +59,8 @@ public class MouseButtonEvent extends BusEvent { { return wheeld != 0; } - - + + /** * @return button id or -1 if none was pressed */ @@ -68,8 +68,8 @@ public class MouseButtonEvent extends BusEvent { { return button; } - - + + /** * @return number of steps the wheel changed since last event */ @@ -77,8 +77,8 @@ public class MouseButtonEvent extends BusEvent { { return wheeld; } - - + + /** * @return mouse position when the event occurred */ @@ -86,8 +86,8 @@ public class MouseButtonEvent extends BusEvent { { return pos; } - - + + /** * @return true if button was just pressed */ @@ -95,8 +95,8 @@ public class MouseButtonEvent extends BusEvent { { return button != -1 && down; } - - + + /** * @return true if button was just released */ @@ -104,11 +104,11 @@ public class MouseButtonEvent extends BusEvent { { return button != -1 && !down; } - - + + /** * Get if event happened over a rect - * + * * @param rect rect region * @return was over */ @@ -116,8 +116,8 @@ public class MouseButtonEvent extends BusEvent { { return rect.getRect().contains(pos); } - - + + @Override public void handleBy(MouseButtonHandler handler) { diff --git a/src/mightypork/gamecore/input/events/MouseButtonHandler.java b/src/mightypork/gamecore/input/events/MouseButtonHandler.java index 6d59f7a..4dc0297 100644 --- a/src/mightypork/gamecore/input/events/MouseButtonHandler.java +++ b/src/mightypork/gamecore/input/events/MouseButtonHandler.java @@ -3,14 +3,14 @@ package mightypork.gamecore.input.events; /** * {@link MouseButtonEvent} listener - * + * * @author Ondřej Hruška (MightyPork) */ public interface MouseButtonHandler { - + /** * Handle an event - * + * * @param event event */ void receive(MouseButtonEvent event); diff --git a/src/mightypork/gamecore/input/events/MouseMotionEvent.java b/src/mightypork/gamecore/input/events/MouseMotionEvent.java index 06fda84..648b061 100644 --- a/src/mightypork/gamecore/input/events/MouseMotionEvent.java +++ b/src/mightypork/gamecore/input/events/MouseMotionEvent.java @@ -9,16 +9,16 @@ import mightypork.utils.math.constraints.vect.VectConst; /** * Mouse moved - * + * * @author Ondřej Hruška (MightyPork) */ @NotLoggedEvent public class MouseMotionEvent extends BusEvent { - + private final VectConst move; private final VectConst pos; - - + + /** * @param pos end pos * @param move move vector @@ -28,8 +28,8 @@ public class MouseMotionEvent extends BusEvent { this.move = move.freeze(); this.pos = pos.freeze(); } - - + + /** * @return movement since last {@link MouseMotionEvent} */ @@ -37,8 +37,8 @@ public class MouseMotionEvent extends BusEvent { { return move; } - - + + /** * @return current mouse position */ @@ -46,12 +46,12 @@ public class MouseMotionEvent extends BusEvent { { return pos; } - - + + @Override public void handleBy(MouseMotionHandler keh) { keh.receive(this); } - + } diff --git a/src/mightypork/gamecore/input/events/MouseMotionHandler.java b/src/mightypork/gamecore/input/events/MouseMotionHandler.java index cbdabe7..38ee5c0 100644 --- a/src/mightypork/gamecore/input/events/MouseMotionHandler.java +++ b/src/mightypork/gamecore/input/events/MouseMotionHandler.java @@ -3,14 +3,14 @@ package mightypork.gamecore.input.events; /** * {@link MouseMotionEvent} listener - * + * * @author Ondřej Hruška (MightyPork) */ public interface MouseMotionHandler { - + /** * Handle an event - * + * * @param event event */ void receive(MouseMotionEvent event); diff --git a/src/mightypork/gamecore/resources/BaseDeferredResource.java b/src/mightypork/gamecore/resources/BaseDeferredResource.java index 716510c..e736345 100644 --- a/src/mightypork/gamecore/resources/BaseDeferredResource.java +++ b/src/mightypork/gamecore/resources/BaseDeferredResource.java @@ -12,17 +12,17 @@ import mightypork.utils.string.StringUtil; /** * Deferred resource abstraction. - * + * * @author Ondřej Hruška (MightyPork) */ @Alias(name = "Resource") public abstract class BaseDeferredResource implements DeferredResource, Destroyable { - + private final String resource; private volatile boolean loadFailed = false; private volatile boolean loadAttempted = false; - - + + /** * @param resource resource path / name; this string is later used in * loadResource() @@ -31,48 +31,48 @@ public abstract class BaseDeferredResource implements DeferredResource, Destroya { this.resource = resource; } - - + + @Override public synchronized final void load() { if (!loadFailed && loadAttempted) return; - -// + +// // if (loadFailed) return; // if (loadAttempted) return; -// - +// + loadAttempted = true; loadFailed = false; - + try { if (resource == null) { throw new NullPointerException("Resource string cannot be null for non-null resource."); } - + final long time = Profiler.begin(); Log.f3("(res) + Load: " + this); loadResource(resource); Log.f3("(res) - Done: " + this + " in " + Profiler.endStr(time)); - + } catch (final Throwable t) { loadFailed = true; Log.e("(res) Failed to load: " + this, t); } } - - + + @Override public synchronized final boolean isLoaded() { return loadAttempted && !loadFailed; } - - + + /** * Check if the resource is loaded; if not, try to do so. - * + * * @return true if it's loaded now. */ public synchronized final boolean ensureLoaded() @@ -81,36 +81,36 @@ public abstract class BaseDeferredResource implements DeferredResource, Destroya return true; } else { if (loadFailed) return false; - + Log.f3("(res) !! Loading on access: " + this); load(); } - + return isLoaded(); } - - + + /** * Load the resource. Called from load() - once only. - * + * * @param resource the path / name of a resource * @throws IOException when some problem prevented the resource from being * loaded. */ protected abstract void loadResource(String resource) throws IOException; - - + + @Override public abstract void destroy(); - - + + @Override public String toString() { return StringUtil.fromLastChar(resource, '/'); } - - + + @Override public int hashCode() { @@ -119,8 +119,8 @@ public abstract class BaseDeferredResource implements DeferredResource, Destroya result = prime * result + ((resource == null) ? 0 : resource.hashCode()); return result; } - - + + @Override public boolean equals(Object obj) { diff --git a/src/mightypork/gamecore/resources/DeferredResource.java b/src/mightypork/gamecore/resources/DeferredResource.java index 4636bee..67af186 100644 --- a/src/mightypork/gamecore/resources/DeferredResource.java +++ b/src/mightypork/gamecore/resources/DeferredResource.java @@ -3,20 +3,20 @@ package mightypork.gamecore.resources; /** * Deferred resource - * + * * @author Ondřej Hruška (MightyPork) */ public interface DeferredResource { - + /** * Load the actual resource, if not loaded yet. */ void load(); - - + + /** * Check if resource was successfully loaded. - * + * * @return true if already loaded */ boolean isLoaded(); diff --git a/src/mightypork/gamecore/resources/Res.java b/src/mightypork/gamecore/resources/Res.java index 523be6a..6d168d3 100644 --- a/src/mightypork/gamecore/resources/Res.java +++ b/src/mightypork/gamecore/resources/Res.java @@ -14,43 +14,43 @@ import mightypork.gamecore.graphics.textures.TxSheet; /** * Static resource repository - * + * * @author Ondřej Hruška (MightyPork) */ public final class Res { - + private static TextureRegistry textures; private static SoundRegistry sounds; private static FontRegistry fonts; - + private static boolean initialized = false; - - + + /** * Load on behalf of given base app - * + * * @param app app access */ public static void init() { if (initialized) return; initialized = true; - + textures = new TextureRegistry(); sounds = new SoundRegistry(); fonts = new FontRegistry(); } - - + + public static ITexture getTexture(String key) { return textures.getTexture(key); } - - + + /** * Get a texture sheet by key - * + * * @param key * @return sheet */ @@ -58,11 +58,11 @@ public final class Res { { return textures.getSheet(key); } - - + + /** * Get a texture quad by key - * + * * @param key * @return quad */ @@ -70,31 +70,31 @@ public final class Res { { return textures.getQuad(key); } - - + + public static LoopPlayer getSoundLoop(String key) { return sounds.getLoop(key); } - - + + public static EffectPlayer getSoundEffect(String key) { return sounds.getEffect(key); } - - + + public static IFont getFont(String key) { return fonts.getFont(key); } - - + + public static void load(ResourceSetup binder) { binder.addFonts(fonts); binder.addTextures(textures); binder.addSounds(sounds); } - + } diff --git a/src/mightypork/gamecore/resources/ResourceSetup.java b/src/mightypork/gamecore/resources/ResourceSetup.java index 5e7682f..4aa8ab8 100644 --- a/src/mightypork/gamecore/resources/ResourceSetup.java +++ b/src/mightypork/gamecore/resources/ResourceSetup.java @@ -8,30 +8,30 @@ import mightypork.gamecore.graphics.textures.TextureRegistry; /** * Resource binder; used by apps to specify what resources are to be loaded. - * + * * @author Ondřej Hruška (MightyPork) */ public interface ResourceSetup { - + /** * Add fonts to load. - * + * * @param fonts font registry */ void addFonts(FontRegistry fonts); - - + + /** * Add sounds to load. - * + * * @param sounds sound registry */ void addSounds(SoundRegistry sounds); - - + + /** * Add textures to load - * + * * @param textures texture registry */ void addTextures(TextureRegistry textures); diff --git a/src/mightypork/gamecore/resources/loading/AsyncResourceLoader.java b/src/mightypork/gamecore/resources/loading/AsyncResourceLoader.java index 8dd66e3..1bee35f 100644 --- a/src/mightypork/gamecore/resources/loading/AsyncResourceLoader.java +++ b/src/mightypork/gamecore/resources/loading/AsyncResourceLoader.java @@ -16,18 +16,18 @@ import mightypork.utils.logging.Log; /** * Asynchronous resource loading thread. - * + * * @author Ondřej Hruška (MightyPork) */ public class AsyncResourceLoader extends Thread implements ResourceLoader, Destroyable { - + private final ExecutorService exs = Executors.newFixedThreadPool(2); - + private final LinkedBlockingQueue toLoad = new LinkedBlockingQueue<>(); private volatile boolean stopped; private volatile boolean mainLoopQueuing = true; - - + + @Override public synchronized void init() { @@ -35,35 +35,35 @@ public class AsyncResourceLoader extends Thread implements ResourceLoader, Destr setDaemon(true); super.start(); } - - + + public void enableMainLoopQueuing(boolean yes) { mainLoopQueuing = yes; } - - + + public AsyncResourceLoader() { super("Deferred loader"); } - - + + @Override public void loadResource(final DeferredResource resource) { if (resource.isLoaded()) return; - + // textures & fonts needs to be loaded in main thread if (Reflect.hasAnnotation(resource, MustLoadInRenderingContext.class)) { - + if (!mainLoopQueuing) { // just let it be } else { Log.f3("(loader) Delegating to main thread: " + Support.str(resource)); - + App.bus().send(new MainLoopRequest(new Runnable() { - + @Override public void run() { @@ -71,31 +71,31 @@ public class AsyncResourceLoader extends Thread implements ResourceLoader, Destr } }, false)); } - + return; } - + toLoad.add(resource); } - - + + @Override public void run() { Log.f3("Asynchronous resource loader started."); - + while (!stopped) { - + try { final DeferredResource def = toLoad.take(); if (def == null) continue; - + if (!def.isLoaded()) { - + Log.f3("(loader) Scheduling... " + Support.str(def)); - + exs.submit(new Runnable() { - + @Override public void run() { @@ -105,15 +105,15 @@ public class AsyncResourceLoader extends Thread implements ResourceLoader, Destr } }); } - + } catch (final InterruptedException ignored) { // } - + } } - - + + // apparently, destroy method exists on thread :/ @SuppressWarnings("deprecation") @Override @@ -123,5 +123,5 @@ public class AsyncResourceLoader extends Thread implements ResourceLoader, Destr stopped = true; exs.shutdownNow(); } - + } diff --git a/src/mightypork/gamecore/resources/loading/MustLoadInRenderingContext.java b/src/mightypork/gamecore/resources/loading/MustLoadInRenderingContext.java index 057f12b..436a445 100644 --- a/src/mightypork/gamecore/resources/loading/MustLoadInRenderingContext.java +++ b/src/mightypork/gamecore/resources/loading/MustLoadInRenderingContext.java @@ -12,7 +12,7 @@ import java.lang.annotation.Target; /** * Resource that is texture-based and therefore needs to be loaded in the main * thread (ie. main loop). - * + * * @author Ondřej Hruška (MightyPork) */ diff --git a/src/mightypork/gamecore/resources/loading/ResourceLoadRequest.java b/src/mightypork/gamecore/resources/loading/ResourceLoadRequest.java index 4dfe638..2e6ccee 100644 --- a/src/mightypork/gamecore/resources/loading/ResourceLoadRequest.java +++ b/src/mightypork/gamecore/resources/loading/ResourceLoadRequest.java @@ -8,15 +8,15 @@ import mightypork.utils.eventbus.events.flags.SingleReceiverEvent; /** * Request to load a deferred resource. - * + * * @author Ondřej Hruška (MightyPork) */ @SingleReceiverEvent public class ResourceLoadRequest extends BusEvent { - + private final DeferredResource resource; - - + + /** * @param resource resource to load */ @@ -24,8 +24,8 @@ public class ResourceLoadRequest extends BusEvent { { this.resource = resource; } - - + + @Override public void handleBy(ResourceLoader handler) { diff --git a/src/mightypork/gamecore/resources/loading/ResourceLoader.java b/src/mightypork/gamecore/resources/loading/ResourceLoader.java index b06a669..192c434 100644 --- a/src/mightypork/gamecore/resources/loading/ResourceLoader.java +++ b/src/mightypork/gamecore/resources/loading/ResourceLoader.java @@ -6,22 +6,22 @@ import mightypork.gamecore.resources.DeferredResource; /** * {@link ResourceLoadRequest} listener - * + * * @author Ondřej Hruška (MightyPork) */ public interface ResourceLoader { - + /** * Load a resource - * + * * @param resource */ void loadResource(DeferredResource resource); - - + + /** * Initialize the loader (Join the bus, start a stread etc) - * + * * @param app app the loader works for. The event bus must already be * initialized. */