diff options
Diffstat (limited to 'ardor3d-core/src/main/java')
5 files changed, 289 insertions, 72 deletions
diff --git a/ardor3d-core/src/main/java/com/ardor3d/ui/text/BMFont.java b/ardor3d-core/src/main/java/com/ardor3d/ui/text/BMFont.java index 5dd8c07..8aeda6a 100644 --- a/ardor3d-core/src/main/java/com/ardor3d/ui/text/BMFont.java +++ b/ardor3d-core/src/main/java/com/ardor3d/ui/text/BMFont.java @@ -3,7 +3,7 @@ * * This file is part of Ardor3D. * - * Ardor3D is free software: you can redistribute it and/or modify it + * Ardor3D is free software: you can redistribute it and/or modify it * under the terms of its license which may be found in the accompanying * LICENSE file or at <http://www.ardor3d.com/LICENSE>. */ @@ -45,7 +45,7 @@ import com.ardor3d.util.export.Savable; import com.ardor3d.util.resource.ResourceSource; /** - * Loads a font generated by BMFont (http://www.angelcode.com/products/bmfont/). + * Loads a font generated by BMFont ({@link http://www.angelcode.com/products/bmfont/}). * <ul> * <li>Font info file *must* be in XML format. * <li>The texture should be saved in 32 bit PNG format - TGA does not appear to work. @@ -67,6 +67,8 @@ public class BMFont implements Savable { private int _maxCharAdv; private Common _common = null; private Info _info = null; + private final float _defaultLodBias = -0.6f; + private final float _defaultAnisotropy = 1; /** * This constructor should be used when loading as Savable @@ -76,9 +78,9 @@ public class BMFont implements Savable { /** * Reads an XML BMFont description file and loads corresponding texture. Note that the TGA written by BMFont does * not seem to be read properly by the Ardor3D loader. PNG works fine. - * - * @param fileUrl - * - the location of the .fnt font file. Can not be null. + * + * @param source + * ResourceSource describing where this font comes from. * @param useMipMaps * if true, use trilinear filtering with max anisotropy, else min filter is bilinear. MipMaps result in * blurrier text, but less shimmering. @@ -87,11 +89,18 @@ public class BMFont implements Savable { */ public BMFont(final ResourceSource source, final boolean useMipMaps) throws IOException { _useMipMaps = useMipMaps; - parseFontFile(source); initialize(source); } + public void setBlendStateSetter(final RenderStateSetter setter) { + _blendStateSetter = setter; + } + + public void setAlphaStateSetter(final RenderStateSetter setter) { + _alphaStateSetter = setter; + } + /** apply default render states to spatial */ public void applyRenderStatesTo(final Spatial spatial, final boolean useBlend) { if (useBlend) { @@ -112,15 +121,14 @@ public class BMFont implements Savable { } public int getSize() { - return Math.abs(_info.size); + return _info.size; } + /** + * The average of _common.base and _common.lineHeight seems to be the best general purpose value + */ public int getLineHeight() { - return _common.lineHeight; - } - - public int getBaseHeight() { - return _common.base; + return (_common.base + _common.lineHeight) / 2; } public int getTextureWidth() { @@ -181,7 +189,7 @@ public class BMFont implements Savable { /** * Writes the XML for this font out to the OutputStream provided. - * + * * @param outputStream * the OutputStream to which the XML for this font will be written to * @throws IOException @@ -372,10 +380,10 @@ public class BMFont implements Savable { /** * load the texture and create default render states. Only a single page is supported. - * - * @param fontUrl + * + * @param source + * the source of the font file */ - // ---------------------------------------------------------- protected void initialize(final ResourceSource source) throws MalformedURLException { _styleName = _info.face + "-" + _info.size; @@ -394,8 +402,7 @@ public class BMFont implements Savable { // only a single page is supported if (_pages.size() > 0) { final Page page = _pages.get(0); - - final ResourceSource texSrc = source.getRelativeSource("./" + page.file); + final ResourceSource texSrc = source.getRelativeSource(page.file); Texture.MinificationFilter minFilter; Texture.MagnificationFilter magFilter; @@ -410,11 +417,9 @@ public class BMFont implements Savable { _pageTexture = TextureManager.loadFromKey(tkey, null, null); _pageTexture.setMagnificationFilter(magFilter); - // Add a touch higher mipmap selection. - _pageTexture.setLodBias(-1); - if (_useMipMaps) { - _pageTexture.setAnisotropicFilterPercent(1.0f); + _pageTexture.setAnisotropicFilterPercent(_defaultAnisotropy); + _pageTexture.setLodBias(_defaultLodBias); } } } @@ -436,7 +441,7 @@ public class BMFont implements Savable { } /** - * + * * @param fontUrl * @throws IOException */ @@ -450,9 +455,9 @@ public class BMFont implements Savable { final Document doc = db.parse(source.openStream()); doc.getDocumentElement().normalize(); - recurse(doc.getElementsByTagName("font").item(0)); + recurse(doc.getFirstChild()); - // db.reset(); + db.reset(); } catch (final Throwable t) { final IOException ex = new IOException("Error loading font file " + source.toString()); ex.initCause(t); @@ -824,7 +829,7 @@ public class BMFont implements Savable { public BlendState blendState; public ZBufferState zBuffState; - float _blendDisabledTestRef = 0.3f; + float _blendDisabledTestRef = 0.23f; float _blendEnabledTestRef = 0.02f; boolean _useBlend; @@ -850,7 +855,7 @@ public class BMFont implements Savable { spatial.setRenderState(blendState); spatial.setRenderState(zBuffState); if (_useBlend) { - spatial.getSceneHints().setRenderBucketType(RenderBucketType.Transparent); + spatial.getSceneHints().setRenderBucketType(RenderBucketType.PostBucket); } else { spatial.getSceneHints().setRenderBucketType(RenderBucketType.Opaque); } diff --git a/ardor3d-core/src/main/java/com/ardor3d/ui/text/BMFontManager.java b/ardor3d-core/src/main/java/com/ardor3d/ui/text/BMFontManager.java new file mode 100644 index 0000000..3578eec --- /dev/null +++ b/ardor3d-core/src/main/java/com/ardor3d/ui/text/BMFontManager.java @@ -0,0 +1,134 @@ +/** + * Copyright (c) 2008-2012 Ardor Labs, Inc. + * + * This file is part of Ardor3D. + * + * Ardor3D is free software: you can redistribute it and/or modify it + * under the terms of its license which may be found in the accompanying + * LICENSE file or at <http://www.ardor3d.com/LICENSE>. + */ + +package com.ardor3d.ui.text; + +import java.io.IOException; +import java.util.HashMap; +import java.util.logging.Level; +import java.util.logging.Logger; + +import com.ardor3d.util.resource.URLResourceSource; + +/** + * Simple singleton that loads some font textures and provides easy access. + */ +public class BMFontManager { + private static final Logger logger = Logger.getLogger(BMFontManager.class.getName()); + + private static final BMFontManager INSTANCE = new BMFontManager(); + + private final HashMap<String, BMFont> _loadedFonts = new HashMap<>(); + + public enum FontStyle { + ArialMedium("arial-24-bold-regular"), // + SansExtraSmall("DroidSans-14-bold-regular"), // + SansSmall("DroidSans-16-bold-regular"), // + SansMedium("DroidSans-20-bold-regular"), // + SansLarge("DroidSans-26-bold-regular"), // + SansExtraLarge("DroidSans-40-bold-regular"), // + MonoSmall("DroidSansMono-15-bold-regular"), // + MonoMedium("DroidSansMono-20-bold-regular"), // + MonoLarge("DroidSansMono-26-bold-regular"), // + MonoExtraLarge("DroidSansMono-40-bold-regular"); + + public final String fontName; + + FontStyle(final String name) { + fontName = name; + } + } + + /** + * + * @param style + * @return + */ + public static BMFont getFont(final FontStyle style) { + return getFont(style.fontName); + } + + /** + * Retrieves the font, loads it if need be. Font must exist in this bundle in images/fonts. + * + * @param fontName + * @return + */ + public static BMFont getFont(final String fontName) { + BMFont found = INSTANCE._loadedFonts.get(fontName); + if (found == null) { + found = newFont(fontName); + if (found != null) { + INSTANCE._loadedFonts.put(fontName, found); + } + } + return found; + } + + /** + * Creates the font. Font must exist in this bundle in images/fonts. + * + * @param fontName + * @return + */ + public static BMFont newFont(final String fontName) { + BMFont font = null; + final URLResourceSource rs = new URLResourceSource(BMFontManager.class.getResource(fontName + ".fnt")); + try { + font = new BMFont(rs, false); + } catch (final IOException e) { + if (logger.isLoggable(Level.WARNING)) { + logger.logp(Level.WARNING, "BMFontManager", "getFont(String)", "Unable to load font.", + new Object[] { fontName }); + } + } + return font; + } + + public static BMFont defaultFont() { + return getFont(FontStyle.SansMedium); + } + + public static BMFont sansExtraSmall() { + return getFont(FontStyle.SansExtraSmall); + } + + public static BMFont sansSmall() { + return getFont(FontStyle.SansSmall); + } + + public static BMFont sansMedium() { + return getFont(FontStyle.SansMedium); + } + + public static BMFont sansLarge() { + return getFont(FontStyle.SansLarge); + } + + public static BMFont sansExtraLarge() { + return getFont(FontStyle.SansExtraLarge); + } + + public static BMFont monoSmall() { + return getFont(FontStyle.MonoSmall); + } + + public static BMFont monoMedium() { + return getFont(FontStyle.MonoMedium); + } + + public static BMFont monoLarge() { + return getFont(FontStyle.MonoLarge); + } + + public static BMFont monoExtraLarge() { + return getFont(FontStyle.MonoExtraLarge); + } +}
\ No newline at end of file diff --git a/ardor3d-core/src/main/java/com/ardor3d/ui/text/BMText.java b/ardor3d-core/src/main/java/com/ardor3d/ui/text/BMText.java index 84546e6..b9b01be 100644 --- a/ardor3d-core/src/main/java/com/ardor3d/ui/text/BMText.java +++ b/ardor3d-core/src/main/java/com/ardor3d/ui/text/BMText.java @@ -3,7 +3,7 @@ * * This file is part of Ardor3D. * - * Ardor3D is free software: you can redistribute it and/or modify it + * Ardor3D is free software: you can redistribute it and/or modify it * under the terms of its license which may be found in the accompanying * LICENSE file or at <http://www.ardor3d.com/LICENSE>. */ @@ -11,10 +11,14 @@ package com.ardor3d.ui.text; import java.nio.FloatBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Logger; import com.ardor3d.annotation.SavableFactory; import com.ardor3d.math.ColorRGBA; import com.ardor3d.math.Matrix3; +import com.ardor3d.math.TransformException; import com.ardor3d.math.Vector2; import com.ardor3d.math.Vector3; import com.ardor3d.math.type.ReadOnlyColorRGBA; @@ -24,7 +28,6 @@ import com.ardor3d.renderer.Camera.ProjectionMode; import com.ardor3d.renderer.IndexMode; import com.ardor3d.renderer.Renderer; import com.ardor3d.scenegraph.Mesh; -import com.ardor3d.scenegraph.hint.CullHint; import com.ardor3d.scenegraph.hint.LightCombineMode; import com.ardor3d.scenegraph.hint.TextureCombineMode; import com.ardor3d.util.geom.BufferUtils; @@ -34,6 +37,8 @@ import com.ardor3d.util.geom.BufferUtils; */ @SavableFactory(factoryMethod = "initSavable") public class BMText extends Mesh { + private static final Logger logger = Logger.getLogger(BMText.class.getName()); + protected BMFont _font; protected String _textString; @@ -50,6 +55,8 @@ public class BMText extends Mesh { protected ColorRGBA _textClr = new ColorRGBA(1, 1, 1, 1); protected ColorRGBA _tempClr = new ColorRGBA(1, 1, 1, 1); + final protected List<BMTextChangeListener> _listeners = new ArrayList<>(); + public enum AutoScale { /** * No auto scaling @@ -70,11 +77,6 @@ public class BMText extends Mesh { protected AutoScale _autoScale = AutoScale.CapScreenSize; - /** - * @see BMText#setAutoFadeDistanceRange(double, double) - * @see BMText#setAutoFadeFixedPixelSize(int) - * @see BMText#setAutoFadeFalloff(float) - */ public enum AutoFade { /** * No auto fade. @@ -118,8 +120,8 @@ public class BMText extends Mesh { * Alignment of the text block from the pivot point */ public enum Align { - North(-0.5f, 0.0f), NorthWest(0.0f, 0.0f), NorthEast(-1.0f, 0.0f), Center(-0.5f, -0.5f), West(0.0f, -0.5f), East( - -1.0f, -0.5f), South(-0.5f, -1.0f), SouthWest(0.0f, -1.0f), SouthEast(-1.0f, -1.0f); + North(-0.5f, 0.0f), NorthWest(0.0f, 0.0f), NorthEast(-1.0f, 0.0f), Center(-0.5f, -0.5f), West(0.0f, + -0.5f), East(-1.0f, -0.5f), South(-0.5f, -1.0f), SouthWest(0.0f, -1.0f), SouthEast(-1.0f, -1.0f); public final float horizontal; public final float vertical; @@ -144,7 +146,7 @@ public class BMText extends Mesh { protected BMText() {} /** - * + * * @param sName * @param text * @param font @@ -162,7 +164,7 @@ public class BMText extends Mesh { } /** - * + * * @param sName * spatial name * @param text @@ -182,13 +184,13 @@ public class BMText extends Mesh { _justify = justify; _spacing = 0; _useBlend = useBlend; - if (_font.getOutlineWidth() > 1) { - _spacing = _font.getOutlineWidth() - 1; + if (_font != null) { + if (_font.getOutlineWidth() > 1) { + _spacing = _font.getOutlineWidth() - 1; + } } - // -- never cull setModelBound(null); - getSceneHints().setCullHint(CullHint.Never); // -- default to non-pickable getSceneHints().setAllPickingHints(false); @@ -197,12 +199,14 @@ public class BMText extends Mesh { getSceneHints().setLightCombineMode(LightCombineMode.Off); getSceneHints().setTextureCombineMode(TextureCombineMode.Replace); - // triangles - getMeshData().setIndexMode(IndexMode.Triangles); + // quads + getMeshData().setIndexMode(IndexMode.Quads); setText(text); - _font.applyRenderStatesTo(this, useBlend); + if (_font != null) { + _font.applyRenderStatesTo(this, useBlend); + } } public void setTextColor(final ReadOnlyColorRGBA clr) { @@ -298,20 +302,24 @@ public class BMText extends Mesh { @Override public synchronized void draw(final Renderer r) { - if (_textString.length() > 0) { + if (_font != null && _textString.length() > 0) { final Camera cam = Camera.getCurrentCamera(); if (!(_autoScale == AutoScale.Off && _autoFade == AutoFade.Off)) { updateScaleAndAlpha(cam, r); } - correctTransform(cam); - - super.draw(r); + // if text is transparent, don't spend time + // calculating transform and drawing + if (getDefaultColor().getAlpha() > 0.05) { + correctTransform(cam); + updateWorldBound(false); + super.draw(r); + } } } /** - * + * * @param cam */ public void correctTransform(final Camera cam) { @@ -322,14 +330,18 @@ public class BMText extends Mesh { _look.set(cam.getDirection()); _left.set(cam.getLeft()).negateLocal(); _rot.fromAxes(_left, _look, cam.getUp()); - _worldTransform.setRotation(_rot); + if (_rot.isOrthonormal()) { + _worldTransform.setRotation(_rot); + } else { + logger.warning("BMText: non-orthonormal rotation matrix :" + getName()); + } } _worldTransform.setScale(_localTransform.getScale()); } /** * Update the text's scale - * + * * @param cam */ public void updateScaleAndAlpha(final Camera cam, final Renderer r) { @@ -345,8 +357,8 @@ public class BMText extends Mesh { // calculate the height in world units of the screen at that depth final double heightAtZ; - if (cam.getProjectionMode() == ProjectionMode.Parallel) { - heightAtZ = cam.getFrustumTop(); + if (cam.getProjectionMode().equals(ProjectionMode.Parallel)) { + heightAtZ = cam.getFrustumBottom(); } else { heightAtZ = zDepth * cam.getFrustumTop() / cam.getFrustumNear(); } @@ -369,10 +381,26 @@ public class BMText extends Mesh { } } finalScale *= _fontScale; - setScale(finalScale, finalScale, -finalScale); + try { + setScale(finalScale, finalScale, -finalScale); + } catch (final TransformException e) { + final Matrix3 rot = new Matrix3(getRotation()); + final Vector3 c0 = rot.getColumn(0, new Vector3()); + final Vector3 c1 = rot.getColumn(1, new Vector3()); + final Vector3 c2 = rot.getColumn(2, new Vector3()); + c0.normalizeLocal(); + c1.normalizeLocal(); + c2.normalizeLocal(); + rot.setColumn(0, c0); + rot.setColumn(1, c1); + rot.setColumn(2, c2); + setRotation(rot); + setScale(finalScale, finalScale, -finalScale); + } } // -- adjust alpha ------- + final float oldAlpha = getDefaultColor().getAlpha(); switch (_autoFade) { case Off: break; @@ -386,11 +414,17 @@ public class BMText extends Mesh { screenSizeCapAlphaFade(capSize, depthScale, _screenSizeAlphaFalloff); break; } + final float newAlpha = getDefaultColor().getAlpha(); + if (newAlpha != oldAlpha) { + for (final BMTextChangeListener listener : _listeners) { + listener.textAlphaChanged(this, newAlpha); + } + } } /** * Set transparency based on native screen size. - * + * * @param capSize * 1/(font point size) * @param depthScale @@ -507,12 +541,12 @@ public class BMText extends Mesh { /** * Check whether buffers have sufficient capacity to hold current string values; if not, increase capacity and set * the limit. - * + * * @param text */ protected void checkBuffers(final String text) { final int chunkSize = 20; - final int vertices = 6 * text.length(); + final int vertices = 4 * text.length(); final int chunks = 1 + (vertices / chunkSize); final int required = chunks * chunkSize; FloatBuffer vertexBuffer = getMeshData().getVertexBuffer(); @@ -572,6 +606,10 @@ public class BMText extends Mesh { * Set text string and recreate geometry */ public synchronized void setText(final String text) { + if (_font == null) { + return; + } + if (text == null) { _textString = ""; } else { @@ -627,10 +665,8 @@ public class BMText extends Mesh { vertices.put(l).put(0).put(t); // left top vertices.put(l).put(0).put(b); // left bottom - vertices.put(r).put(0).put(t); // right top - vertices.put(r).put(0).put(t); // right top - vertices.put(l).put(0).put(b); // left bottom vertices.put(r).put(0).put(b); // right bottom + vertices.put(r).put(0).put(t); // right top // -- tex coords ---------------- l = chr.x / txW; @@ -640,10 +676,8 @@ public class BMText extends Mesh { texCrds.put(l).put(t); // left top texCrds.put(l).put(b); // left bottom - texCrds.put(r).put(t); // right top - texCrds.put(r).put(t); // right top - texCrds.put(l).put(b); // left bottom texCrds.put(r).put(b); // right bottom + texCrds.put(r).put(t); // right top int nextVal = 0; if (i < strLen - 1) { @@ -655,7 +689,11 @@ public class BMText extends Mesh { } _meshData.setVertexBuffer(vertices); _meshData.setTextureBuffer(texCrds, 0); - _meshData.setIndices(null); + + // -- notify listeners + for (final BMTextChangeListener listener : _listeners) { + listener.textSizeChanged(this, _size); + } } // this is inefficient yet incredibly convenient @@ -665,10 +703,6 @@ public class BMText extends Mesh { vertices.put(0).put(0).put(0); vertices.put(0).put(0).put(0); vertices.put(0).put(0).put(0); - vertices.put(0).put(0).put(0); - vertices.put(0).put(0).put(0); - uvs.put(0).put(0); - uvs.put(0).put(0); uvs.put(0).put(0); uvs.put(0).put(0); uvs.put(0).put(0); @@ -713,7 +747,7 @@ public class BMText extends Mesh { /** * set a fixed offset from the alignment center of rotation IN FONT UNITS */ - public void setFixedOffset(final Vector2 offset) { + public void setFixedOffset(final ReadOnlyVector2 offset) { final double x = offset.getX() * _font.getSize(); final double y = offset.getY() * _font.getSize(); _fixedOffset.set(x, y); @@ -724,6 +758,24 @@ public class BMText extends Mesh { return _lines; } + public ReadOnlyVector2 getFixedOffset() { + return _fixedOffset; + } + + public ReadOnlyVector2 getSize() { + return _size; + } + + public void addChangeListener(final BMTextChangeListener listener) { + if (!_listeners.contains(listener)) { + _listeners.add(listener); + } + } + + public boolean removeChangeListener(final BMTextChangeListener listener) { + return _listeners.remove(listener); + } + @Override public BMText makeCopy(final boolean shareGeometricData) { final BMText text = (BMText) super.makeCopy(shareGeometricData); diff --git a/ardor3d-core/src/main/java/com/ardor3d/ui/text/BMTextChangeListener.java b/ardor3d-core/src/main/java/com/ardor3d/ui/text/BMTextChangeListener.java new file mode 100644 index 0000000..8aaf5ea --- /dev/null +++ b/ardor3d-core/src/main/java/com/ardor3d/ui/text/BMTextChangeListener.java @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2008-2012 Ardor Labs, Inc. + * + * This file is part of Ardor3D. + * + * Ardor3D is free software: you can redistribute it and/or modify it + * under the terms of its license which may be found in the accompanying + * LICENSE file or at <http://www.ardor3d.com/LICENSE>. + */ + +package com.ardor3d.ui.text; + +import com.ardor3d.math.type.ReadOnlyVector2; + +public interface BMTextChangeListener { + public void textSizeChanged(BMText text, ReadOnlyVector2 size); + + public void textAlphaChanged(BMText text, float alpha); +}
\ No newline at end of file diff --git a/ardor3d-core/src/main/java/com/ardor3d/ui/text/BasicText.java b/ardor3d-core/src/main/java/com/ardor3d/ui/text/BasicText.java index fb3c712..325f9ac 100644 --- a/ardor3d-core/src/main/java/com/ardor3d/ui/text/BasicText.java +++ b/ardor3d-core/src/main/java/com/ardor3d/ui/text/BasicText.java @@ -3,7 +3,7 @@ * * This file is part of Ardor3D. * - * Ardor3D is free software: you can redistribute it and/or modify it + * Ardor3D is free software: you can redistribute it and/or modify it * under the terms of its license which may be found in the accompanying * LICENSE file or at <http://www.ardor3d.com/LICENSE>. */ @@ -19,6 +19,7 @@ import com.ardor3d.renderer.queue.RenderBucketType; import com.ardor3d.renderer.state.BlendState; import com.ardor3d.renderer.state.CullState; import com.ardor3d.renderer.state.ZBufferState; +import com.ardor3d.scenegraph.hint.CullHint; import com.ardor3d.scenegraph.hint.LightCombineMode; import com.ardor3d.scenegraph.hint.TextureCombineMode; import com.ardor3d.util.resource.ResourceLocatorTool; @@ -47,9 +48,12 @@ public class BasicText extends BMText { protected BasicText() {} + public BasicText(final String name, final String text, final BMFont font) { + this(name, text, font, font.getSize()); + } + public BasicText(final String name, final String text, final BMFont font, final double fontSize) { super(name, text, font); - getSceneHints().setRenderBucketType(RenderBucketType.Ortho); setFontScale(fontSize); setAutoFade(AutoFade.Off); setAutoScale(AutoScale.Off); @@ -74,8 +78,11 @@ public class BasicText extends BMText { blend.setTestFunction(BlendState.TestFunction.GreaterThan); setRenderState(blend); + getSceneHints().setRenderBucketType(RenderBucketType.Ortho); + getSceneHints().setCullHint(CullHint.Never); getSceneHints().setLightCombineMode(LightCombineMode.Off); getSceneHints().setTextureCombineMode(TextureCombineMode.Replace); + updateModelBound(); } |