package org.csdgn.cddatse.data; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.io.Reader; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import javax.imageio.ImageIO; import org.csdgn.cddatse.Options; import org.csdgn.maru.Files; import org.csdgn.maru.Strings; import com.google.gson.Gson; import com.google.gson.GsonBuilder; public class GFX { public static GFX instance; public String jsonFilename; public String tilesetFilename; public String name = ""; public String view = ""; public Tileset tileset; public ArrayList<BufferedImage> images = new ArrayList<BufferedImage>(); private GFX() {} public GFX(String author, int tileWidth, int tileHeight, String jsonFilename, String tilesetFilename) { tileset = new Tileset(); name = author; view = author + "'s"; this.jsonFilename = jsonFilename; this.tilesetFilename = tilesetFilename; tileset.tile_info = new TileInfo[1]; tileset.tile_info[0] = new TileInfo(); tileset.tile_info[0].width = tileWidth; tileset.tile_info[0].height = tileHeight; tileset.tiles = new ArrayList<BaseTile>(); } public TileInfo getTileInfo() { return tileset.tile_info[0]; } public void save(File outputFolder) throws IOException { //write tileset.txt StringBuilder sb = new StringBuilder(); sb.append("NAME: "); sb.append(name); sb.append("\r\nVIEW: "); sb.append(view); sb.append("\r\nJSON: "); String path = "gfx/" + outputFolder.getName() + "/"; sb.append(path); sb.append(jsonFilename); sb.append("\r\nTILESET: "); sb.append(path); sb.append(tilesetFilename); File file = new File(outputFolder,"tileset.txt"); Files.setFileContents(file,sb.toString()); //:3 optimize(); //write the json file file = new File(outputFolder,jsonFilename); GsonBuilder gb = new GsonBuilder(); if(Options.prettyPrint) { gb = gb.setPrettyPrinting(); } Files.setFileContents(file, gb.create().toJson(tileset)); //build buffered image, 16 tiles wide :) if(images.size() > 0) { TileInfo info = getTileInfo(); int width = 16 * info.width; int height = (int) Math.ceil(images.size()/16.0)*info.height; BufferedImage output = new BufferedImage(width,height,BufferedImage.TYPE_INT_ARGB); Graphics2D gx = output.createGraphics(); int x = 0; int y = 0; for(BufferedImage image : images) { gx.drawImage(image, x, y, null); //increment x += info.width; if(x >= width) { x = 0; y += info.height; } } //write image file = new File(outputFolder,tilesetFilename); ImageIO.write(output, "png", file); } } public void optimize() { //remove unused images, and recalculate all indexes ArrayList<BufferedImage> keep = new ArrayList<BufferedImage>(); HashMap<Integer,Integer> swapMap = new HashMap<Integer,Integer>(); for(BaseTile tile : tileset.tiles) { for(int index : tile.imageList()) { BufferedImage img = images.get(index); int nindex = keep.indexOf(img); if(nindex == -1) { nindex = keep.size(); keep.add(img); } if(index != nindex) { swapMap.put(index, nindex); } } } for(BaseTile tile : tileset.tiles) { tile.replaceIndexes(swapMap); } images.clear(); images.addAll(keep); } public static GFX load(File file) { try { return _load(file); } catch (IOException e) { e.printStackTrace(); } return null; } private static GFX _load(File src) throws IOException { GFX gfx = new GFX(); String jsonPath = ""; String tilesetPath = ""; for(String line : Files.getFileLines(src)) { line = line.trim(); if(line.startsWith("#")) { continue; } else if(line.startsWith("NAME")) { gfx.name = line.substring(line.indexOf(':')+1).trim(); } else if(line.startsWith("VIEW")) { gfx.view = line.substring(line.indexOf(':')+1).trim(); } else if(line.startsWith("JSON")) { jsonPath = line.substring(line.indexOf(':')+1).trim(); } else if(line.startsWith("TILESET")) { tilesetPath = line.substring(line.indexOf(':')+1).trim(); } } File rootFile = src.getAbsoluteFile(); for(int upd = Strings.count(jsonPath, '/'); upd >= 0; upd--) { rootFile = rootFile.getParentFile(); } File jsonFile = new File(rootFile,jsonPath); File tilesetFile = new File(rootFile,tilesetPath); gfx.jsonFilename = jsonFile.getName(); gfx.tilesetFilename = tilesetFile.getName(); gfx.tileset = readJson(jsonFile); TileInfo info = gfx.getTileInfo(); //load tileset images and cut them up BufferedImage tileset = ImageIO.read(tilesetFile); //go through the tileset and cut up each image into a tile //shove that tile into the images array gfx.images.addAll(cutImageIntoTiles(tileset,info.width,info.height)); return gfx; } public static List<BufferedImage> cutImageIntoTiles(BufferedImage image, int width, int height) { ArrayList<BufferedImage> list = new ArrayList<BufferedImage>(); int imgWidth = image.getWidth(); int imgHeight = image.getHeight(); for(int y = 0; y < imgHeight; y += height) { for(int x = 0; x < imgWidth; x += width) { list.add(image.getSubimage(x, y, width, height)); } } return list; } private static Tileset readJson(File jsonFile) throws IOException { Reader reader = new BufferedReader(new FileReader(jsonFile)); Tileset tileset = new Gson().fromJson(reader, Tileset.class); reader.close(); return tileset; } public void addTile(GFX src, BaseTile tile) { tile = tile.copy(); importTileImages(src,tile); tileset.tiles.add(tile); } public void replaceTile(BaseTile current, GFX src, BaseTile replacement) { replacement = replacement.copy(); importTileImages(src,replacement); current.id = replacement.id; current.fg = replacement.fg; current.bg = replacement.bg; current.rotates = replacement.rotates; current.multitile = replacement.multitile; current.additional_tiles = replacement.additional_tiles; } private void importTileImages(GFX src, BaseTile tile) { List<Integer> srcIndex = tile.imageList(); HashMap<Integer,Integer> map = new HashMap<Integer,Integer>(); for(int index : srcIndex) { BufferedImage img = src.images.get(index); int nindex = images.indexOf(img); if(nindex == -1) { nindex = images.size(); images.add(img); } if(index != nindex) { map.put(index, nindex); } } tile.replaceIndexes(map); } public void dispose() { //clear all image resources for(BufferedImage img : images) { img.flush(); } images.clear(); images = null; tileset.tile_info = null; tileset.tiles.clear(); tileset.tiles = null; tileset = null; } }