com.bladecoder.engine.ui.BladeSkin Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of blade-engine Show documentation
Show all versions of blade-engine Show documentation
Classic point and click adventure game engine
package com.bladecoder.engine.ui;
import java.util.ArrayList;
import java.util.Arrays;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator;
import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator.FreeTypeFontParameter;
import com.badlogic.gdx.scenes.scene2d.ui.Button;
import com.badlogic.gdx.scenes.scene2d.ui.CheckBox;
import com.badlogic.gdx.scenes.scene2d.ui.ImageButton;
import com.badlogic.gdx.scenes.scene2d.ui.ImageTextButton;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.List;
import com.badlogic.gdx.scenes.scene2d.ui.ProgressBar;
import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane;
import com.badlogic.gdx.scenes.scene2d.ui.SelectBox;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.Slider;
import com.badlogic.gdx.scenes.scene2d.ui.SplitPane;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.scenes.scene2d.ui.TextField;
import com.badlogic.gdx.scenes.scene2d.ui.TextTooltip;
import com.badlogic.gdx.scenes.scene2d.ui.Touchpad;
import com.badlogic.gdx.scenes.scene2d.ui.Tree;
import com.badlogic.gdx.scenes.scene2d.ui.Window;
import com.badlogic.gdx.scenes.scene2d.utils.Drawable;
import com.badlogic.gdx.scenes.scene2d.utils.NinePatchDrawable;
import com.badlogic.gdx.scenes.scene2d.utils.SpriteDrawable;
import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;
import com.badlogic.gdx.scenes.scene2d.utils.TiledDrawable;
import com.badlogic.gdx.utils.Json;
import com.badlogic.gdx.utils.Json.ReadOnlySerializer;
import com.badlogic.gdx.utils.JsonValue;
import com.badlogic.gdx.utils.SerializationException;
import com.badlogic.gdx.utils.reflect.ClassReflection;
import com.badlogic.gdx.utils.reflect.ReflectionException;
import com.bladecoder.engine.util.DPIUtils;
import com.bladecoder.engine.util.EngineLogger;
import com.bladecoder.engine.util.FileUtils;
/**
* Custom Skin class to add TTF font support
*
* @author rgarcia
*/
public class BladeSkin extends Skin {
public BladeSkin(FileHandle skinFile) {
super(skinFile);
}
public BladeSkin(FileHandle skinFile, TextureAtlas atlas) {
super(skinFile, atlas);
}
/**
* Override BitmapFont.class serializer to support TTF fonts
*
* Also add the size parameter to support bitmaps font size in pt
*/
@Override
protected Json getJsonLoader(final FileHandle skinFile) {
Json json = super.getJsonLoader(skinFile);
final Skin skin = this;
json.setSerializer(Skin.class, new ReadOnlySerializer() {
public Skin read (Json json, JsonValue typeToValueMap, @SuppressWarnings("rawtypes") Class ignored) {
for (JsonValue valueMap = typeToValueMap.child; valueMap != null; valueMap = valueMap.next) {
try {
Class> type = json.getClass(valueMap.name());
if (type == null) type = ClassReflection.forName(valueMap.name());
readNamedObjects(json, type, valueMap);
} catch (ReflectionException ex) {
throw new SerializationException(ex);
}
}
return skin;
}
private void readNamedObjects (Json json, Class> type, JsonValue valueMap) {
Class> addType = type == TintedDrawable.class ? Drawable.class : type;
for (JsonValue valueEntry = valueMap.child; valueEntry != null; valueEntry = valueEntry.next) {
Object object = json.readValue(type, valueEntry);
if (object == null) continue;
try {
add(valueEntry.name, object, addType);
if (addType != Drawable.class && ClassReflection.isAssignableFrom(Drawable.class, addType))
add(valueEntry.name, object, Drawable.class);
} catch (Exception ex) {
throw new SerializationException(
"Error reading " + ClassReflection.getSimpleName(type) + ": " + valueEntry.name, ex);
}
}
}
});
json.setSerializer(BitmapFont.class, new ReadOnlySerializer() {
public BitmapFont read(Json json, JsonValue jsonData, @SuppressWarnings("rawtypes") Class type) {
String path = json.readValue("file", String.class, jsonData);
int scaledSize = json.readValue("scaledSize", int.class, -1, jsonData);
Boolean flip = json.readValue("flip", Boolean.class, false, jsonData);
int size = json.readValue("size", int.class, -1, jsonData);
FileHandle fontFile = skinFile.parent().child(path);
if (!FileUtils.exists(fontFile))
fontFile = Gdx.files.internal(path);
if (!FileUtils.exists(fontFile))
throw new SerializationException("Font file not found: " + fontFile);
BitmapFont font;
if (fontFile.extension().equalsIgnoreCase("ttf")) {
if (size == -1)
throw new SerializationException("'size' mandatory parameter for .ttf fonts");
long initTime = System.currentTimeMillis();
FreeTypeFontGenerator generator = new FreeTypeFontGenerator(fontFile);
FreeTypeFontParameter parameter = new FreeTypeFontParameter();
parameter.size = (int) (DPIUtils.dpToPixels(size) * DPIUtils.getSizeMultiplier());
parameter.incremental = json.readValue("incremental", boolean.class, true, jsonData);
parameter.borderWidth = json.readValue("borderWidth", int.class, 0, jsonData);
parameter.borderColor = json.readValue("borderColor", Color.class, Color.BLACK, jsonData);
parameter.borderStraight = json.readValue("borderStraight", boolean.class, false, jsonData);
parameter.shadowOffsetX = json.readValue("shadowOffsetX", int.class, 0, jsonData);
parameter.shadowOffsetY = json.readValue("shadowOffsetY", int.class, 0, jsonData);
parameter.shadowColor = json.readValue("shadowColor", Color.class, Color.BLACK, jsonData);
if(parameter.incremental)
parameter.characters = "";
// parameter.hinting = Hinting.Medium;
// parameter.mono = false;
font = generator.generateFont(parameter);
EngineLogger.debug(path + " TIME (ms): " + (System.currentTimeMillis() - initTime));
// TODO Dispose all generators.
} else {
// Use a region with the same name as the font, else use a
// PNG file in the same directory as the FNT file.
String regionName = fontFile.nameWithoutExtension();
try {
TextureRegion region = skin.optional(regionName, TextureRegion.class);
if (region != null)
font = new BitmapFont(fontFile, region, flip);
else {
FileHandle imageFile = fontFile.parent().child(regionName + ".png");
if (FileUtils.exists(imageFile))
font = new BitmapFont(fontFile, imageFile, flip);
else
font = new BitmapFont(fontFile, flip);
}
// Scaled size is the desired cap height to scale the
// font to.
if (scaledSize != -1)
font.getData().setScale(scaledSize / font.getCapHeight());
else if (size != -1) // TODO set size in points (dpi
// independent)
font.getData().setScale(
(DPIUtils.dpToPixels(size) * DPIUtils.getSizeMultiplier()) / font.getCapHeight());
} catch (RuntimeException ex) {
throw new SerializationException("Error loading bitmap font: " + fontFile, ex);
}
}
font.getData().markupEnabled = true;
return font;
}
});
for (Class> cls : TAGGED_STYLES){
json.addClassTag(cls.getSimpleName(), cls);
}
return json;
}
private static final Class>[] AUTO_TAGGED_STYLES = {
BitmapFont.class, Color.class, TintedDrawable.class,
NinePatchDrawable.class, SpriteDrawable.class, TextureRegionDrawable.class, TiledDrawable.class,
Button.ButtonStyle.class, CheckBox.CheckBoxStyle.class, ImageButton.ImageButtonStyle.class,
ImageTextButton.ImageTextButtonStyle.class, Label.LabelStyle.class, List.ListStyle.class,
ProgressBar.ProgressBarStyle.class, ScrollPane.ScrollPaneStyle.class, SelectBox.SelectBoxStyle.class,
Slider.SliderStyle.class, SplitPane.SplitPaneStyle.class, TextButton.TextButtonStyle.class,
TextField.TextFieldStyle.class, TextTooltip.TextTooltipStyle.class, Touchpad.TouchpadStyle.class,
Tree.TreeStyle.class, Window.WindowStyle.class
};
private final static ArrayList> TAGGED_STYLES = new ArrayList>(Arrays.asList(AUTO_TAGGED_STYLES));
public static final void addStyleTag(Class> tag) {
TAGGED_STYLES.add(tag);
}
}