diff --git a/src/mightypork/rogue/App.java b/src/mightypork/rogue/App.java index acd6917..54026c8 100644 --- a/src/mightypork/rogue/App.java +++ b/src/mightypork/rogue/App.java @@ -13,11 +13,12 @@ import mightypork.rogue.bus.events.ActionRequest.RequestType; import mightypork.rogue.gui.ScreenRegistry; import mightypork.rogue.gui.screens.test_bouncyboxes.ScreenTestBouncy; import mightypork.rogue.gui.screens.test_cat_sound.ScreenTestCat; +import mightypork.rogue.gui.screens.test_font.ScreenTestFont; import mightypork.rogue.input.InputSystem; import mightypork.rogue.input.KeyStroke; +import mightypork.rogue.loading.DeferredLoader; import mightypork.rogue.render.DisplaySystem; import mightypork.rogue.sound.SoundSystem; -import mightypork.rogue.texture.DeferredLoader; import mightypork.utils.control.bus.EventBus; import mightypork.utils.control.bus.events.DestroyEvent; import mightypork.utils.control.bus.events.UpdateEvent; @@ -199,8 +200,9 @@ public class App implements AppAccess { screens.add(new ScreenTestBouncy(this)); screens.add(new ScreenTestCat(this)); + screens.add(new ScreenTestFont(this)); - screens.showScreen("test.cat"); + screens.showScreen("test.font"); } @@ -284,11 +286,13 @@ public class App implements AppAccess { } - private boolean lockInstance() + private static boolean lockInstance() { final File lockFile = new File(Paths.WORKDIR, ".lock"); try { + final RandomAccessFile randomAccessFile = new RandomAccessFile(lockFile, "rw"); + final FileLock fileLock = randomAccessFile.getChannel().tryLock(); if (fileLock != null) { Runtime.getRuntime().addShutdownHook(new Thread() { @@ -308,6 +312,7 @@ public class App implements AppAccess { }); return true; } + } catch (Exception e) { System.err.println("Unable to create and/or lock file."); e.printStackTrace(); diff --git a/src/mightypork/rogue/Res.java b/src/mightypork/rogue/Res.java index 7bc6cac..58e29f7 100644 --- a/src/mightypork/rogue/Res.java +++ b/src/mightypork/rogue/Res.java @@ -1,22 +1,40 @@ package mightypork.rogue; +import mightypork.rogue.fonts.DeferredFont; +import mightypork.rogue.fonts.DeferredFont.FontStyle; +import mightypork.rogue.fonts.FontBank; +import mightypork.rogue.fonts.GLFont; import mightypork.rogue.sound.SoundBank; import mightypork.rogue.sound.players.EffectPlayer; import mightypork.rogue.sound.players.LoopPlayer; +import mightypork.rogue.texture.FilteredTexture.Filter; +import mightypork.rogue.texture.FilteredTexture.Wrap; import mightypork.rogue.texture.TextureBank; import mightypork.rogue.texture.TxQuad; import org.newdawn.slick.opengl.Texture; +/** + * Static resource repository + * + * @author MightyPork + */ public class Res { private static TextureBank textures; private static SoundBank sounds; + private static FontBank fonts; + private static boolean initialized = false; + /** + * Load on behalf of given {@link AppAccess} + * + * @param app app access + */ public static void load(App app) { if (initialized) return; @@ -24,6 +42,7 @@ public class Res { textures = new TextureBank(app); sounds = new SoundBank(app); + fonts = new FontBank(app); loadSounds(); loadTextures(); @@ -33,13 +52,13 @@ public class Res { private static void loadFonts() { - // + fonts.loadFont("PolygonPixel_16", new DeferredFont("/res/font/PolygonPixel5x7Standard.ttf", null, 32, FontStyle.PLAIN, true)); } private static void loadTextures() { - textures.loadTexture("test.kitten", "/res/img/kitten.png"); + textures.loadTexture("test.kitten", "/res/img/kitten.png", Filter.LINEAR, Filter.NEAREST, Wrap.CLAMP); } @@ -74,4 +93,10 @@ public class Res { return sounds.getEffect(key); } + + public static GLFont getFont(String key) + { + return fonts.getFont(key); + } + } diff --git a/src/mightypork/rogue/bus/Subsystem.java b/src/mightypork/rogue/bus/Subsystem.java index 4c01200..99f2ad5 100644 --- a/src/mightypork/rogue/bus/Subsystem.java +++ b/src/mightypork/rogue/bus/Subsystem.java @@ -2,8 +2,6 @@ package mightypork.rogue.bus; import mightypork.rogue.AppAccess; -import mightypork.utils.control.bus.clients.DelegatingClient; -import mightypork.utils.control.bus.clients.ToggleableClient; import mightypork.utils.control.interf.Destroyable; @@ -13,7 +11,7 @@ import mightypork.utils.control.interf.Destroyable; * * @author MightyPork */ -public abstract class Subsystem extends ChildClient implements DelegatingClient, ToggleableClient, Destroyable { +public abstract class Subsystem extends ChildClient implements Destroyable { public Subsystem(AppAccess app) { super(app); diff --git a/src/mightypork/rogue/bus/events/ResourceLoadRequest.java b/src/mightypork/rogue/bus/events/ResourceLoadRequest.java index 36dbfb5..85ec024 100644 --- a/src/mightypork/rogue/bus/events/ResourceLoadRequest.java +++ b/src/mightypork/rogue/bus/events/ResourceLoadRequest.java @@ -1,7 +1,7 @@ package mightypork.rogue.bus.events; -import mightypork.rogue.Deferred; +import mightypork.rogue.loading.Deferred; import mightypork.utils.control.bus.Event; import mightypork.utils.control.bus.SingularEvent; diff --git a/src/mightypork/rogue/fonts/Align.java b/src/mightypork/rogue/fonts/Align.java deleted file mode 100644 index bafde67..0000000 --- a/src/mightypork/rogue/fonts/Align.java +++ /dev/null @@ -1,20 +0,0 @@ -package mightypork.rogue.fonts; - - -/** - * Alignment - * - * @author MightyPork - */ -public class Align { - - public static final int LEFT = -1; - public static final int RIGHT = 1; - public static final int TOP = 1; - public static final int BOTTOM = -1; - public static final int UP = 1; - public static final int DOWN = -1; - public static final int CENTER = 0; - public static final int MIDDLE = 0; - -} diff --git a/src/mightypork/rogue/fonts/DeferredFont.java b/src/mightypork/rogue/fonts/DeferredFont.java new file mode 100644 index 0000000..2295300 --- /dev/null +++ b/src/mightypork/rogue/fonts/DeferredFont.java @@ -0,0 +1,216 @@ +package mightypork.rogue.fonts; + + +import java.awt.Font; +import java.awt.FontFormatException; +import java.io.IOException; +import java.io.InputStream; + +import mightypork.rogue.loading.DeferredResource; +import mightypork.rogue.loading.MustLoadInMainThread; +import mightypork.utils.files.FileUtils; +import mightypork.utils.math.color.RGB; +import mightypork.utils.math.coord.Coord; + + +/** + * Font obtained from a resource file (TTF). + * + * @author MightyPork + */ +public class DeferredFont extends DeferredResource implements MustLoadInMainThread, GLFont { + + public static enum FontStyle + { + PLAIN(Font.PLAIN), BOLD(Font.BOLD), ITALIC(Font.ITALIC), BOLD_ITALIC(Font.BOLD + Font.ITALIC); + + int numeric; + + + private FontStyle(int style) { + this.numeric = style; + } + } + + private SlickFont font = null; + private final double size; + private final FontStyle style; + private final boolean antiAlias; + private final String extraChars; + + + /** + * A font from resource + * + * @param resourcePath resource to load + * @param extraChars extra chars (0-255 loaded by default) + * @param size size (pt) + */ + public DeferredFont(String resourcePath, String extraChars, double size) { + this(resourcePath, extraChars, size, FontStyle.PLAIN, true); + } + + + /** + * A font from resource + * + * @param resourcePath resource to load + * @param extraChars extra chars (0-255 loaded by default) + * @param size size (pt) + * @param style font style + */ + public DeferredFont(String resourcePath, String extraChars, double size, FontStyle style) { + this(resourcePath, extraChars, size, style, true); + } + + + /** + * A font from resource + * + * @param resourcePath resource to load + * @param extraChars extra chars (0-255 loaded by default) + * @param size size (pt) + * @param style font style + * @param antialias use antialiasing + */ + public DeferredFont(String resourcePath, String extraChars, double size, FontStyle style, boolean antialias) { + super(resourcePath); + this.size = size; + this.style = style; + this.antiAlias = antialias; + this.extraChars = extraChars; + } + + + @Override + protected final void loadResource(String path) throws FontFormatException, IOException + { + Font awtFont = getAwtFont(path, (float) size, style.numeric); + + font = new SlickFont(awtFont, antiAlias, extraChars); + } + + + /** + * Get a font for a resource path / name + * + * @param resource resource to load + * @param size font size (pt) + * @param style font style + * @return the {@link Font} + * @throws FontFormatException + * @throws IOException + */ + protected Font getAwtFont(String resource, float size, int style) throws FontFormatException, IOException + { + InputStream in = null; + + try { + + in = FileUtils.getResource(resource); + + Font awtFont = Font.createFont(Font.TRUETYPE_FONT, in); + + awtFont = awtFont.deriveFont(size); + awtFont = awtFont.deriveFont(style); + + return awtFont; + + } finally { + try { + if (in != null) in.close(); + } catch (IOException e) { + //pass + } + } + } + + + /** + * Draw string + * + * @param str string to draw + * @param color draw color + */ + @Override + public void draw(String str, RGB color) + { + if (!ensureLoaded()) return; + + font.draw(str, color); + } + + + /** + * Draw string at 0,0 + * + * @param str string to draw + * @param color draw color + * @param startIndex first drawn character index + * @param endIndex last drawn character index + */ + @Override + public void draw(String str, RGB color, int startIndex, int endIndex) + { + if (!ensureLoaded()) return; + + font.draw(str, color, startIndex, endIndex); + } + + + /** + * Draw string 0,0 + * + * @param str string to draw + */ + @Override + public void draw(String str) + { + if (!ensureLoaded()) return; + + font.draw(str); + } + + + /** + * Get size needed to render give string + * + * @param text string to check + * @return coord (width, height) + */ + @Override + public Coord getNeededSpace(String text) + { + if (!ensureLoaded()) return Coord.zero(); + + return font.getNeededSpace(text); + } + + + /** + * @return font height + */ + @Override + public int getHeight() + { + if (!ensureLoaded()) return 0; + + return font.getHeight(); + } + + + @Override + public int getWidth(String text) + { + return font.getWidth(text); + } + + + @Override + public void destroy() + { + // this will have to suffice + font = null; + } + +} diff --git a/src/mightypork/rogue/fonts/DeferredFontNative.java b/src/mightypork/rogue/fonts/DeferredFontNative.java new file mode 100644 index 0000000..e2a8dd8 --- /dev/null +++ b/src/mightypork/rogue/fonts/DeferredFontNative.java @@ -0,0 +1,61 @@ +package mightypork.rogue.fonts; + + +import java.awt.Font; +import java.awt.FontFormatException; +import java.io.IOException; + + +/** + * Font obtained from the OS + * + * @author MightyPork + */ +public class DeferredFontNative extends DeferredFont { + + /** + * A font from OS, found by name + * + * @param fontName font family name + * @param extraChars extra chars (0-255 loaded by default) + * @param size size (pt) + */ + public DeferredFontNative(String fontName, String extraChars, double size) { + super(fontName, extraChars, size); + } + + + /** + * A font from OS, found by name + * + * @param fontName font family name + * @param extraChars extra chars (0-255 loaded by default) + * @param size size (pt) + * @param style font style + */ + public DeferredFontNative(String fontName, String extraChars, double size, FontStyle style) { + super(fontName, extraChars, size, style); + } + + + /** + * A font from OS, found by name + * + * @param fontName font family name + * @param extraChars extra chars (0-255 loaded by default) + * @param size size (pt) + * @param style font style + * @param antialias use antialiasing + */ + public DeferredFontNative(String fontName, String extraChars, double size, FontStyle style, boolean antialias) { + super(fontName, extraChars, size, style, antialias); + } + + + @Override + protected Font getAwtFont(String resource, float size, int style) throws FontFormatException, IOException + { + return new Font(resource, style, (int) size); + } + +} diff --git a/src/mightypork/rogue/fonts/FontBank.java b/src/mightypork/rogue/fonts/FontBank.java new file mode 100644 index 0000000..0cbcf2e --- /dev/null +++ b/src/mightypork/rogue/fonts/FontBank.java @@ -0,0 +1,75 @@ +package mightypork.rogue.fonts; + + +import java.util.HashMap; + +import mightypork.rogue.AppAccess; +import mightypork.rogue.AppAdapter; +import mightypork.rogue.bus.events.ResourceLoadRequest; +import mightypork.utils.logging.Log; + +import org.newdawn.slick.opengl.Texture; + + +/** + * Font loader and registry + * + * @author MightyPork + */ +public class FontBank extends AppAdapter { + + private static final GLFont NULL_FONT = new NullFont(); + + + public FontBank(AppAccess app) { + super(app); + } + + private final HashMap fonts = new HashMap(); + + + /** + * Load a {@link DeferredFont} + * + * @param key font key + * @param font font instance + */ + public void loadFont(String key, DeferredFont font) + { + bus().queue(new ResourceLoadRequest(font)); + + fonts.put(key, font); + } + + + /** + * Add a {@link GLFont} to the bank. + * + * @param key font key + * @param font font instance + */ + public void addFont(String key, GLFont font) + { + fonts.put(key, font); + } + + + /** + * Get a loaded {@link Texture} + * + * @param key texture key + * @return the texture + */ + public GLFont getFont(String key) + { + GLFont f = fonts.get(key); + + if (f == null) { + Log.w("There's no font called " + key + "!"); + return NULL_FONT; + } + + return f; + } + +} diff --git a/src/mightypork/rogue/fonts/FontManager.java b/src/mightypork/rogue/fonts/FontManager.java deleted file mode 100644 index dcc1472..0000000 --- a/src/mightypork/rogue/fonts/FontManager.java +++ /dev/null @@ -1,320 +0,0 @@ -package mightypork.rogue.fonts; - - -import java.awt.Font; -import java.io.InputStream; -import java.util.HashMap; - -import mightypork.rogue.Config; -import mightypork.utils.logging.Log; -import mightypork.utils.math.coord.Coord; - -import org.newdawn.slick.util.ResourceLoader; - - -/** - * Remade universal font manager for Sector. - * - * @author MightyPork - */ -public class FontManager { - - private static final boolean DEBUG = Config.LOG_FONTS; - - /** - * Glyph tables. - * - * @author MightyPork - */ - public static class Glyphs { - - //@formatter:off - /** all glyphs */ - public static final String all = - " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]" + - "^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ¡¢£¤" + - "¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäå" + - "æçèéêëìíîïðñòóôõö÷øùúûüýþÿ"; - - /** letters and numbers, sufficient for basic messages etc. NO SPACE */ - public static final String alnum_nospace = - "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; - - /** letters and numbers, sufficient for basic messages etc. */ - public static final String alnum = - " "+alnum_nospace; - - /** letters and numbers with the most basic punctuation signs */ - public static final String basic_text = - " .-,.?!:;_"+alnum_nospace; - - /** letters */ - public static final String alpha = - " ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; - - /** numbers */ - public static final String numbers = - " 0123456789.-,:"; - - /** non-standard variants of alnum */ - public static final String alnum_extra = - " ŒÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜŸÝßàáâãäåæçèéêëìíîïðñòóôõöøùúû" + - "üýþÿĚŠČŘŽŤŇĎŮěščřžťňďůŁłđ"; - - /** signs and punctuation */ - public static final String signs = - " !\"#$%&§'()*+,-./:;<=>?@[\\]^_{|}~"; - - /** extra signs and punctuation */ - public static final String signs_extra = - " ¥€£¢`ƒ„…†‡ˆ‰‹‘’“”•›¡¤¦¨ª«¬­¯°±²³´µ¶·¸¹º»¼½¾¿÷™©­®→↓←↑"; - - - /** basic character set. */ - public static final String basic = alnum + signs; - //@formatter:on - } - - /** - * Font style - * - * @author MightyPork - */ - public static enum Style - { - /** Normal */ - NORMAL, - /** Italic */ - ITALIC, - /** Stronger italic to left. */ - LEFT, - /** Stronger italic to right */ - RIGHT, - /** Monospace type */ - MONO, - /** Bold */ - BOLD, - /** Bold & Italic */ - BOLD_I, - /** Bold & Left */ - BOLD_L, - /** Bold & Right */ - BOLD_R, - /** Heavy style, stronger than bold. */ - HEAVY, - /** Light (lighter than normal) */ - LIGHT, - /** narrow style, similar to Light */ - NARROW, - /** Wide style, like Bold but with thinner lines */ - WIDE, - /** Outline variant of normal */ - OUTLINE; - } - - // /** - // * Preloaded font identifier [name, size, style] - // * - // * @author MightyPork - // */ - // public static class FontId { - // - // /** font size (pt) */ - // public float size = 24; - // /** font name, registered with registerFile */ - // public String name = ""; - // /** font style. The given style must be in a file. */ - // public Style style; - // - // /** Set of glyphs in this ID */ - // public String glyphs = ""; - // - // /** Index for faster comparision of glyph ids. */ - // public int glyphset_id = 0; - // - // - // /** - // * Preloaded font identifier - // * - // * @param name font name (registerFile) - // * @param size font size (pt) - // * @param style font style - // * @param glyphs glyphs to load - // */ - // public FontId(String name, double size, Style style, String glyphs) { - // this.name = name; - // this.size = (float) size; - // this.style = style; - // - // if (glyphs.equals(Glyphs.basic)) { - // glyphset_id = 1; - // } else if (glyphs.equals(Glyphs.alnum)) { - // glyphset_id = 2; - // } else if (glyphs.equals(Glyphs.basic_text)) { - // glyphset_id = 3; - // } else if (glyphs.equals(Glyphs.numbers)) { - // glyphset_id = 4; - // } else if (glyphs.equals(Glyphs.alpha)) { - // glyphset_id = 5; - // } else if (glyphs.equals(Glyphs.all)) { - // glyphset_id = 6; - // } else if (glyphs.equals(Glyphs.alnum_extra)) { - // glyphset_id = 7; - // } else if (glyphs.equals(Glyphs.signs)) { - // glyphset_id = 8; - // } else if (glyphs.equals(Glyphs.signs_extra)) { - // glyphset_id = 9; - // } else { - // this.glyphs = glyphs; - // } - // } - // - // - // @Override - // public boolean equals(Object obj) - // { - // if (obj == null) return false; - // if (!(obj.getClass().isAssignableFrom(getClass()))) return false; - // if (obj instanceof FontId) { - // if (obj == this) return true; - // FontId id2 = ((FontId) obj); - // boolean flag = true; - // flag &= id2.size == size; - // flag &= id2.name.equals(name); - // flag &= id2.style == style; - // flag &= ((id2.glyphset_id != -1 && id2.glyphset_id == glyphset_id) || - // id2.glyphs.equals(glyphs)); - // return flag; - // } - // return false; - // } - // - // - // @Override - // public int hashCode() - // { - // return (new Float(size).hashCode()) ^ name.hashCode() ^ style.hashCode() - // ^ glyphset_id; - // } - // - // - // @Override - // public String toString() - // { - // return "[" + name + ", " + size + ", " + style + (glyphset_id > 0 ? - // ", g=" + glyphset_id : ", g=custom") + "]"; - // } - // } - - /** - * Group of styles of one font. - * - * @author MightyPork - */ - public static class FontFamily extends HashMap { - } - - /** - * Table of font files. name → {style:file,style:file,style:file...} - */ - private static HashMap fontFiles = new HashMap(); - - - /** - * Register font file. - * - * @param path resource path (res/fonts/...) - * @param name font name (for binding) - * @param style font style in this file - */ - public static void registerFile(String path, String name, Style style) - { - if (fontFiles.containsKey(name)) { - if (fontFiles.get(name) != null) { - fontFiles.get(name).put(style, path); - return; - } - } - - // insert new table of styles to font name. - FontFamily family = new FontFamily(); - family.put(style, path); - fontFiles.put(name, family); - } - - /** Counter of loaded fonts */ - public static int loadedFontCounter = 0; - - - /** - * Preload font if needed, get preloaded font.
- * If needed file is not available, throws runtime exception. - * - * @param name font name (registerFile) - * @param size font size (pt) - * @param style font style - * @param glyphs glyphs needed - * @return the loaded font. - */ - public static LoadedFont loadFont(String name, double size, Style style, String glyphs) - { - return loadFont(name, size, style, glyphs, 9, 8, Coord.one(), 0, 0); - } - - - /** - * Preload font if needed, get preloaded font.
- * If needed file is not available, throws runtime exception. - * - * @param name font name (registerFile) - * @param size font size (pt) - * @param style font style - * @param glyphs glyphs needed - * @param correctLeft left horizontal correction - * @param correctRight right horizontal correction - * @param scale font scale (changing aspect ratio) - * @param clipTop top clip (0-1) - top part of the font to be cut off - * @param clipBottom bottom clip (0-1) - bottom part of the font to be cut - * off - * @return the loaded font. - */ - public static LoadedFont loadFont(String name, double size, Style style, String glyphs, int correctLeft, int correctRight, Coord scale, double clipTop, double clipBottom) - { - String resourcePath; - try { - resourcePath = fontFiles.get(name).get(style); - if (resourcePath == null) { - Log.w("Font [" + name + "] does not have variant " + style + ".\nUsing NORMAL instead."); - resourcePath = fontFiles.get(name).get(Style.NORMAL); - if (resourcePath == null) { - throw new NullPointerException(); - } - } - } catch (NullPointerException npe) { - throw new RuntimeException("Font loading failed: no font file registered for name \"" + name + "\"."); - } - - InputStream in = ResourceLoader.getResourceAsStream(resourcePath); - - Font awtFont; - try { - awtFont = Font.createFont(Font.TRUETYPE_FONT, in); - } catch (Exception e) { - Log.e("Loading of font " + resourcePath + " failed.", e); - throw new RuntimeException(e); - } - - awtFont = awtFont.deriveFont((float) size); // set font size - LoadedFont font = new LoadedFont(awtFont, true, glyphs); - - font.setCorrection(correctLeft, correctRight); - font.setClip(clipTop, clipBottom); - font.setScale(scale.x, scale.y); - - loadedFontCounter++; - - if (DEBUG) Log.f3("Font from file \"" + resourcePath + "\" preloaded."); - - return font; - } -} diff --git a/src/mightypork/rogue/fonts/Fonts.java b/src/mightypork/rogue/fonts/Fonts.java deleted file mode 100644 index 25eb2c8..0000000 --- a/src/mightypork/rogue/fonts/Fonts.java +++ /dev/null @@ -1,60 +0,0 @@ -package mightypork.rogue.fonts; - - -import static mightypork.rogue.fonts.FontManager.Style.*; -import mightypork.rogue.fonts.FontManager.Glyphs; -import mightypork.utils.logging.Log; - - -/** - * Global font preloader - * - * @author Rapus - */ -public class Fonts { - - public static LoadedFont splash_info; - - public static LoadedFont tooltip; - public static LoadedFont gui; - public static LoadedFont gui_title; - public static LoadedFont program_number; - public static LoadedFont menu_button; - public static LoadedFont menu_title; - public static LoadedFont tiny; - - - private static void registerFileNames() - { - FontManager.registerFile("res/fonts/4feb.ttf", "4feb", NORMAL); - } - - - /** - * Load fonts needed for splash. - */ - public static void loadForSplash() - { - registerFileNames(); - - gui = FontManager.loadFont("4feb", 24, NORMAL, Glyphs.basic).setCorrection(8, 7); - splash_info = FontManager.loadFont("4feb", 42, NORMAL, "Loading."); - } - - - /** - * Preload all fonts we will use in the game - */ - public static void load() - { - tooltip = FontManager.loadFont("4feb", 24, NORMAL, Glyphs.basic_text).setCorrection(8, 7); - gui_title = FontManager.loadFont("4feb", 30, NORMAL, Glyphs.basic_text); - menu_button = FontManager.loadFont("4feb", 36, NORMAL, Glyphs.basic_text); - menu_title = FontManager.loadFont("4feb", 34, NORMAL, Glyphs.basic_text); - program_number = FontManager.loadFont("4feb", 28, NORMAL, Glyphs.numbers); - tiny = FontManager.loadFont("4feb", 20, NORMAL, Glyphs.basic_text); - - Log.i("Fonts loaded = " + FontManager.loadedFontCounter); - - } -} diff --git a/src/mightypork/rogue/fonts/GLFont.java b/src/mightypork/rogue/fonts/GLFont.java new file mode 100644 index 0000000..7a50042 --- /dev/null +++ b/src/mightypork/rogue/fonts/GLFont.java @@ -0,0 +1,59 @@ +package mightypork.rogue.fonts; + + +import mightypork.utils.math.color.RGB; +import mightypork.utils.math.coord.Coord; + + +public interface GLFont { + + /** + * Draw string at position + * + * @param text string to draw + * @param color draw color + */ + abstract void draw(String text, RGB color); + + + /** + * Draw string at position + * + * @param text string to draw + * @param color draw color + * @param startIndex first drawn character index + * @param endIndex last drawn character index + */ + abstract void draw(String text, RGB color, int startIndex, int endIndex); + + + /** + * Draw string at position + * + * @param str string to draw + */ + abstract void draw(String str); + + + /** + * Get suize needed to render give string + * + * @param text string to check + * @return coord (width, height) + */ + abstract Coord getNeededSpace(String text); + + + /** + * @return font height + */ + abstract int getHeight(); + + + /** + * @param text texted text + * @return space needed + */ + abstract int getWidth(String text); + +} diff --git a/src/mightypork/rogue/fonts/Glyphs.java b/src/mightypork/rogue/fonts/Glyphs.java new file mode 100644 index 0000000..24edd1e --- /dev/null +++ b/src/mightypork/rogue/fonts/Glyphs.java @@ -0,0 +1,24 @@ +package mightypork.rogue.fonts; + + +/** + * Glyph tables. + * + * @author MightyPork + */ +public class Glyphs { + + public static final String space = " "; + public static final String latin = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + public static final String latin_extra = "ŒÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜŸÝßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿĚŠČŘŽŤŇĎŮěščřžťňďůŁłđ"; + public static final String numbers = "0123456789"; + public static final String punctuation = ".-,.?!:;\"'"; + public static final String punctuation_extra = "()¿¡»«›‹“”‘’„…"; + public static final String symbols = "[]{}#$%&§*+/<=>@\\^_|~°"; + public static final String symbols_extra = "¥€£¢`ƒ†‡ˆ‰•¤¦¨ªº¹²³¬­¯±´µ¶·¸¼½¾×÷™©­®→↓←↑"; + + public static final String basic = space + latin + numbers + punctuation + symbols; + public static final String extra = latin_extra + punctuation_extra + symbols_extra; + public static final String all = basic + extra; + +} diff --git a/src/mightypork/rogue/fonts/LoadedFont.java b/src/mightypork/rogue/fonts/LoadedFont.java deleted file mode 100644 index cdba1c9..0000000 --- a/src/mightypork/rogue/fonts/LoadedFont.java +++ /dev/null @@ -1,639 +0,0 @@ -package mightypork.rogue.fonts; - - -import static mightypork.rogue.fonts.Align.*; -import static org.lwjgl.opengl.GL11.*; - -import java.awt.*; -import java.awt.image.BufferedImage; -import java.awt.image.DataBuffer; -import java.awt.image.DataBufferByte; -import java.awt.image.DataBufferInt; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.IntBuffer; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import mightypork.rogue.Config; -import mightypork.utils.logging.Log; -import mightypork.utils.math.color.RGB; -import mightypork.utils.math.coord.Coord; - -import org.lwjgl.BufferUtils; -import org.lwjgl.opengl.GL11; -import org.lwjgl.util.glu.GLU; - - -/** - * A TrueType font implementation originally for Slick, edited for Bobjob's - * Engine - * - * @original author James Chambers (Jimmy) - * @original author Jeremy Adams (elias4444) - * @original author Kevin Glass (kevglass) - * @original author Peter Korzuszek (genail) - * @new version edited by David Aaron Muhar (bobjob) - * @new version edited by MightyPork - */ -public class LoadedFont { - - private static final boolean DEBUG = Config.LOG_FONTS; - - /** Map of user defined font characters (Character <-> IntObject) */ - private Map chars = new HashMap(100); - - /** Boolean flag on whether AntiAliasing is enabled or not */ - private boolean antiAlias; - - /** Font's size */ - private int fontSize = 0; - - /** Font's height */ - private int fontHeight = 0; - - /** Texture used to cache the font 0-255 characters */ - private int fontTextureID; - - /** Default font texture width */ - private int textureWidth = 2048; - - /** Default font texture height */ - private int textureHeight = 2048; - - /** A reference to Java's AWT Font that we create our font texture from */ - private Font font; - - /** The font metrics for our Java AWT font */ - private FontMetrics fontMetrics; - - private int correctL = 9, correctR = 8; - - private double defScaleX = 1, defScaleY = 1; - private double clipVerticalT = 0; - private double clipVerticalB = 0; - - private class CharStorageEntry { - - /** Character's width */ - public int width; - - /** Character's height */ - public int height; - - /** Character's stored x position */ - public int texPosX; - - /** Character's stored y position */ - public int texPosY; - } - - - public LoadedFont(Font font, boolean antiAlias, String charsNeeded) { - this.font = font; - this.fontSize = font.getSize() + 3; - this.antiAlias = antiAlias; - - createSet(charsNeeded.toCharArray()); - - fontHeight -= 1; - if (fontHeight <= 0) fontHeight = 1; - } - - - public void setCorrection(boolean on) - { - if (on) { - correctL = 9;// 2 - correctR = 8;// 1 - } else { - correctL = 0; - correctR = 0; - } - } - - - private BufferedImage getFontImage(char ch) - { - // Create a temporary image to extract the character's size - BufferedImage tempfontImage = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB); - Graphics2D g = (Graphics2D) tempfontImage.getGraphics(); - if (antiAlias == true) { - g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - } - g.setFont(font); - fontMetrics = g.getFontMetrics(); - int charwidth = fontMetrics.charWidth(ch) + 8; - - if (charwidth <= 0) { - charwidth = 7; - } - int charheight = fontMetrics.getHeight() + 3; - if (charheight <= 0) { - charheight = fontSize; - } - - // Create another image holding the character we are creating - BufferedImage fontImage; - fontImage = new BufferedImage(charwidth, charheight, BufferedImage.TYPE_INT_ARGB); - Graphics2D gt = (Graphics2D) fontImage.getGraphics(); - if (antiAlias == true) { - gt.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - } - gt.setFont(font); - - gt.setColor(Color.WHITE); - int charx = 3; - int chary = 1; - gt.drawString(String.valueOf(ch), (charx), (chary) + fontMetrics.getAscent()); - - return fontImage; - - } - - - private void createSet(char[] charsToLoad) - { - try { - class LoadedGlyph { - - public char c; - public BufferedImage image; - public int width; - public int height; - - - public LoadedGlyph(char c, BufferedImage image) { - this.image = image; - this.c = c; - this.width = image.getWidth(); - this.height = image.getHeight(); - } - } - - List glyphs = new ArrayList(); - List loaded = new ArrayList(); - for (char ch : charsToLoad) { - if (!loaded.contains(ch)) { - glyphs.add(new LoadedGlyph(ch, getFontImage(ch))); - loaded.add(ch); - } - } - - Coord canvas = new Coord(128, 128); - double lineHeight = 0; - Coord begin = new Coord(0, 0); - boolean needsLarger = false; - - while (true) { - needsLarger = false; - - for (LoadedGlyph glyph : glyphs) { - if (begin.x + glyph.width > canvas.x) { - begin.y += lineHeight; - lineHeight = 0; - begin.x = 0; - } - - if (lineHeight < glyph.height) { - lineHeight = glyph.height; - } - - if (begin.y + lineHeight > canvas.y) { - needsLarger = true; - break; - } - - // draw. - begin.x += glyph.width; - } - - if (needsLarger) { - canvas.x *= 2; - canvas.y *= 2; - begin.setTo(0, 0); - lineHeight = 0; - } else { - if (DEBUG) Log.f3("Preparing texture " + canvas.x + "x" + canvas.y); - break; - } - } - - textureWidth = (int) canvas.x; - textureHeight = (int) canvas.y; - - BufferedImage imgTemp = new BufferedImage(textureWidth, textureHeight, BufferedImage.TYPE_INT_ARGB); - Graphics2D g = (Graphics2D) imgTemp.getGraphics(); - - g.setColor(new Color(0, 0, 0, 1)); - g.fillRect(0, 0, textureWidth, textureHeight); - - int rowHeight = 0; - int positionX = 0; - int positionY = 0; - - for (LoadedGlyph glyph : glyphs) { - CharStorageEntry storedChar = new CharStorageEntry(); - - storedChar.width = glyph.width; - storedChar.height = glyph.height; - - if (positionX + storedChar.width >= textureWidth) { - positionX = 0; - positionY += rowHeight; - rowHeight = 0; - } - - storedChar.texPosX = positionX; - storedChar.texPosY = positionY; - - if (storedChar.height > fontHeight) { - fontHeight = storedChar.height; - } - - if (storedChar.height > rowHeight) { - rowHeight = storedChar.height; - } - - // Draw it here - g.drawImage(glyph.image, positionX, positionY, null); - - positionX += storedChar.width; - - chars.put(glyph.c, storedChar); - } - - fontTextureID = loadImage(imgTemp); - - imgTemp = null; - - } catch (Exception e) { - System.err.println("Failed to create font."); - e.printStackTrace(); - } - } - - - private void drawQuad(double drawX, double drawY, double drawX2, double drawY2, CharStorageEntry charObj) - { - double srcX = charObj.texPosX + charObj.width; - double srcY = charObj.texPosY + charObj.height; - double srcX2 = charObj.texPosX; - double srcY2 = charObj.texPosY; - double DrawWidth = drawX2 - drawX; - double DrawHeight = drawY2 - drawY; - double TextureSrcX = srcX / textureWidth; - double TextureSrcY = srcY / textureHeight; - double SrcWidth = srcX2 - srcX; - double SrcHeight = srcY2 - srcY; - double RenderWidth = (SrcWidth / textureWidth); - double RenderHeight = (SrcHeight / textureHeight); - - drawY -= DrawHeight * clipVerticalB; - - GL11.glTexCoord2d(TextureSrcX, TextureSrcY); - GL11.glVertex2d(drawX, drawY); - GL11.glTexCoord2d(TextureSrcX, TextureSrcY + RenderHeight); - GL11.glVertex2d(drawX, drawY + DrawHeight); - GL11.glTexCoord2d(TextureSrcX + RenderWidth, TextureSrcY + RenderHeight); - GL11.glVertex2d(drawX + DrawWidth, drawY + DrawHeight); - GL11.glTexCoord2d(TextureSrcX + RenderWidth, TextureSrcY); - GL11.glVertex2d(drawX + DrawWidth, drawY); - } - - - public int getWidth(String whatchars) - { - if (whatchars == null) whatchars = ""; - int totalwidth = 0; - CharStorageEntry charStorage = null; - char currentChar = 0; - for (int i = 0; i < whatchars.length(); i++) { - currentChar = whatchars.charAt(i); - - charStorage = chars.get(currentChar); - - if (charStorage != null) { - totalwidth += charStorage.width - correctL; - } - } - return (int) (totalwidth * defScaleX); - } - - - public int getHeight() - { - return (int) (fontHeight * defScaleY * (1 - clipVerticalT - clipVerticalB)); - } - - - public int getLineHeight() - { - return getHeight(); - } - - - public void drawString(double x, double y, String text, double scaleX, double scaleY, RGB color) - { - drawString(x, y, text, 0, text.length() - 1, scaleX, scaleY, color, LEFT); - } - - - public void drawString(double x, double y, String text, double scaleX, double scaleY, RGB color, int align) - { - drawString(x, y, text, 0, text.length() - 1, scaleX, scaleY, color, align); - } - - - private void drawString(double x, double y, String text, int startIndex, int endIndex, double scaleX, double scaleY, RGB color, int align) - { - x = Math.round(x); - y = Math.round(y); - - scaleX *= defScaleX; - scaleY *= defScaleY; - - CharStorageEntry charStorage = null; - int charCurrent; - - int totalwidth = 0; - int i = startIndex, d = 1, c = correctL; - float startY = 0; - - switch (align) { - case RIGHT: { - d = -1; - c = correctR; - - while (i < endIndex) { - if (text.charAt(i) == '\n') startY -= getHeight(); - i++; - } - break; - } - case CENTER: { - for (int l = startIndex; l <= endIndex; l++) { - charCurrent = text.charAt(l); - if (charCurrent == '\n') break; - - charStorage = chars.get((char) charCurrent); - if (charStorage != null) { - totalwidth += charStorage.width - correctL; - } - } - totalwidth /= -2; - break; - } - case LEFT: - default: { - d = 1; - c = correctL; - break; - } - - } - - GL11.glPushAttrib(GL_ENABLE_BIT); - GL11.glEnable(GL11.GL_TEXTURE_2D); - GL11.glBindTexture(GL11.GL_TEXTURE_2D, fontTextureID); - GL11.glColor4d(color.r, color.g, color.b, color.a); - GL11.glBegin(GL11.GL_QUADS); - - while (i >= startIndex && i <= endIndex) { - charCurrent = text.charAt(i); - - charStorage = chars.get(new Character((char) charCurrent)); - - if (charStorage != null) { - if (d < 0) totalwidth += (charStorage.width - c) * d; - if (charCurrent == '\n') { - startY -= getHeight() * d; - totalwidth = 0; - if (align == CENTER) { - for (int l = i + 1; l <= endIndex; l++) { - charCurrent = text.charAt(l); - if (charCurrent == '\n') break; - - charStorage = chars.get((char) charCurrent); - - totalwidth += charStorage.width - correctL; - } - totalwidth /= -2; - } - // if center get next lines total width/2; - } else { - //@formatter:off - drawQuad( - (totalwidth + charStorage.width) * scaleX + x, - startY * scaleY + y, totalwidth * scaleX + x, - (startY + charStorage.height) * scaleY + y, - charStorage - ); - //@formatter:on - - if (d > 0) totalwidth += (charStorage.width - c) * d; - } - - } - - i += d; - } - GL11.glEnd(); - GL11.glPopAttrib(); - } - - - public static int loadImage(BufferedImage bufferedImage) - { - try { - short width = (short) bufferedImage.getWidth(); - short height = (short) bufferedImage.getHeight(); - // textureLoader.bpp = bufferedImage.getColorModel().hasAlpha() ? - // (byte)32 : (byte)24; - int bpp = (byte) bufferedImage.getColorModel().getPixelSize(); - ByteBuffer byteBuffer; - DataBuffer db = bufferedImage.getData().getDataBuffer(); - if (db instanceof DataBufferInt) { - int intI[] = ((DataBufferInt) (bufferedImage.getData().getDataBuffer())).getData(); - byte newI[] = new byte[intI.length * 4]; - for (int i = 0; i < intI.length; i++) { - byte b[] = intToByteArray(intI[i]); - int newIndex = i * 4; - - newI[newIndex] = b[1]; - newI[newIndex + 1] = b[2]; - newI[newIndex + 2] = b[3]; - newI[newIndex + 3] = b[0]; - } - - byteBuffer = ByteBuffer.allocateDirect(width * height * (bpp / 8)).order(ByteOrder.nativeOrder()).put(newI); - } else { - byteBuffer = ByteBuffer.allocateDirect(width * height * (bpp / 8)).order(ByteOrder.nativeOrder()).put(((DataBufferByte) (bufferedImage.getData().getDataBuffer())).getData()); - } - byteBuffer.flip(); - - int internalFormat = GL11.GL_RGBA8, format = GL11.GL_RGBA; - IntBuffer textureId = BufferUtils.createIntBuffer(1); - - GL11.glGenTextures(textureId); - GL11.glBindTexture(GL11.GL_TEXTURE_2D, textureId.get(0)); - - GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_CLAMP); - GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_CLAMP); - - GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR); - GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR); - - GL11.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_TEXTURE_ENV_MODE, GL11.GL_MODULATE); - - GLU.gluBuild2DMipmaps(GL11.GL_TEXTURE_2D, internalFormat, width, height, format, GL11.GL_UNSIGNED_BYTE, byteBuffer); - return textureId.get(0); - - } catch (Exception e) { - e.printStackTrace(); - System.exit(-1); - } - - return -1; - } - - - public static boolean isSupported(String fontname) - { - Font font[] = getFonts(); - for (int i = font.length - 1; i >= 0; i--) { - if (font[i].getName().equalsIgnoreCase(fontname)) return true; - } - return false; - } - - - public static Font[] getFonts() - { - return GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts(); - } - - - public static Font getFont(String fontname, int style, float size) - { - Font result = null; - GraphicsEnvironment graphicsenvironment = GraphicsEnvironment.getLocalGraphicsEnvironment(); - for (Font font : graphicsenvironment.getAllFonts()) { - if (font.getName().equalsIgnoreCase(fontname)) { - result = font.deriveFont(style, size); - break; - } - } - return result; - } - - - public static byte[] intToByteArray(int value) - { - return new byte[] { (byte) (value >>> 24), (byte) (value >>> 16), (byte) (value >>> 8), (byte) value }; - } - - - public void destroy() - { - IntBuffer scratch = BufferUtils.createIntBuffer(1); - scratch.put(0, fontTextureID); - GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0); - GL11.glDeleteTextures(scratch); - } - - - public LoadedFont setScale(double x, double y) - { - defScaleX = x; - defScaleY = y; - return this; - } - - - public LoadedFont setClip(double clipRatioTop, double clipRatioBottom) - { - clipVerticalT = clipRatioTop; - clipVerticalB = clipRatioBottom; - return this; - } - - - public LoadedFont setCorrection(int correctionLeft, int correctionRight) - { - correctL = correctionLeft; - correctR = correctionRight; - return this; - } - - - /** - * Draw string with font. - * - * @param x x coord - * @param y y coord - * @param text text to draw - * @param color render color - * @param align (-1,0,1) - */ - public void draw(double x, double y, String text, RGB color, int align) - { - drawString(x, y, text, 1, 1, color, align); - } - - - /** - * Draw string with font. - * - * @param pos coord - * @param text text to draw - * @param color render color - * @param align (-1,0,1) - */ - public void draw(Coord pos, String text, RGB color, int align) - { - drawString(pos.x, pos.y, text, 1, 1, color, align); - } - - - public void drawFuzzy(Coord pos, String text, int align, RGB textColor, RGB blurColor, int blurSize) - { - drawFuzzy(pos, text, align, textColor, blurColor, blurSize, true); - } - - - public void drawFuzzy(Coord pos, String text, int align, RGB textColor, RGB blurColor, int blurSize, boolean smooth) - { - glPushMatrix(); - - glTranslated(pos.x, pos.y, pos.z); - - // shadow - int sh = blurSize; - - int l = glGenLists(1); - - glNewList(l, GL_COMPILE); - draw(0, 0, text, blurColor, align); - glEndList(); - - for (int xx = -sh; xx <= sh; xx += (smooth ? 1 : sh)) { - for (int yy = -sh; yy <= sh; yy += (smooth ? 1 : sh)) { - if (xx == 0 && yy == 0) continue; - glPushMatrix(); - glTranslated(xx, yy, 0); - glCallList(l); - glPopMatrix(); - } - } - - glDeleteLists(l, 1); - - draw(0, 0, text, textColor, align); - - glPopMatrix(); - } - -} diff --git a/src/mightypork/rogue/fonts/NullFont.java b/src/mightypork/rogue/fonts/NullFont.java new file mode 100644 index 0000000..deeeb7a --- /dev/null +++ b/src/mightypork/rogue/fonts/NullFont.java @@ -0,0 +1,56 @@ +package mightypork.rogue.fonts; + + +import mightypork.utils.math.color.RGB; +import mightypork.utils.math.coord.Coord; + + +/** + * Null font used where real resource could not be loaded. + * + * @author MightyPork + */ +public class NullFont implements GLFont { + + @Override + public void draw(String str, RGB color) + { + // nope + } + + + @Override + public void draw(String str, RGB color, int startIndex, int endIndex) + { + // nope + } + + + @Override + public void draw(String str) + { + // nope + } + + + @Override + public Coord getNeededSpace(String str) + { + return Coord.zero(); + } + + + @Override + public int getHeight() + { + return 0; + } + + + @Override + public int getWidth(String text) + { + return 0; + } + +} diff --git a/src/mightypork/rogue/fonts/SlickFont.java b/src/mightypork/rogue/fonts/SlickFont.java new file mode 100644 index 0000000..b95fdc6 --- /dev/null +++ b/src/mightypork/rogue/fonts/SlickFont.java @@ -0,0 +1,130 @@ +package mightypork.rogue.fonts; + + +import static org.lwjgl.opengl.GL11.*; + +import java.awt.Font; + +import mightypork.utils.math.color.RGB; +import mightypork.utils.math.coord.Coord; + +import org.newdawn.slick.Color; +import org.newdawn.slick.TrueTypeFont; + + +/** + * Wrapper for slick font + * + * @author MightyPork + */ +public class SlickFont implements GLFont { + + private final TrueTypeFont ttf; + + + /** + * A font with ASCII and extra chars + * + * @param font font to load + * @param antiAlias antialiasing + * @param extraChars extra chars to load + */ + public SlickFont(Font font, boolean antiAlias, String extraChars) { + + ttf = new TrueTypeFont(font, antiAlias, stripASCII(extraChars)); + } + + + private static char[] stripASCII(String chars) + { + if (chars == null) return null; + + StringBuilder sb = new StringBuilder(); + for (char c : chars.toCharArray()) { + if (c <= 255) continue; // already included in default set + sb.append(c); + } + + return sb.toString().toCharArray(); + } + + + private static void prepareForRender() + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + } + + + /** + * Draw in color + * + * @param str string to draw + * @param color text color + */ + @Override + public void draw(String str, RGB color) + { + prepareForRender(); + ttf.drawString(0, 0, str, rgbToSlickColor(color)); + } + + + /** + * Draw substring in color + * + * @param str string to draw + * @param color text color + * @param startIndex first char to draw + * @param endIndex last char to draw (INCLUDING!) + */ + @Override + public void draw(String str, RGB color, int startIndex, int endIndex) + { + prepareForRender(); + ttf.drawString(0, 0, str, rgbToSlickColor(color), startIndex, endIndex); + } + + + /** + * Draw in white + * + * @param str chars to draw + */ + @Override + public void draw(String str) + { + prepareForRender(); + ttf.drawString(0, 0, str); + } + + + private static Color rgbToSlickColor(RGB rgb) + { + return new Color((float) rgb.r, (float) rgb.g, (float) rgb.b, (float) rgb.a); + } + + + @Override + public Coord getNeededSpace(String text) + { + return new Coord(getWidth(text), getHeight()); + } + + + @Override + public int getHeight() + { + return ttf.getHeight(); + } + + + @Override + public int getWidth(String text) + { + return ttf.getWidth(text); + } + +} diff --git a/src/mightypork/rogue/gui/Screen.java b/src/mightypork/rogue/gui/Screen.java index 2f82c01..3b09faa 100644 --- a/src/mightypork/rogue/gui/Screen.java +++ b/src/mightypork/rogue/gui/Screen.java @@ -8,7 +8,6 @@ import mightypork.rogue.bus.events.ScreenChangeEvent; import mightypork.rogue.input.KeyBinder; import mightypork.rogue.input.KeyBindingPool; import mightypork.rogue.input.KeyStroke; -import mightypork.rogue.render.Render; import mightypork.utils.control.interf.Destroyable; import mightypork.utils.math.constraints.ConstraintContext; import mightypork.utils.math.coord.Coord; @@ -25,7 +24,6 @@ public abstract class Screen extends ChildClient implements Destroyable, KeyBind private final KeyBindingPool keybindings = new KeyBindingPool(); private boolean active; - private boolean needSetupGraphics = false; private boolean needSetupViewport = false; @@ -69,10 +67,9 @@ public abstract class Screen extends ChildClient implements Destroyable, KeyBind { if (shown) { active = true; - needSetupGraphics = true; needSetupViewport = true; - onSizeChanged(getRect().getSize()); + onSizeChanged(getRect().size()); onScreenEnter(); // enable events @@ -124,24 +121,6 @@ public abstract class Screen extends ChildClient implements Destroyable, KeyBind protected abstract void renderScreen(); - /** - * Render screen - */ - private void renderBegin() - { - Render.pushState(); - } - - - /** - * Render screen - */ - private void renderEnd() - { - Render.popState(); - } - - /** * @return true if screen is the curretn screen */ @@ -173,41 +152,15 @@ public abstract class Screen extends ChildClient implements Destroyable, KeyBind { if (!isActive()) return; - if (needSetupGraphics) { - setupGraphics(); - } - if (needSetupViewport) { setupViewport(); } - renderBegin(); renderScreen(); - renderEnd(); - } - - - private void setupGraphics() - { - 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); } - private void setupViewport() + protected void setupViewport() { // fix projection for changed size glMatrixMode(GL_PROJECTION); diff --git a/src/mightypork/rogue/gui/screens/test_font/ScreenTestFont.java b/src/mightypork/rogue/gui/screens/test_font/ScreenTestFont.java new file mode 100644 index 0000000..5208e69 --- /dev/null +++ b/src/mightypork/rogue/gui/screens/test_font/ScreenTestFont.java @@ -0,0 +1,61 @@ +package mightypork.rogue.gui.screens.test_font; + + +import mightypork.rogue.AppAccess; +import mightypork.rogue.Res; +import mightypork.rogue.fonts.GLFont; +import mightypork.rogue.gui.Screen; +import mightypork.rogue.render.Render; +import mightypork.utils.math.coord.Coord; + + +public class ScreenTestFont extends Screen { + + public ScreenTestFont(AppAccess app) { + super(app); + } + + + @Override + protected void deinitScreen() + { + // + } + + + @Override + protected void onScreenEnter() + { + // + } + + + @Override + protected void onScreenLeave() + { + // + } + + + @Override + protected void renderScreen() + { + GLFont font = Res.getFont("PolygonPixel_16"); + + String s = "It works!"; + double scale = getRect().height() / 50D; + Render.pushState(); + Render.translate(getRect().getCenter().sub(font.getNeededSpace(s).mul(scale).half())); + Render.scale(new Coord(scale)); + font.draw("It works!"); + Render.popState(); + } + + + @Override + public String getId() + { + return "test.font"; + } + +} diff --git a/src/mightypork/rogue/input/InputSystem.java b/src/mightypork/rogue/input/InputSystem.java index b732755..94536cb 100644 --- a/src/mightypork/rogue/input/InputSystem.java +++ b/src/mightypork/rogue/input/InputSystem.java @@ -22,6 +22,7 @@ public class InputSystem extends Subsystem implements Updateable, KeyBinder { // listeners private final KeyBindingPool keybindings; private boolean yAxisDown = true; + private static boolean inited = false; public InputSystem(AppAccess app) { @@ -43,8 +44,11 @@ public class InputSystem extends Subsystem implements Updateable, KeyBinder { } - private void initDevices() + private static void initDevices() { + if (inited) return; + inited = true; + try { Mouse.create(); Keyboard.create(); diff --git a/src/mightypork/rogue/Deferred.java b/src/mightypork/rogue/loading/Deferred.java similarity index 59% rename from src/mightypork/rogue/Deferred.java rename to src/mightypork/rogue/loading/Deferred.java index 2c56b6d..68f1603 100644 --- a/src/mightypork/rogue/Deferred.java +++ b/src/mightypork/rogue/loading/Deferred.java @@ -1,4 +1,4 @@ -package mightypork.rogue; +package mightypork.rogue.loading; /** @@ -9,12 +9,14 @@ package mightypork.rogue; public interface Deferred { /** - * Load the actual resource if not loaded yet + * Load the actual resource, if not loaded yet. */ public void load(); /** + * Check if resource was successfully loaded. + * * @return true if already loaded */ public boolean isLoaded(); diff --git a/src/mightypork/rogue/texture/DeferredLoader.java b/src/mightypork/rogue/loading/DeferredLoader.java similarity index 84% rename from src/mightypork/rogue/texture/DeferredLoader.java rename to src/mightypork/rogue/loading/DeferredLoader.java index 2ede4e0..c957575 100644 --- a/src/mightypork/rogue/texture/DeferredLoader.java +++ b/src/mightypork/rogue/loading/DeferredLoader.java @@ -1,4 +1,4 @@ -package mightypork.rogue.texture; +package mightypork.rogue.loading; import java.util.concurrent.ExecutorService; @@ -6,7 +6,6 @@ import java.util.concurrent.Executors; import java.util.concurrent.LinkedBlockingQueue; import mightypork.rogue.AppAccess; -import mightypork.rogue.Deferred; import mightypork.rogue.bus.events.MainLoopTaskRequest; import mightypork.rogue.bus.events.ResourceLoadRequest; import mightypork.utils.control.interf.Destroyable; @@ -56,15 +55,19 @@ public class DeferredLoader extends Thread implements ResourceLoadRequest.Listen if (!def.isLoaded()) { + // skip nulls + if (def instanceof NullResource) continue; + // texture needs to be loaded in main thread, unfortunately. // -> delegate to MainLoop - if (def instanceof DeferredTexture) { + if (def instanceof MustLoadInMainThread) { + Log.f3(" Loading \"" + Log.str(def) + "\" in main thread (texture based)."); + app.bus().queue(new MainLoopTaskRequest(new Runnable() { @Override public void run() { - Log.f3(" Loading \"" + Log.str(def) + "\""); def.load(); } })); @@ -72,7 +75,7 @@ public class DeferredLoader extends Thread implements ResourceLoadRequest.Listen continue; } - Log.f3(" Loading \"" + Log.str(def) + "\""); + Log.f3(" Loading \"" + Log.str(def) + "\" asynchronously."); exs.submit(new Runnable() { diff --git a/src/mightypork/rogue/loading/DeferredResource.java b/src/mightypork/rogue/loading/DeferredResource.java new file mode 100644 index 0000000..3ef132c --- /dev/null +++ b/src/mightypork/rogue/loading/DeferredResource.java @@ -0,0 +1,127 @@ +package mightypork.rogue.loading; + + +import mightypork.utils.control.interf.Destroyable; +import mightypork.utils.logging.Log; + + +/** + * Deferred resource abstraction.
+ * Resources implementing {@link NullResource} will be treated as fake and not + * attempted to load. + * + * @author MightyPork + */ +public abstract class DeferredResource implements Deferred, Destroyable { + + private String resource; + private boolean loadFailed = false; + private boolean loadAttempted = false; + + + public DeferredResource(String resource) { + this.resource = resource; + } + + + @Override + public synchronized final void load() + { + + if (loadAttempted) return; + + loadAttempted = true; + loadFailed = false; + + if (isNull()) return; + try { + if (resource == null) throw new NullPointerException("Resource string cannot be null for non-null resource."); + + Log.f3("Loading resource " + this); + loadResource(resource); + Log.f3("Resource " + this + " loaded."); + } catch (Exception e) { + loadFailed = true; + Log.e("Failed to load resource \"" + resource + "\"", e); + } + } + + + @Override + public synchronized final boolean isLoaded() + { + if (isNull()) return false; + + 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() + { + if (isNull()) return false; + + if (isLoaded()) { + return true; + } else { + load(); + } + + return isLoaded(); + } + + + /** + * Load the resource. Called from load() - once only. + * + * @param resource the path / name of a resource + * @throws Exception when some problem prevented the resource from being + * loaded. + */ + protected abstract void loadResource(String resource) throws Exception; + + + @Override + public abstract void destroy(); + + + @Override + public String toString() + { + return Log.str(getClass()) + "(\"" + resource + "\")"; + } + + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + ((resource == null) ? 0 : resource.hashCode()); + return result; + } + + + @Override + public boolean equals(Object obj) + { + if (this == obj) return true; + if (obj == null) return false; + if (!(obj instanceof DeferredResource)) return false; + DeferredResource other = (DeferredResource) obj; + if (resource == null) { + if (other.resource != null) return false; + } else if (!resource.equals(other.resource)) return false; + return true; + } + + + private boolean isNull() + { + return this instanceof NullResource; + } +} diff --git a/src/mightypork/rogue/loading/MustLoadInMainThread.java b/src/mightypork/rogue/loading/MustLoadInMainThread.java new file mode 100644 index 0000000..59436a8 --- /dev/null +++ b/src/mightypork/rogue/loading/MustLoadInMainThread.java @@ -0,0 +1,12 @@ +package mightypork.rogue.loading; + + +/** + * Resource that is texture-based and therefore needs to be loaded in the main + * thread (ie. main loop). + * + * @author MightyPork + */ +public interface MustLoadInMainThread { + +} diff --git a/src/mightypork/rogue/loading/NullResource.java b/src/mightypork/rogue/loading/NullResource.java new file mode 100644 index 0000000..af48646 --- /dev/null +++ b/src/mightypork/rogue/loading/NullResource.java @@ -0,0 +1,12 @@ +package mightypork.rogue.loading; + + +/** + * Resource that is used as a placeholder instead of an actual resource; this + * resource should not be attempted to be loaded. + * + * @author MightyPork + */ +public interface NullResource { + +} diff --git a/src/mightypork/rogue/render/DisplaySystem.java b/src/mightypork/rogue/render/DisplaySystem.java index e72a286..faf8dfe 100644 --- a/src/mightypork/rogue/render/DisplaySystem.java +++ b/src/mightypork/rogue/render/DisplaySystem.java @@ -56,6 +56,9 @@ public class DisplaySystem extends Subsystem implements ConstraintContext { switchFullscreen(); Display.update(); } + + Render.init(); + } catch (LWJGLException e) { throw new RuntimeException("Could not initialize screen", e); } diff --git a/src/mightypork/rogue/render/Render.java b/src/mightypork/rogue/render/Render.java index 3456325..1e1085f 100644 --- a/src/mightypork/rogue/render/Render.java +++ b/src/mightypork/rogue/render/Render.java @@ -30,7 +30,25 @@ public class Render { private static final Coord AXIS_Y = new Coord(0, 1, 0); private static final Coord AXIS_Z = new Coord(0, 0, 1); - private static boolean inited = false; + + public static void init() + { + 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); + } /** @@ -67,24 +85,89 @@ public class Render { } + /** + * Scale + * + * @param factor vector of scaling factors + */ + public static void scale(Coord factor) + { + glScaled(factor.x, factor.y, factor.z); + } + + + /** + * Scale by X factor + * + * @param factor scaling factor + */ + public static void scaleX(double factor) + { + glScaled(factor, 1, 1); + } + + + /** + * Scale by Y factor + * + * @param factor scaling factor + */ + public static void scaleY(double factor) + { + glScaled(1, factor, 1); + } + + + /** + * Scale by Z factor + * + * @param factor scaling factor + */ + public static void scaleZ(double factor) + { + glScaled(1, 1, factor); + } + + + /** + * Rotate around X axis + * + * @param angle deg + */ public static void rotateX(double angle) { rotate(angle, AXIS_X); } + /** + * Rotate around Y axis + * + * @param angle deg + */ public static void rotateY(double angle) { rotate(angle, AXIS_Y); } + /** + * Rotate around Z axis + * + * @param angle deg + */ public static void rotateZ(double angle) { rotate(angle, AXIS_Z); } + /** + * Rotate + * + * @param angle rotate angle + * @param axis rotation axis + */ public static void rotate(double angle, Coord axis) { Coord vec = axis.norm(1); @@ -92,12 +175,18 @@ public class Render { } + /** + * Store GL state + */ public static void pushState() { SlickCallable.enterSafeBlock(); } + /** + * Restore Gl state + */ public static void popState() { SlickCallable.leaveSafeBlock(); @@ -113,15 +202,6 @@ public class Render { public synchronized static Texture loadTexture(String resourcePath) { - if (!inited) { - inited = true; - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - } - try { String ext = FileUtils.getExtension(resourcePath).toUpperCase(); @@ -148,14 +228,27 @@ public class Render { * Bind texture * * @param texture the texture + * @param linear use linear interpolation for scaling * @throws RuntimeException if not loaded yet */ - private static void bindTexture(Texture texture) throws RuntimeException + private static void bindTexture(Texture texture, boolean linear) throws RuntimeException { texture.bind(); } + /** + * Bind texture with linear interpolation + * + * @param texture the texture + * @throws RuntimeException if not loaded yet + */ + private static void bindTexture(Texture texture) throws RuntimeException + { + bindTexture(texture, false); + } + + /** * Unbind all */ @@ -211,7 +304,21 @@ public class Render { * @param quad rectangle (px) * @param uvs texture coords (0-1) */ - private static void quadUV(Rect quad, Rect uvs) + public static void quadUV(Rect quad, Rect uvs) + { + glBegin(GL_QUADS); + quadUV_nobound(quad, uvs); + glEnd(); + } + + + /** + * Draw quad without glBegin and glEnd. + * + * @param quad rectangle (px) + * @param uvs texture coords (0-1) + */ + public static void quadUV_nobound(Rect quad, Rect uvs) { double left = quad.xMin(); double bottom = quad.yMin(); @@ -224,7 +331,6 @@ public class Render { double ttop = uvs.yMax(); // quad with texture - glBegin(GL_QUADS); glTexCoord2d(tleft, ttop); glVertex2d(left, top); glTexCoord2d(tright, ttop); @@ -233,7 +339,6 @@ public class Render { glVertex2d(right, bottom); glTexCoord2d(tleft, tbottom); glVertex2d(left, bottom); - glEnd(); } diff --git a/src/mightypork/rogue/sound/DeferredAudio.java b/src/mightypork/rogue/sound/DeferredAudio.java index 239ddc2..b47aa99 100644 --- a/src/mightypork/rogue/sound/DeferredAudio.java +++ b/src/mightypork/rogue/sound/DeferredAudio.java @@ -1,10 +1,10 @@ package mightypork.rogue.sound; -import mightypork.rogue.Deferred; -import mightypork.utils.control.interf.Destroyable; +import java.io.IOException; + +import mightypork.rogue.loading.DeferredResource; import mightypork.utils.files.FileUtils; -import mightypork.utils.logging.Log; import mightypork.utils.math.coord.Coord; import org.newdawn.slick.openal.Audio; @@ -16,24 +16,24 @@ import org.newdawn.slick.openal.SoundStore; * * @author MightyPork */ -public class DeferredAudio implements Destroyable, Deferred { +public class DeferredAudio extends DeferredResource { private enum PlayMode { EFFECT, MUSIC; - }; + } + + /** Audio resource */ + private Audio backingAudio = null; - private Audio audio = null; + // last play options + private PlayMode mode = PlayMode.EFFECT; private double pauseLoopPosition = 0; private boolean looping = false; private boolean paused = false; - private PlayMode mode = PlayMode.EFFECT; private double lastPlayPitch = 1; private double lastPlayGain = 1; - private final String resourcePath; - private boolean loadFailed = false; - /** * Create deferred primitive audio player @@ -41,8 +41,7 @@ public class DeferredAudio implements Destroyable, Deferred { * @param resourceName resource to load when needed */ public DeferredAudio(String resourceName) { - this.audio = null; - this.resourcePath = resourceName; + super(resourceName); } @@ -54,7 +53,7 @@ public class DeferredAudio implements Destroyable, Deferred { if (!ensureLoaded()) return; if (isPlaying() && looping) { - pauseLoopPosition = audio.getPosition(); + pauseLoopPosition = backingAudio.getPosition(); stop(); paused = true; } @@ -73,74 +72,37 @@ public class DeferredAudio implements Destroyable, Deferred { int source = -1; if (looping && paused) { if (mode == PlayMode.MUSIC) { - source = audio.playAsMusic((float) lastPlayPitch, (float) lastPlayGain, true); + source = backingAudio.playAsMusic((float) lastPlayPitch, (float) lastPlayGain, true); } else { - source = audio.playAsSoundEffect((float) lastPlayPitch, (float) lastPlayGain, true); + source = backingAudio.playAsSoundEffect((float) lastPlayPitch, (float) lastPlayGain, true); } - audio.setPosition((float) pauseLoopPosition); + backingAudio.setPosition((float) pauseLoopPosition); paused = false; } return source; } - /** - * Check if resource is loaded - * - * @return resource is loaded - */ @Override - public synchronized boolean isLoaded() - { - return audio != null; - } - - - @Override - public synchronized void load() - { - ensureLoaded(); - } - - - /** - * Try to load if not loaded already - * - * @return is loaded - */ - protected synchronized boolean ensureLoaded() + protected void loadResource(String resource) throws IOException { - if (isLoaded()) return true; // already loaded - if (loadFailed || resourcePath == null) return false; + String ext = FileUtils.getExtension(resource); - Log.f3("Trying to load: " + resourcePath); - - loadFailed = false; - try { - String ext = FileUtils.getExtension(resourcePath); + if (ext.equalsIgnoreCase("ogg")) { + backingAudio = SoundStore.get().getOgg(resource); - // java 6 can't use String switch :( - if (ext.equalsIgnoreCase("ogg")) { - audio = SoundStore.get().getOgg(resourcePath); - } else if (ext.equalsIgnoreCase("wav")) { - audio = SoundStore.get().getWAV(resourcePath); - } else if (ext.equalsIgnoreCase("aif")) { - audio = SoundStore.get().getAIF(resourcePath); - } else if (ext.equalsIgnoreCase("mod")) { - audio = SoundStore.get().getMOD(resourcePath); - } else { - Log.e("Invalid audio file extension: " + resourcePath); - loadFailed = true; // don't try next time - } + } else if (ext.equalsIgnoreCase("wav")) { + backingAudio = SoundStore.get().getWAV(resource); - if (!loadFailed) Log.f3("Audio loaded: " + resourcePath); + } else if (ext.equalsIgnoreCase("aif")) { + backingAudio = SoundStore.get().getAIF(resource); - } catch (Exception e) { - Log.e("Could not load " + resourcePath, e); - loadFailed = true; // don't try next time + } else if (ext.equalsIgnoreCase("mod")) { + backingAudio = SoundStore.get().getMOD(resource); + + } else { + throw new RuntimeException("Invalid audio file extension."); } - - return isLoaded(); } @@ -148,7 +110,7 @@ public class DeferredAudio implements Destroyable, Deferred { { if (!isLoaded()) return; - audio.stop(); + backingAudio.stop(); paused = false; } @@ -157,7 +119,7 @@ public class DeferredAudio implements Destroyable, Deferred { { if (!isLoaded()) return false; - return audio.isPlaying(); + return backingAudio.isPlaying(); } @@ -165,7 +127,7 @@ public class DeferredAudio implements Destroyable, Deferred { { if (!isLoaded()) return false; - return audio.isPaused(); + return backingAudio.isPaused(); } @@ -218,7 +180,7 @@ public class DeferredAudio implements Destroyable, Deferred { this.lastPlayGain = gain; looping = loop; mode = PlayMode.EFFECT; - return audio.playAsSoundEffect((float) pitch, (float) gain, loop, (float) x, (float) y, (float) z); + return backingAudio.playAsSoundEffect((float) pitch, (float) gain, loop, (float) x, (float) y, (float) z); } @@ -256,7 +218,7 @@ public class DeferredAudio implements Destroyable, Deferred { this.lastPlayGain = (float) gain; looping = loop; mode = PlayMode.MUSIC; - return audio.playAsMusic((float) pitch, (float) gain, loop); + return backingAudio.playAsMusic((float) pitch, (float) gain, loop); } @@ -265,41 +227,8 @@ public class DeferredAudio implements Destroyable, Deferred { { if (!isLoaded()) return; - audio.release(); - audio = null; - } - - - @Override - public int hashCode() - { - final int prime = 31; - int result = 1; - result = prime * result + ((resourcePath == null) ? 0 : resourcePath.hashCode()); - return result; - } - - - @Override - public boolean equals(Object obj) - { - if (this == obj) return true; - if (obj == null) return false; - if (!(obj instanceof DeferredAudio)) return false; - DeferredAudio other = (DeferredAudio) obj; - if (resourcePath == null) { - if (other.resourcePath != null) return false; - } else if (!resourcePath.equals(other.resourcePath)) { - return false; - } - return true; - } - - - @Override - public String toString() - { - return "Audio(\"" + resourcePath + "\")"; + backingAudio.release(); + backingAudio = null; } } diff --git a/src/mightypork/rogue/sound/JointVolume.java b/src/mightypork/rogue/sound/JointVolume.java index 7fda073..7e278fd 100644 --- a/src/mightypork/rogue/sound/JointVolume.java +++ b/src/mightypork/rogue/sound/JointVolume.java @@ -6,7 +6,7 @@ import mightypork.utils.objects.Mutable; /** - * Volume multiplex + * Volume combined of multiple volumes, combining them (multiplication). * * @author MightyPork */ diff --git a/src/mightypork/rogue/sound/NullAudio.java b/src/mightypork/rogue/sound/NullAudio.java index a5df14b..eecaba7 100644 --- a/src/mightypork/rogue/sound/NullAudio.java +++ b/src/mightypork/rogue/sound/NullAudio.java @@ -1,30 +1,18 @@ package mightypork.rogue.sound; -public class NullAudio extends DeferredAudio { +import mightypork.rogue.loading.NullResource; + + +/** + * Placeholder for cases where no matching audio is found and + * {@link NullPointerException} has to be avoided. + * + * @author MightyPork + */ +public class NullAudio extends DeferredAudio implements NullResource { public NullAudio() { - super(""); - } - - - @Override - public void load() - { - } - - - @Override - public boolean isLoaded() - { - return true; - } - - - @Override - protected boolean ensureLoaded() - { - return false; + super(null); } - } diff --git a/src/mightypork/rogue/tasks/TaskTakeScreenshot.java b/src/mightypork/rogue/tasks/TaskTakeScreenshot.java index fd6e44c..f8bd777 100644 --- a/src/mightypork/rogue/tasks/TaskTakeScreenshot.java +++ b/src/mightypork/rogue/tasks/TaskTakeScreenshot.java @@ -67,7 +67,7 @@ public class TaskTakeScreenshot implements Runnable { } - private String getUniqueScreenshotName() + private static String getUniqueScreenshotName() { DateFormat df = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss"); return df.format(new Date()); diff --git a/src/mightypork/rogue/texture/DeferredTexture.java b/src/mightypork/rogue/texture/DeferredTexture.java index 4f68634..84c0586 100644 --- a/src/mightypork/rogue/texture/DeferredTexture.java +++ b/src/mightypork/rogue/texture/DeferredTexture.java @@ -1,21 +1,30 @@ package mightypork.rogue.texture; -import mightypork.rogue.Deferred; +import mightypork.rogue.loading.DeferredResource; +import mightypork.rogue.loading.MustLoadInMainThread; import mightypork.rogue.render.Render; import mightypork.utils.math.coord.Rect; +import org.lwjgl.opengl.GL11; import org.newdawn.slick.opengl.Texture; -public class DeferredTexture implements Texture, Deferred { +/** + * Deferred texture + * + * @author MightyPork + */ +public class DeferredTexture extends DeferredResource implements FilteredTexture, MustLoadInMainThread { private Texture backingTexture; - private final String resourcePath; + private Filter filter_min = Filter.LINEAR; + private Filter filter_mag = Filter.LINEAR; + private Wrap wrap = Wrap.CLAMP; public DeferredTexture(String resourcePath) { - this.resourcePath = resourcePath; + super(resourcePath); } @@ -26,49 +35,52 @@ public class DeferredTexture implements Texture, Deferred { @Override - public synchronized void load() + protected void loadResource(String path) { - if (!isLoaded()) { - backingTexture = Render.loadTexture(resourcePath); - } - } - - - @Override - public boolean isLoaded() - { - return backingTexture != null; + backingTexture = Render.loadTexture(path); } @Override public boolean hasAlpha() { - load(); + if (!ensureLoaded()) return false; + return backingTexture.hasAlpha(); } - @Override - public String getTextureRef() + public void bindRaw() { - load(); - return backingTexture.getTextureRef(); + if (!ensureLoaded()) return; + + backingTexture.bind(); } @Override public void bind() { - load(); + if (!ensureLoaded()) return; + backingTexture.bind(); + + GL11.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_TEXTURE_ENV_MODE, GL11.GL_MODULATE); + + GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, wrap.num); + GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, wrap.num); + + GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, filter_min.num); + GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, filter_mag.num); + } @Override public int getImageHeight() { - load(); + if (!ensureLoaded()) return 0; + return backingTexture.getImageHeight(); } @@ -76,15 +88,26 @@ public class DeferredTexture implements Texture, Deferred { @Override public int getImageWidth() { - load(); + if (!ensureLoaded()) return 0; + return backingTexture.getImageWidth(); } + @Override + public String getTextureRef() + { + if (!ensureLoaded()) return null; + + return backingTexture.getTextureRef(); + } + + @Override public float getHeight() { - load(); + if (!ensureLoaded()) return 0; + return backingTexture.getHeight(); } @@ -92,7 +115,8 @@ public class DeferredTexture implements Texture, Deferred { @Override public float getWidth() { - load(); + if (!ensureLoaded()) return 0; + return backingTexture.getWidth(); } @@ -100,7 +124,8 @@ public class DeferredTexture implements Texture, Deferred { @Override public int getTextureHeight() { - load(); + if (!ensureLoaded()) return 0; + return backingTexture.getTextureHeight(); } @@ -108,7 +133,8 @@ public class DeferredTexture implements Texture, Deferred { @Override public int getTextureWidth() { - load(); + if (!ensureLoaded()) return 0; + return backingTexture.getTextureWidth(); } @@ -116,7 +142,8 @@ public class DeferredTexture implements Texture, Deferred { @Override public void release() { - if (backingTexture == null) return; + if (!isLoaded()) return; + backingTexture.release(); } @@ -124,7 +151,8 @@ public class DeferredTexture implements Texture, Deferred { @Override public int getTextureID() { - load(); + if (!ensureLoaded()) return -1; + return backingTexture.getTextureID(); } @@ -132,7 +160,8 @@ public class DeferredTexture implements Texture, Deferred { @Override public byte[] getTextureData() { - load(); + if (!ensureLoaded()) return null; + return backingTexture.getTextureData(); } @@ -140,15 +169,38 @@ public class DeferredTexture implements Texture, Deferred { @Override public void setTextureFilter(int textureFilter) { - load(); + if (!ensureLoaded()) return; + backingTexture.setTextureFilter(textureFilter); } @Override - public String toString() + public void destroy() + { + release(); + } + + + @Override + public void setFilter(Filter filterMin, Filter filterMag) + { + this.filter_min = filterMin; + this.filter_mag = filterMag; + } + + + @Override + public void setWrap(Wrap wrapping) + { + this.wrap = wrapping; + } + + + @Override + public void setFilter(Filter filter) { - return "Texture(\"" + resourcePath + "\")"; + setFilter(filter, filter); } } diff --git a/src/mightypork/rogue/texture/FilteredTexture.java b/src/mightypork/rogue/texture/FilteredTexture.java new file mode 100644 index 0000000..bf01294 --- /dev/null +++ b/src/mightypork/rogue/texture/FilteredTexture.java @@ -0,0 +1,56 @@ +package mightypork.rogue.texture; + + +import org.lwjgl.opengl.GL11; +import org.newdawn.slick.opengl.Texture; + + +public interface FilteredTexture extends Texture { + + public static enum Filter + { + LINEAR(GL11.GL_LINEAR), NEAREST(GL11.GL_NEAREST); + + public final int num; + + + private Filter(int gl) { + this.num = gl; + } + } + + public static enum Wrap + { + CLAMP(GL11.GL_CLAMP), REPEAT(GL11.GL_REPEAT); + + public final int num; + + + private Wrap(int gl) { + this.num = gl; + } + } + + + /** + * Set filter for scaling + * + * @param filterMin downscale filter + * @param filterMag upscale filter + */ + public void setFilter(Filter filterMin, Filter filterMag); + + + /** + * Set filter for scaling (both up and down) + * + * @param filter filter + */ + public void setFilter(Filter filter); + + + /** + * @param wrapping wrap mode + */ + public void setWrap(Wrap wrapping); +} diff --git a/src/mightypork/rogue/texture/TextureBank.java b/src/mightypork/rogue/texture/TextureBank.java index 8fa5539..4cf7dbb 100644 --- a/src/mightypork/rogue/texture/TextureBank.java +++ b/src/mightypork/rogue/texture/TextureBank.java @@ -6,6 +6,8 @@ import java.util.HashMap; import mightypork.rogue.AppAccess; import mightypork.rogue.AppAdapter; import mightypork.rogue.bus.events.ResourceLoadRequest; +import mightypork.rogue.texture.FilteredTexture.Filter; +import mightypork.rogue.texture.FilteredTexture.Wrap; import mightypork.utils.math.coord.Rect; import org.newdawn.slick.opengl.Texture; @@ -30,14 +32,32 @@ public class TextureBank extends AppAdapter { /** - * Load a {@link Texture} from resource + * Load a {@link Texture} from resource, with filters LINEAR and wrap CLAMP * * @param key texture key * @param resourcePath texture resource path */ public void loadTexture(String key, String resourcePath) + { + loadTexture(key, resourcePath, Filter.LINEAR, Filter.NEAREST, Wrap.CLAMP); + } + + + /** + * Load a {@link Texture} from resource + * + * @param key texture key + * @param resourcePath texture resource path + * @param filter_min min filter (when rendered smaller) + * @param filter_mag mag filter (when rendered larger) + * @param wrap texture wrapping + */ + public void loadTexture(String key, String resourcePath, Filter filter_min, Filter filter_mag, Wrap wrap) { DeferredTexture tx = new DeferredTexture(resourcePath); + tx.setFilter(filter_min, filter_mag); + tx.setWrap(wrap); + bus().queue(new ResourceLoadRequest(tx)); textures.put(key, tx); diff --git a/src/mightypork/utils/files/FileTreeDiff.java b/src/mightypork/utils/files/FileTreeDiff.java index ca14bf4..9529e6c 100644 --- a/src/mightypork/utils/files/FileTreeDiff.java +++ b/src/mightypork/utils/files/FileTreeDiff.java @@ -67,7 +67,7 @@ public class FileTreeDiff { private void calcChecksum() throws NotEqualException { - FileInputStream in1, in2; + FileInputStream in1 = null, in2 = null; CheckedInputStream cin1 = null, cin2 = null; for (Tuple pair : compared) { @@ -92,18 +92,34 @@ public class FileTreeDiff { if (read1 == -1) break; } - } catch (IOException e) {} finally { + } catch (IOException e) { + // ignore + } finally { + try { if (cin1 != null) cin1.close(); - } catch (IOException e) { + } catch (Exception e) { // ignore } try { - if (cin1 != null) cin1.close(); - } catch (IOException e) { + if (cin2 != null) cin2.close(); + } catch (Exception e) { + // ignore + } + + try { + if (in1 != null) in1.close(); + } catch (Exception e) { // ignore } + + try { + if (in2 != null) in2.close(); + } catch (Exception e) { + // ignore + } + } } } diff --git a/src/mightypork/utils/files/FileUtils.java b/src/mightypork/utils/files/FileUtils.java index c6555b0..e5f2325 100644 --- a/src/mightypork/utils/files/FileUtils.java +++ b/src/mightypork/utils/files/FileUtils.java @@ -344,7 +344,18 @@ public class FileUtils { public static InputStream getResource(String path) { - return FileUtils.class.getResourceAsStream(path); + InputStream in = FileUtils.class.getResourceAsStream(path); + + if (in != null) return in; + + try { + return new FileInputStream(new File(".", path)); + } catch (FileNotFoundException e) { + // error + Log.w("Could not open resource stream: " + path); + return null; + } + } diff --git a/src/mightypork/utils/files/PropertyManager.java b/src/mightypork/utils/files/PropertyManager.java index c6c2ef8..aed3e44 100644 --- a/src/mightypork/utils/files/PropertyManager.java +++ b/src/mightypork/utils/files/PropertyManager.java @@ -115,7 +115,7 @@ public class PropertyManager { } - private String saveConvert(String theString, boolean escapeSpace, boolean escapeUnicode) + private static String saveConvert(String theString, boolean escapeSpace, boolean escapeUnicode) { int len = theString.length(); int bufLen = len * 2; diff --git a/src/mightypork/utils/files/ZipBuilder.java b/src/mightypork/utils/files/ZipBuilder.java index 249d74d..4ef83f4 100644 --- a/src/mightypork/utils/files/ZipBuilder.java +++ b/src/mightypork/utils/files/ZipBuilder.java @@ -101,7 +101,7 @@ public class ZipBuilder { * @param path original path * @return normalized path */ - private String preparePath(String path) + private static String preparePath(String path) { path = path.replace("\\", "/"); diff --git a/src/mightypork/utils/files/ion/AbstractIonList.java b/src/mightypork/utils/files/ion/AbstractIonList.java index c1149b1..a1f7ebe 100644 --- a/src/mightypork/utils/files/ion/AbstractIonList.java +++ b/src/mightypork/utils/files/ion/AbstractIonList.java @@ -20,7 +20,7 @@ public abstract class AbstractIonList extends ArrayList implements Ionizab { try { while (true) { - byte b = StreamUtils.readByte(in); + byte b = BinaryUtils.readByte(in); if (b == IonMarks.ENTRY) { T value = (T) Ion.readObject(in); @@ -44,10 +44,10 @@ public abstract class AbstractIonList extends ArrayList implements Ionizab try { for (T entry : this) { if (entry instanceof IonizableOptional && !((IonizableOptional) entry).ionShouldSave()) continue; - StreamUtils.writeByte(out, IonMarks.ENTRY); + BinaryUtils.writeByte(out, IonMarks.ENTRY); Ion.writeObject(out, entry); } - StreamUtils.writeByte(out, IonMarks.END); + BinaryUtils.writeByte(out, IonMarks.END); ionWriteCustomData(out); } catch (IOException e) { throw new IonException("Error reading ion map", e); diff --git a/src/mightypork/utils/files/ion/AbstractIonMap.java b/src/mightypork/utils/files/ion/AbstractIonMap.java index a775a63..7cdea7e 100644 --- a/src/mightypork/utils/files/ion/AbstractIonMap.java +++ b/src/mightypork/utils/files/ion/AbstractIonMap.java @@ -34,9 +34,9 @@ public abstract class AbstractIonMap extends LinkedHashMap impleme { try { while (true) { - byte b = StreamUtils.readByte(in); + byte b = BinaryUtils.readByte(in); if (b == IonMarks.ENTRY) { - String key = StreamUtils.readStringBytes(in); + String key = BinaryUtils.readString(in); V value = (V) Ion.readObject(in); put(key, value); @@ -59,11 +59,11 @@ public abstract class AbstractIonMap extends LinkedHashMap impleme { try { for (java.util.Map.Entry entry : entrySet()) { - StreamUtils.writeByte(out, IonMarks.ENTRY); - StreamUtils.writeStringBytes(out, entry.getKey()); + BinaryUtils.writeByte(out, IonMarks.ENTRY); + BinaryUtils.writeString(out, entry.getKey()); Ion.writeObject(out, entry.getValue()); } - StreamUtils.writeByte(out, IonMarks.END); + BinaryUtils.writeByte(out, IonMarks.END); ionWriteCustomData(out); } catch (IOException e) { throw new IonException("Error reading ion map", e); diff --git a/src/mightypork/utils/files/ion/StreamUtils.java b/src/mightypork/utils/files/ion/BinaryUtils.java similarity index 75% rename from src/mightypork/utils/files/ion/StreamUtils.java rename to src/mightypork/utils/files/ion/BinaryUtils.java index 0f64691..380b646 100644 --- a/src/mightypork/utils/files/ion/StreamUtils.java +++ b/src/mightypork/utils/files/ion/BinaryUtils.java @@ -12,7 +12,7 @@ import java.nio.ByteBuffer; * * @author MightyPork */ -public class StreamUtils { +public class BinaryUtils { private static ByteBuffer bi = ByteBuffer.allocate(Integer.SIZE / 8); private static ByteBuffer bd = ByteBuffer.allocate(Double.SIZE / 8); @@ -31,19 +31,19 @@ public class StreamUtils { // CONVERSIONS - private static byte[] convBool(boolean bool) + public static byte[] getBytesBool(boolean bool) { return new byte[] { (byte) (bool ? 1 : 0) }; } - private static byte[] convByte(byte num) + public static byte[] getBytesByte(byte num) { return new byte[] { num }; } - private static byte[] convChar(char num) + public static byte[] getBytesChar(char num) { bc.clear(); bc.putChar(num); @@ -51,7 +51,7 @@ public class StreamUtils { } - private static byte[] convShort(short num) + public static byte[] getBytesShort(short num) { bs.clear(); bs.putShort(num); @@ -59,7 +59,7 @@ public class StreamUtils { } - private static byte[] convInt(int num) + public static byte[] getBytesInt(int num) { bi.clear(); bi.putInt(num); @@ -67,7 +67,7 @@ public class StreamUtils { } - private static byte[] convLong(long num) + public static byte[] getBytesLong(long num) { bl.clear(); bl.putLong(num); @@ -75,7 +75,7 @@ public class StreamUtils { } - private static byte[] convFloat(float num) + public static byte[] getBytesFloat(float num) { bf.clear(); bf.putFloat(num); @@ -83,7 +83,7 @@ public class StreamUtils { } - private static byte[] convDouble(double num) + public static byte[] getBytesDouble(double num) { bd.clear(); bd.putDouble(num); @@ -91,7 +91,7 @@ public class StreamUtils { } - private static byte[] convString(String str) + public static byte[] getBytesString(String str) { char[] chars = str.toCharArray(); @@ -106,76 +106,57 @@ public class StreamUtils { } - private static byte[] convString_b(String str) - { - char[] chars = str.toCharArray(); - ByteBuffer bstr = ByteBuffer.allocate((Byte.SIZE / 8) * chars.length + 1); - for (char c : chars) { - bstr.put((byte) c); - } - bstr.put((byte) 0); - - return bstr.array(); - } - - public static void writeBoolean(OutputStream out, boolean num) throws IOException { - out.write(convBool(num)); + out.write(getBytesBool(num)); } public static void writeByte(OutputStream out, byte num) throws IOException { - out.write(convByte(num)); + out.write(getBytesByte(num)); } public static void writeChar(OutputStream out, char num) throws IOException { - out.write(convChar(num)); + out.write(getBytesChar(num)); } public static void writeShort(OutputStream out, short num) throws IOException { - out.write(convShort(num)); + out.write(getBytesShort(num)); } public static void writeInt(OutputStream out, int num) throws IOException { - out.write(convInt(num)); + out.write(getBytesInt(num)); } public static void writeLong(OutputStream out, long num) throws IOException { - out.write(convLong(num)); + out.write(getBytesLong(num)); } public static void writeFloat(OutputStream out, float num) throws IOException { - out.write(convFloat(num)); + out.write(getBytesFloat(num)); } public static void writeDouble(OutputStream out, double num) throws IOException { - out.write(convDouble(num)); + out.write(getBytesDouble(num)); } public static void writeString(OutputStream out, String str) throws IOException { - out.write(convString(str)); - } - - - public static void writeStringBytes(OutputStream out, String str) throws IOException - { - out.write(convString_b(str)); + out.write(getBytesString(str)); } @@ -250,16 +231,4 @@ public class StreamUtils { } return s; } - - - public static String readStringBytes(InputStream in) throws IOException - { - String s = ""; - byte b; - while ((b = readByte(in)) > 0) { - s += (char) b; - } - return s; - } - } diff --git a/src/mightypork/utils/files/ion/Ion.java b/src/mightypork/utils/files/ion/Ion.java index a7997c0..a758af2 100644 --- a/src/mightypork/utils/files/ion/Ion.java +++ b/src/mightypork/utils/files/ion/Ion.java @@ -191,23 +191,23 @@ public class Ion { switch (b) { case IonMarks.BOOLEAN: - return StreamUtils.readBoolean(in); + return BinaryUtils.readBoolean(in); case IonMarks.BYTE: - return StreamUtils.readByte(in); + return BinaryUtils.readByte(in); case IonMarks.CHAR: - return StreamUtils.readChar(in); + return BinaryUtils.readChar(in); case IonMarks.SHORT: - return StreamUtils.readShort(in); + return BinaryUtils.readShort(in); case IonMarks.INT: - return StreamUtils.readInt(in); + return BinaryUtils.readInt(in); case IonMarks.LONG: - return StreamUtils.readLong(in); + return BinaryUtils.readLong(in); case IonMarks.FLOAT: - return StreamUtils.readFloat(in); + return BinaryUtils.readFloat(in); case IonMarks.DOUBLE: - return StreamUtils.readDouble(in); + return BinaryUtils.readDouble(in); case IonMarks.STRING: - String s = StreamUtils.readString(in); + String s = BinaryUtils.readString(in); return s; default: throw new IonException("Invalid Ion mark " + Integer.toHexString(bi)); @@ -236,55 +236,55 @@ public class Ion { if (obj instanceof Boolean) { out.write(IonMarks.BOOLEAN); - StreamUtils.writeBoolean(out, (Boolean) obj); + BinaryUtils.writeBoolean(out, (Boolean) obj); return; } if (obj instanceof Byte) { out.write(IonMarks.BYTE); - StreamUtils.writeByte(out, (Byte) obj); + BinaryUtils.writeByte(out, (Byte) obj); return; } if (obj instanceof Character) { out.write(IonMarks.CHAR); - StreamUtils.writeChar(out, (Character) obj); + BinaryUtils.writeChar(out, (Character) obj); return; } if (obj instanceof Short) { out.write(IonMarks.SHORT); - StreamUtils.writeShort(out, (Short) obj); + BinaryUtils.writeShort(out, (Short) obj); return; } if (obj instanceof Integer) { out.write(IonMarks.INT); - StreamUtils.writeInt(out, (Integer) obj); + BinaryUtils.writeInt(out, (Integer) obj); return; } if (obj instanceof Long) { out.write(IonMarks.LONG); - StreamUtils.writeLong(out, (Long) obj); + BinaryUtils.writeLong(out, (Long) obj); return; } if (obj instanceof Float) { out.write(IonMarks.FLOAT); - StreamUtils.writeFloat(out, (Float) obj); + BinaryUtils.writeFloat(out, (Float) obj); return; } if (obj instanceof Double) { out.write(IonMarks.DOUBLE); - StreamUtils.writeDouble(out, (Double) obj); + BinaryUtils.writeDouble(out, (Double) obj); return; } if (obj instanceof String) { out.write(IonMarks.STRING); - StreamUtils.writeString(out, (String) obj); + BinaryUtils.writeString(out, (String) obj); return; } diff --git a/src/mightypork/utils/files/ion/IonList.java b/src/mightypork/utils/files/ion/IonList.java index 36026a6..bcc1d7e 100644 --- a/src/mightypork/utils/files/ion/IonList.java +++ b/src/mightypork/utils/files/ion/IonList.java @@ -6,7 +6,7 @@ package mightypork.utils.files.ion; * * @author MightyPork */ -public class IonList extends AbstractIonList implements Ionizable { +public class IonList extends AbstractIonList { public Ionizable getIonizable(int index) throws IonException { @@ -70,61 +70,61 @@ public class IonList extends AbstractIonList implements Ionizable { public void addIonizable(Ionizable o) throws IonException { - addCheckNull(o); + assertNotNull(o); } public void addBoolean(boolean o) throws IonException { - addCheckNull(o); + assertNotNull(o); } public void addByte(byte o) throws IonException { - addCheckNull(o); + assertNotNull(o); } public void addChar(char o) throws IonException { - addCheckNull(o); + assertNotNull(o); } public void addShort(short o) throws IonException { - addCheckNull(o); + assertNotNull(o); } public void addInt(int o) throws IonException { - addCheckNull(o); + assertNotNull(o); } public void addLong(long o) throws IonException { - addCheckNull(o); + assertNotNull(o); } public void addFloat(float o) throws IonException { - addCheckNull(o); + assertNotNull(o); } public void addDouble(double o) throws IonException { - addCheckNull(o); + assertNotNull(o); } public void addString(String o) throws IonException { - addCheckNull(o); + assertNotNull(o); } @@ -142,7 +142,7 @@ public class IonList extends AbstractIonList implements Ionizable { } - private void addCheckNull(Object o) throws IonException + private static void assertNotNull(Object o) throws IonException { if (o == null) throw new IonException("Cannot store null"); } diff --git a/src/mightypork/utils/files/ion/IonMap.java b/src/mightypork/utils/files/ion/IonMap.java index 49c6ad9..2cfaf9d 100644 --- a/src/mightypork/utils/files/ion/IonMap.java +++ b/src/mightypork/utils/files/ion/IonMap.java @@ -6,7 +6,7 @@ package mightypork.utils.files.ion; * * @author MightyPork */ -public class IonMap extends AbstractIonMap implements Ionizable { +public class IonMap extends AbstractIonMap { public boolean getBoolean(String key) { diff --git a/src/mightypork/utils/logging/LogInstance.java b/src/mightypork/utils/logging/LogInstance.java index a7ad2df..c637e84 100644 --- a/src/mightypork/utils/logging/LogInstance.java +++ b/src/mightypork/utils/logging/LogInstance.java @@ -111,7 +111,7 @@ public class LogInstance { String cntStr = ""; File f2; - for (int cnt = 0; (f2 = new File(dir, fbase + cntStr + suff)).exists(); cntStr = "_" + (++cnt)); + for (int cnt = 0; (f2 = new File(dir, fbase + cntStr + suff)).exists(); cntStr = "_" + (++cnt)) {} f.renameTo(f2); } @@ -292,7 +292,7 @@ public class LogInstance { * @param t * @return trace */ - private String getStackTrace(Throwable t) + private static String getStackTrace(Throwable t) { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw, true); diff --git a/src/mightypork/utils/math/constraints/Constraint.java b/src/mightypork/utils/math/constraints/Constraint.java index da1f652..d0bc787 100644 --- a/src/mightypork/utils/math/constraints/Constraint.java +++ b/src/mightypork/utils/math/constraints/Constraint.java @@ -53,6 +53,6 @@ public abstract class Constraint implements SettableContext { { if (context == null) return Coord.zero(); - return context.getRect().getSize(); + return context.getRect().size(); } } diff --git a/src/mightypork/utils/math/constraints/ConstraintFactory.java b/src/mightypork/utils/math/constraints/ConstraintFactory.java index 73773e6..b8aa636 100644 --- a/src/mightypork/utils/math/constraints/ConstraintFactory.java +++ b/src/mightypork/utils/math/constraints/ConstraintFactory.java @@ -242,7 +242,7 @@ public class ConstraintFactory { @Override public Rect getRect() { - double height = getContext().getRect().getSize().y; + double height = getContext().getRect().size().y; double perRow = height / rows; return Rect.fromSize(getOrigin().add(0, perRow * index), getSize().setY(perRow)); @@ -258,7 +258,7 @@ public class ConstraintFactory { @Override public Rect getRect() { - double width = getContext().getRect().getSize().x; + double width = getContext().getRect().size().x; double perCol = width / columns; return Rect.fromSize(getOrigin().add(perCol * index, 0), getSize().setX(perCol)); diff --git a/src/mightypork/utils/math/coord/Coord.java b/src/mightypork/utils/math/coord/Coord.java index 25ef5b7..33ffd17 100644 --- a/src/mightypork/utils/math/coord/Coord.java +++ b/src/mightypork/utils/math/coord/Coord.java @@ -55,6 +55,16 @@ public class Coord { } + /** + * Create a coord with all three coordinates the same + * + * @param d coord value + */ + public Coord(Number d) { + setTo(d, d, d); + } + + /** * Create 2D coord * @@ -666,6 +676,15 @@ public class Coord { } + /** + * @return X as float + */ + public float xf() + { + return (float) x; + } + + /** * @return X as int */ @@ -684,6 +703,15 @@ public class Coord { } + /** + * @return Y as float + */ + public float yf() + { + return (float) y; + } + + /** * @return Y as int */ @@ -702,6 +730,15 @@ public class Coord { } + /** + * @return Z as float + */ + public float zf() + { + return (float) z; + } + + /** * @return Z as int */ @@ -897,7 +934,7 @@ public class Coord { */ public static Coord zero() { - return new Coord(0, 0, 0); + return new Coord(0); } @@ -908,7 +945,7 @@ public class Coord { */ public static Coord one() { - return new Coord(1, 1, 1); + return new Coord(1); } diff --git a/src/mightypork/utils/math/coord/Rect.java b/src/mightypork/utils/math/coord/Rect.java index 9199cff..185e67a 100644 --- a/src/mightypork/utils/math/coord/Rect.java +++ b/src/mightypork/utils/math/coord/Rect.java @@ -46,7 +46,7 @@ public class Rect { * @param size rect size * @return the rect */ - public static Rect fromSize(int x, int y, Coord size) + public static Rect fromSize(double x, double y, Coord size) { return fromSize(x, y, size.x, size.y); } @@ -387,9 +387,9 @@ public class Rect { * * @return coord of width,height */ - public Coord getSize() + public Coord size() { - return new Coord(Math.abs(min.x - max.x), Math.abs(min.y - max.y)); + return new Coord(max.x - min.x, max.y - min.y); } @@ -804,4 +804,16 @@ public class Rect { { return max.y; } + + + public double height() + { + return max.y - min.y; + } + + + public double width() + { + return max.x - min.x; + } }