javadoc, cleanup, added font system
This commit is contained in:
@@ -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();
|
||||
+8
-5
@@ -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,11 +228,24 @@ 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, 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
|
||||
{
|
||||
texture.bind();
|
||||
bindTexture(texture, false);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
private Audio audio = null;
|
||||
/** Audio resource */
|
||||
private Audio backingAudio = 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()
|
||||
protected void loadResource(String resource) throws IOException
|
||||
{
|
||||
return audio != null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public synchronized void load()
|
||||
{
|
||||
ensureLoaded();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Try to load if not loaded already
|
||||
*
|
||||
* @return is loaded
|
||||
*/
|
||||
protected synchronized boolean ensureLoaded()
|
||||
{
|
||||
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("");
|
||||
super(null);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void load()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isLoaded()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected boolean ensureLoaded()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
return "Texture(\"" + resourcePath + "\")";
|
||||
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)
|
||||
{
|
||||
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);
|
||||
|
||||
Reference in New Issue
Block a user