//
// Triple Play - utilities for use in PlayN-based games
// Copyright (c) 2011-2014, Three Rings Design, Inc. - All rights reserved.
// http://github.com/threerings/tripleplay/blob/master/LICENSE
package tripleplay.util;
import pythagoras.f.Point;
import pythagoras.f.Rectangle;
import playn.core.Image;
import playn.core.ImageLayer;
import playn.core.Json;
/**
* A frames implementation that uses a packed texture atlas and metadata generated by the {@code
* FramePacker}.
*/
public class PackedFrames implements Frames
{
public static class Frame {
public final Point offset;
public final Rectangle bounds;
public Frame (Point offset, Rectangle bounds) {
this.offset = offset;
this.bounds = bounds;
}
}
public PackedFrames (Image source, Json.Object meta) {
this(source, meta.getNumber("width"), meta.getNumber("height"), parseFrames(meta));
}
public PackedFrames (Image source, float[][] meta) {
this(source, meta[0][0], meta[0][1], parseFrames(meta));
}
public PackedFrames (Image source, float width, float height, Frame[] frames) {
_source = source;
_width = width;
_height = height;
_frames = frames;
}
@Override public float width () {
return _width;
}
@Override public float height () {
return _height;
}
@Override public int count () {
return _frames.length;
}
@Override public Image frame (int index) {
Rectangle b = _frames[index].bounds;
return _source.subImage(b.x, b.y, b.width, b.height);
}
@Override public Point offset (int index) {
return _frames[index].offset;
}
@Override public void apply (int index, ImageLayer layer) {
Frame f = _frames[index];
layer.setTranslation(f.offset.x, f.offset.y);
Image cur = layer.image();
if (cur instanceof Image.Region) {
Image.Region curr = (Image.Region)cur;
if (curr.parent() == _source) {
curr.setBounds(f.bounds.x, f.bounds.y, f.bounds.width, f.bounds.height);
return;
}
}
layer.setImage(frame(index));
}
/**
* Parses JSON generated the {@code FramePacker} tool.
*/
protected static Frame[] parseFrames (Json.Object meta) {
// TODO: support skipping frames (right now we assume the frames in the json array are
// exactly frames 0 to length-1)
Json.Array jframes = meta.getArray("frames");
Frame[] frames = new Frame[jframes.length()];
for (int ii = 0; ii < frames.length; ii++) {
Json.Object frame = jframes.getObject(ii);
Json.TypedArray<Float> off = frame.getArray("off", Float.class);
Json.TypedArray<Float> src = frame.getArray("src", Float.class);
frames[frame.getInt("idx")] = new Frame(
new Point(off.get(0), off.get(1)),
new Rectangle(src.get(0), src.get(1), src.get(2), src.get(3)));
}
return frames;
}
/**
* Parses custom float[][] array generated the {@code FramePacker} tool.
*/
protected static Frame[] parseFrames (float[][] meta) {
Frame[] frames = new Frame[(meta.length-1)/2];
for (int ii = 0, mm = 1; ii < frames.length; ii++) {
frames[ii] = new Frame(new Point(meta[mm][0], meta[mm++][1]),
new Rectangle(meta[mm][0], meta[mm][1],
meta[mm][2], meta[mm++][3]));
}
return frames;
}
protected final Image _source;
protected final float _width, _height;
protected final Frame[] _frames;
}