@author YongHoon
*/
public class BitmapTextSavable extends Node {
private BitmapFont font;
private StringBlock block;
private boolean needRefresh = true;
private BitmapTextPage[] textPages;
private Letters letters;
private Rectangle box;
public BitmapTextSavable() {
}
public BitmapTextSavable(BitmapFont font) {
this(font, false, false);
}
public BitmapTextSavable(BitmapFont font, boolean rightToLeft) {
this(font, rightToLeft, false);
}
public BitmapTextSavable(BitmapFont font, boolean rightToLeft,
boolean arrayBased) {
setFont(font, rightToLeft, arrayBased);
}
public void setFont(BitmapFont font, boolean rightToLeft, boolean arrayBased) {
textPages = new BitmapTextPage[font.getPageSize()];
for (int page = 0; page < textPages.length; page++) {
textPages[page] = new BitmapTextPage(font, arrayBased, page);
attachChild(textPages[page]);
}
this.font = font;
this.block = new StringBlock();
block.setSize(font.getPreferredSize());
letters = new Letters(font, block, rightToLeft);
}
@Override
public void read(JmeImporter e) throws IOException {
super.read(e);
InputCapsule capsule = e.getCapsule(this);
setFont((BitmapFont) capsule.readSavable(âfontâ, null));
setText(capsule.readString(âtextâ, ââ));
setAlpha(capsule.readFloat(âalphaâ, 1));
setColor((ColorRGBA) capsule.readSavable(âcolorâ, null));
setSize(capsule.readFloat(âsizeâ, 1));
float x = capsule.readFloat(âboxxâ, -1);
float y = capsule.readFloat(âboxyâ, -1);
float w = capsule.readFloat(âboxwâ, -1);
float h = capsule.readFloat(âboxhâ, -1);
if (x != -1) {
setBox(new Rectangle(x, y, w, h));
}
switch (capsule.readInt(âalignmentâ, 0)) {
case 1:
setAlignment(Align.Left);
break;
case 2:
setAlignment(Align.Center);
break;
case 3:
setAlignment(Align.Right);
break;
}
}
@Override
public void write(JmeExporter e) throws IOException {
for (BitmapTextPage t : textPages) {
detachChild(t);
// exclude the textpages from the saving process
}
super.write(e);
for (BitmapTextPage t : textPages) {
attachChild(t);
}
OutputCapsule capsule = e.getCapsule(this);
capsule.write(font, "font", null);
capsule.write(getText(), "text", null);
capsule.write(getAlpha(), "alpha", 1);
capsule.write(getColor(), "color", null);
capsule.write(getSize(), "size", 1);
if (box != null) {
capsule.write(box.x, "boxx", -2);
capsule.write(box.y, "boxy", -2);
capsule.write(box.width, "boxw", -2);
capsule.write(box.height, "boxh", -2);
}
switch (getAlignment()) {
case Left:
capsule.write(1, "alignment", 0);
break;
case Center:
capsule.write(2, "alignment", 0);
break;
case Right:
capsule.write(3, "alignment", 0);
break;
}
}
private void setFont(BitmapFont font) {
setFont(font, false, false);
}
@Override
public BitmapTextSavable clone() {
BitmapTextSavable clone = (BitmapTextSavable) super.clone();
for (int i = 0; i < textPages.length; i++) {
clone.textPages[i] = textPages[i].clone();
}
clone.block = block.clone();
clone.needRefresh = true;
return clone;
}
public BitmapFont getFont() {
return font;
}
/**
- Changes text size
-
-
@param size
-
text size
*/
public void setSize(float size) {
block.setSize(size);
needRefresh = true;
letters.invalidate();
}
public float getSize() {
return block.getSize();
}
/**
*/
public void setText(CharSequence text) {
// note: text.toString() is free if text is already a java.lang.String.
setText(text != null ? text.toString() : null);
}
/**
-
-
@param text
-
String to change text to
*/
public void setText(String text) {
text = text == null ? ââ : text;
if (text == block.getText() || block.getText().equals(text)) {
return;
}
/*
* The problem with the below block is that StringBlock carries pretty
* much all of the text-related state of the BitmapText such as size,
* text box, alignment, etc.
*
* I'm not sure why this change was needed and the commit message was
* not entirely helpful because it purports to fix a problem that I've
* never encountered.
*
* If block.setText("") doesn't do the right thing then that's where the
* fix should go because StringBlock carries too much information to be
* blown away every time. -pspeed
*
* Change was made:
* http://code.google.com/p/jmonkeyengine/source/detail?
* spec=svn9389&r=9389 Diff:
* http://code.google.com/p/jmonkeyengine/source
* /diff?path=/trunk/engine/
* src/core/com/jme3/font/BitmapText.java&format
* =side&r=9389&old_path=/trunk
* /engine/src/core/com/jme3/font/BitmapText.java&old=8843
*
* // If the text is empty, reset if (text.isEmpty()) {
* detachAllChildren();
*
* for (int page = 0; page < textPages.length; page++) { textPages[page]
* = new BitmapTextPage(font, true, page); attachChild(textPages[page]);
* }
*
* block = new StringBlock(); letters = new Letters(font, block,
* letters.getQuad().isRightToLeft()); }
*/
// Update the text content
block.setText(text);
letters.setText(text);
// Flag for refresh
needRefresh = true;
}
/**
-
@return returns text
*/
public String getText() {
return block.getText();
}
/**
-
@return color of the text
*/
public ColorRGBA getColor() {
return letters.getBaseColor();
}
/**
- changes text color. all substring colors are deleted.
-
-
@param color
-
new color of text
*/
public void setColor(ColorRGBA color) {
letters.setColor(color);
letters.invalidate(); // TODO: Donât have to align.
needRefresh = true;
}
/**
- Sets an overall alpha that will be applied to all letters. If the alpha
- passed is -1 then alpha reverts to default⊠which will be 1 for
- anything unspecified and color tags will be reset to 1 or their encoded
- alpha.
*/
public void setAlpha(float alpha) {
letters.setBaseAlpha(alpha);
needRefresh = true;
}
public float getAlpha() {
return letters.getBaseAlpha();
}
/**
*/
public void setBox(Rectangle rect) {
this.box = rect;
block.setTextBox(rect);
letters.invalidate();
needRefresh = true;
}
/**
-
@return height of the line
*/
public float getLineHeight() {
return font.getLineHeight(block);
}
/**
-
@return height of whole textblock
*/
public float getHeight() {
if (needRefresh) {
assemble();
}
float height = getLineHeight() * block.getLineCount();
Rectangle textBox = block.getTextBox();
if (textBox != null) {
return Math.max(height, textBox.height);
}
return height;
}
/**
-
@return width of line
*/
public float getLineWidth() {
if (needRefresh) {
assemble();
}
Rectangle textBox = block.getTextBox();
if (textBox != null) {
return Math.max(letters.getTotalWidth(), textBox.width);
}
return letters.getTotalWidth();
}
/**
-
@return line count
*/
public int getLineCount() {
if (needRefresh) {
assemble();
}
return block.getLineCount();
}
public LineWrapMode getLineWrapMode() {
return block.getLineWrapMode();
}
/**
- Set horizontal alignment. Applicable only when text bound is set.
-
-
@param align
*/
public void setAlignment(BitmapFont.Align align) {
if (block.getTextBox() == null && align != Align.Left) {
throw new RuntimeException(âBound is not setâ);
}
block.setAlignment(align);
letters.invalidate();
needRefresh = true;
}
/**
- Set vertical alignment. Applicable only when text bound is set.
-
-
@param align
*/
public void setVerticalAlignment(BitmapFont.VAlign align) {
if (block.getTextBox() == null && align != VAlign.Top) {
throw new RuntimeException(âBound is not setâ);
}
block.setVerticalAlignment(align);
letters.invalidate();
needRefresh = true;
}
public BitmapFont.Align getAlignment() {
return block.getAlignment();
}
public BitmapFont.VAlign getVerticalAlignment() {
return block.getVerticalAlignment();
}
/**
/**
- Set the font style of substring. If font doesnât contain style, default
- style is applied
-
-
@param regexp
-
regular expression
-
@param style
*/
public void setStyle(String regexp, int style) {
Pattern p = Pattern.compile(regexp);
Matcher m = p.matcher(block.getText());
while (m.find()) {
setStyle(m.start(), m.end(), style);
}
}
/**
/**
- Set the color of substring.
-
-
@param regexp
-
regular expression
-
@param color
*/
public void setColor(String regexp, ColorRGBA color) {
Pattern p = Pattern.compile(regexp);
Matcher m = p.matcher(block.getText());
while (m.find()) {
letters.setColor(m.start(), m.end(), color);
}
letters.invalidate();
needRefresh = true;
}
/**
-
@param tabs
-
tab positions
*/
public void setTabPosition(float⊠tabs) {
block.setTabPosition(tabs);
letters.invalidate();
needRefresh = false;
}
/**
- used for the tabs over the last tab position.
-
-
@param width
-
tab size
*/
public void setTabWidth(float width) {
block.setTabWidth(width);
letters.invalidate();
needRefresh = false;
}
/**
- for setLineWrapType(LineWrapType.NoWrap), set the last character when the
- text exceeds the bound.
-
-
@param c
*/
public void setEllipsisChar(char c) {
block.setEllipsisChar©;
letters.invalidate();
needRefresh = false;
}
/**
- Available only when bounding is set.
setBox()
method call is
- needed in advance. true when
-
-
@param wrap
-
NoWrap : Letters over the text bound is not shown. the last
-
character is set to '...'(0x2026) Character: Character is
-
split at the end of the line. Word : Word is split at the end
-
of the line. Clip : The text is hard-clipped at the border
-
including showing only a partial letter if it goes beyond the
-
text bound.
*/
public void setLineWrapMode(LineWrapMode wrap) {
if (block.getLineWrapMode() != wrap) {
block.setLineWrapMode(wrap);
letters.invalidate();
needRefresh = true;
}
}
@Override
public void updateLogicalState(float tpf) {
super.updateLogicalState(tpf);
if (needRefresh) {
assemble();
}
}
private void assemble() {
// first generate quadlist
letters.update();
for (int i = 0; i < textPages.length; i++) {
textPages[i].assemble(letters);
}
needRefresh = false;
}
private ColorRGBA getColor(Material mat, String name) {
MatParam mp = mat.getParam(name);
if (mp == null) {
return null;
}
return (ColorRGBA) mp.getValue();
}
public void render(RenderManager rm, ColorRGBA color) {
for (BitmapTextPage page : textPages) {
Material mat = page.getMaterial();
mat.setTexture(âColorMapâ, page.getTexture());
// ColorRGBA original = getColor(mat, âColorâ);
// mat.setColor(âColorâ, color);
mat.render(page, rm);
// if( original == null ) {
// mat.clearParam("Color");
// } else {
// mat.setColor("Color", original);
// }
}
}
}
[/java]