javadoc, cleanup, added font system

v5stable
Ondřej Hruška 10 years ago
parent f5929f23b1
commit da67300522
  1. 11
      src/mightypork/rogue/App.java
  2. 29
      src/mightypork/rogue/Res.java
  3. 4
      src/mightypork/rogue/bus/Subsystem.java
  4. 2
      src/mightypork/rogue/bus/events/ResourceLoadRequest.java
  5. 20
      src/mightypork/rogue/fonts/Align.java
  6. 216
      src/mightypork/rogue/fonts/DeferredFont.java
  7. 61
      src/mightypork/rogue/fonts/DeferredFontNative.java
  8. 75
      src/mightypork/rogue/fonts/FontBank.java
  9. 320
      src/mightypork/rogue/fonts/FontManager.java
  10. 60
      src/mightypork/rogue/fonts/Fonts.java
  11. 59
      src/mightypork/rogue/fonts/GLFont.java
  12. 24
      src/mightypork/rogue/fonts/Glyphs.java
  13. 639
      src/mightypork/rogue/fonts/LoadedFont.java
  14. 56
      src/mightypork/rogue/fonts/NullFont.java
  15. 130
      src/mightypork/rogue/fonts/SlickFont.java
  16. 51
      src/mightypork/rogue/gui/Screen.java
  17. 61
      src/mightypork/rogue/gui/screens/test_font/ScreenTestFont.java
  18. 6
      src/mightypork/rogue/input/InputSystem.java
  19. 6
      src/mightypork/rogue/loading/Deferred.java
  20. 13
      src/mightypork/rogue/loading/DeferredLoader.java
  21. 127
      src/mightypork/rogue/loading/DeferredResource.java
  22. 12
      src/mightypork/rogue/loading/MustLoadInMainThread.java
  23. 12
      src/mightypork/rogue/loading/NullResource.java
  24. 3
      src/mightypork/rogue/render/DisplaySystem.java
  25. 133
      src/mightypork/rogue/render/Render.java
  26. 141
      src/mightypork/rogue/sound/DeferredAudio.java
  27. 2
      src/mightypork/rogue/sound/JointVolume.java
  28. 34
      src/mightypork/rogue/sound/NullAudio.java
  29. 2
      src/mightypork/rogue/tasks/TaskTakeScreenshot.java
  30. 118
      src/mightypork/rogue/texture/DeferredTexture.java
  31. 56
      src/mightypork/rogue/texture/FilteredTexture.java
  32. 22
      src/mightypork/rogue/texture/TextureBank.java
  33. 26
      src/mightypork/utils/files/FileTreeDiff.java
  34. 13
      src/mightypork/utils/files/FileUtils.java
  35. 2
      src/mightypork/utils/files/PropertyManager.java
  36. 2
      src/mightypork/utils/files/ZipBuilder.java
  37. 6
      src/mightypork/utils/files/ion/AbstractIonList.java
  38. 10
      src/mightypork/utils/files/ion/AbstractIonMap.java
  39. 69
      src/mightypork/utils/files/ion/BinaryUtils.java
  40. 36
      src/mightypork/utils/files/ion/Ion.java
  41. 24
      src/mightypork/utils/files/ion/IonList.java
  42. 2
      src/mightypork/utils/files/ion/IonMap.java
  43. 4
      src/mightypork/utils/logging/LogInstance.java
  44. 2
      src/mightypork/utils/math/constraints/Constraint.java
  45. 4
      src/mightypork/utils/math/constraints/ConstraintFactory.java
  46. 41
      src/mightypork/utils/math/coord/Coord.java
  47. 18
      src/mightypork/utils/math/coord/Rect.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();

@ -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);
}
}

@ -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);

@ -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;

@ -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;
}

@ -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;
}
}

@ -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);
}
}

@ -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<String, GLFont> fonts = new HashMap<String, GLFont>();
/**
* 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;
}
}

@ -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<Style, String> {
}
/**
* Table of font files. name {style:file,style:file,style:file...}
*/
private static HashMap<String, FontFamily> fontFiles = new HashMap<String, FontFamily>();
/**
* 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.<br>
* 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.<br>
* 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;
}
}

@ -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);
}
}

@ -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);
}

@ -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;
}

@ -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<Character, CharStorageEntry> chars = new HashMap<Character, CharStorageEntry>(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<LoadedGlyph> glyphs = new ArrayList<LoadedGlyph>();
List<Character> loaded = new ArrayList<Character>();
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();
}
}

@ -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;
}
}

@ -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);
}
}

@ -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);

@ -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";
}
}

@ -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();

@ -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();

@ -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("<DEFERRED> Loading \"" + Log.str(def) + "\" in main thread (texture based).");
app.bus().queue(new MainLoopTaskRequest(new Runnable() {
@Override
public void run()
{
Log.f3("<DEFERRED> Loading \"" + Log.str(def) + "\"");
def.load();
}
}));
@ -72,7 +75,7 @@ public class DeferredLoader extends Thread implements ResourceLoadRequest.Listen
continue;
}
Log.f3("<DEFERRED> Loading \"" + Log.str(def) + "\"");
Log.f3("<DEFERRED> Loading \"" + Log.str(def) + "\" asynchronously.");
exs.submit(new Runnable() {

@ -0,0 +1,127 @@
package mightypork.rogue.loading;
import mightypork.utils.control.interf.Destroyable;
import mightypork.utils.logging.Log;
/**
* Deferred resource abstraction.<br>
* 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;
}
}

@ -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 {
}

@ -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 {
}

@ -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);
}

@ -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();
}

@ -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;
}
}

@ -6,7 +6,7 @@ import mightypork.utils.objects.Mutable;
/**
* Volume multiplex
* Volume combined of multiple volumes, combining them (multiplication).
*
* @author MightyPork
*/

@ -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);
}
}

@ -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());

@ -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);
}
}

@ -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);
}

@ -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);

@ -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<File> 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
}
}
}
}

@ -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;
}
}

@ -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;

@ -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("\\", "/");

@ -20,7 +20,7 @@ public abstract class AbstractIonList<T> extends ArrayList<T> 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<T> extends ArrayList<T> 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);

@ -34,9 +34,9 @@ public abstract class AbstractIonMap<V> extends LinkedHashMap<String, V> 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<V> extends LinkedHashMap<String, V> impleme
{
try {
for (java.util.Map.Entry<String, V> 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);

@ -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;
}
}

@ -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;
}

@ -6,7 +6,7 @@ package mightypork.utils.files.ion;
*
* @author MightyPork
*/
public class IonList extends AbstractIonList<Object> implements Ionizable {
public class IonList extends AbstractIonList<Object> {
public Ionizable getIonizable(int index) throws IonException
{
@ -70,61 +70,61 @@ public class IonList extends AbstractIonList<Object> 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<Object> 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");
}

@ -6,7 +6,7 @@ package mightypork.utils.files.ion;
*
* @author MightyPork
*/
public class IonMap extends AbstractIonMap<Object> implements Ionizable {
public class IonMap extends AbstractIonMap<Object> {
public boolean getBoolean(String key)
{

@ -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);

@ -53,6 +53,6 @@ public abstract class Constraint implements SettableContext {
{
if (context == null) return Coord.zero();
return context.getRect().getSize();
return context.getRect().size();
}
}

@ -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));

@ -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);
}

@ -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;
}
}

Loading…
Cancel
Save