156 lines
4.5 KiB
Java

package net.lax1dude.eaglercraft.beta;
import java.nio.IntBuffer;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import net.lax1dude.eaglercraft.EaglerAdapter;
import net.lax1dude.eaglercraft.EaglerImage;
import net.minecraft.src.GLAllocation;
public class SpriteSheetTexture {
public final String name;
public final int iconIndex;
public final int iconTileSize;
private IntBuffer buffer = null;
private int dataFrameCount = 0;
private int[] frameSet = null;
public int ticks = 0;
private int[] mipmapOffsets = new int[5];
public SpriteSheetTexture(String name, int iconIndex, int iconTileSize) {
this.name = name;
this.iconIndex = iconIndex;
this.iconTileSize = iconTileSize;
reloadData();
}
public void update() {
ticks = (ticks + 1) % frameSet.length;
}
public IntBuffer grabFrame(int lvl) {
int offWidth = 16 >> lvl;
int step = offWidth * offWidth * iconTileSize * iconTileSize;
int startIndex = mipmapOffsets[lvl] + step * frameSet[ticks];
buffer.limit(startIndex + step);
buffer.position(startIndex);
return buffer;
}
public void reloadData() {
ticks = 0;
buffer = null;
frameSet = null;
byte[] imgBytes = EaglerAdapter.loadResourceBytes("/sprite_sheet/" + name + ".png");
if(imgBytes == null) {
return;
}
int dim = iconTileSize * iconTileSize * 256;
EaglerImage img = EaglerImage.loadImage(imgBytes);
dataFrameCount = img.data.length / dim;
ArrayList<Integer> loadedFrameSet = new ArrayList();
byte[] metaBytes = EaglerAdapter.loadResourceBytes("/sprite_sheet/" + name + ".txt");
if(metaBytes == null) {
for(int i = 0; i < dataFrameCount; ++i) {
loadedFrameSet.add(i);
}
}else {
String str = new String(metaBytes, StandardCharsets.UTF_8);
String[] splitted = str.split("\\s*,\\s*");
for(int i = 0; i < splitted.length; ++i) {
String idxStr = splitted[i];
int z = idxStr.indexOf('*');
if(z != -1) {
int idx = Integer.parseInt(idxStr.substring(0, z));
int c = Integer.parseInt(idxStr.substring(z + 1));
for(int j = 0; j < c; ++j) {
loadedFrameSet.add(idx);
}
}else {
loadedFrameSet.add(Integer.parseInt(idxStr));
}
}
}
frameSet = new int[loadedFrameSet.size()];
for(int i = 0; i < frameSet.length; ++i) {
frameSet[i] = loadedFrameSet.get(i).intValue();
}
buffer = GLAllocation.createDirectIntBuffer(
16 * 16 * dataFrameCount * iconTileSize * iconTileSize +
8 * 8 * dataFrameCount * iconTileSize * iconTileSize +
4 * 4 * dataFrameCount * iconTileSize * iconTileSize +
2 * 2 * dataFrameCount * iconTileSize * iconTileSize +
dataFrameCount * iconTileSize * iconTileSize
);
int[] texData = swapRB(img.data);
mipmapOffsets[0] = 0;
buffer.put(texData);
mipmapOffsets[1] = buffer.position();
texData = downscale(texData, 16 * iconTileSize, 16 * iconTileSize * dataFrameCount);
buffer.put(texData);
mipmapOffsets[2] = buffer.position();
texData = downscale(texData, 8 * iconTileSize, 8 * iconTileSize * dataFrameCount);
buffer.put(texData);
mipmapOffsets[3] = buffer.position();
texData = downscale(texData, 4 * iconTileSize, 4 * iconTileSize * dataFrameCount);
buffer.put(texData);
mipmapOffsets[4] = buffer.position();
texData = downscale(texData, 2 * iconTileSize, 2 * iconTileSize * dataFrameCount);
buffer.put(texData);
}
private static int[] downscale(int[] in, int sw, int sh) {
int dw = sw / 2;
int dh = sh / 2;
int[] ret = new int[dw * dh];
for(int y = 0; y < dh; ++y) {
for(int x = 0; x < dw; ++x) {
int a = in[((x * 2) + (y * 2) * sw)];
int b = in[((x * 2 + 1) + (y * 2) * sw)];
int c = in[((x * 2 + 1) + (y * 2 + 1) * sw)];
int d = in[((x * 2) + (y * 2 + 1) * sw)];
int b1= (((a >> 26) & 0x3F)) +
(((b >> 26) & 0x3F)) +
(((c >> 26) & 0x3F)) +
(((d >> 26) & 0x3F));
int b2= (((a >> 18) & 0x3F)) +
(((b >> 18) & 0x3F)) +
(((c >> 18) & 0x3F)) +
(((d >> 18) & 0x3F));
int b3= (((a >> 10) & 0x3F)) +
(((b >> 10) & 0x3F)) +
(((c >> 10) & 0x3F)) +
(((d >> 10) & 0x3F));
int b4= (((a >> 2) & 0x3F)) +
(((b >> 2) & 0x3F)) +
(((c >> 2) & 0x3F)) +
(((d >> 2) & 0x3F));
ret[y * dw + x] = (b1 << 24) | (b2 << 16) | (b3 << 8) | b4;
}
}
return ret;
}
private static int[] swapRB(int[] in) {
int[] out = new int[in.length];
for(int i = 0; i < in.length; ++i) {
int r = (in[i] >> 16) & 0xFF;
int b = in[i] & 0xFF;
out[i] = (in[i] & 0xFF00FF00) | (b << 16) | r;
}
return out;
}
}