Shucks, that was a lot more complicated than I thought
The mod time of a target directory can't be reliably checked using the files, so we need to compare the modificaiton times of each source and destination image file as we go.
This commit is contained in:
committed by
Michael Bayne
parent
6ec4fb5c4f
commit
9647cfb968
@@ -77,24 +77,29 @@ public class BundleWriter
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests if the target is newer than the given time. Note that if we are in directory-mode,
|
* Tests if the target bundle is newer than the given time. Note that if we are in
|
||||||
* false is returned.
|
* directory-mode, false is returned.
|
||||||
*/
|
*/
|
||||||
public boolean isNewerThan (long newest)
|
public boolean isNewerThan (long newest)
|
||||||
{
|
{
|
||||||
if (_jar != null) {
|
if (_jar != null) {
|
||||||
return _target.lastModified() > newest;
|
return _target.lastModified() > newest;
|
||||||
} else {
|
} else {
|
||||||
File []files = _target.listFiles();
|
|
||||||
if (files == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
for (File file : files) {
|
|
||||||
if (file.lastModified() < newest) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
|
/**
|
||||||
|
* Tests if a given path within the target bundle is newer than a given time. Note that if
|
||||||
|
* we are in jar mode, false is returned.
|
||||||
|
*/
|
||||||
|
public boolean isPathNewerThan (String path, long newest)
|
||||||
|
{
|
||||||
|
if (_jar != null) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
File f = new File(_target, path);
|
||||||
|
return f.lastModified() > newest;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ import org.xml.sax.SAXException;
|
|||||||
import com.samskivert.io.PersistenceException;
|
import com.samskivert.io.PersistenceException;
|
||||||
import com.samskivert.io.StreamUtil;
|
import com.samskivert.io.StreamUtil;
|
||||||
import com.samskivert.util.HashIntMap;
|
import com.samskivert.util.HashIntMap;
|
||||||
|
import com.samskivert.util.IntMap;
|
||||||
|
|
||||||
import com.threerings.resource.FastImageIO;
|
import com.threerings.resource.FastImageIO;
|
||||||
|
|
||||||
@@ -131,6 +132,9 @@ public class TileSetBundler
|
|||||||
/** Loads images for the bundle. */
|
/** Loads images for the bundle. */
|
||||||
public final ImageProvider improv;
|
public final ImageProvider improv;
|
||||||
|
|
||||||
|
/** Modification time of the newest source file. */
|
||||||
|
public final long newestSource;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new writer.
|
* Creates a new writer.
|
||||||
*
|
*
|
||||||
@@ -138,11 +142,13 @@ public class TileSetBundler
|
|||||||
* @param bundle contains the tilesets we'd like to save out to the bundle.
|
* @param bundle contains the tilesets we'd like to save out to the bundle.
|
||||||
* @param improv the image provider.
|
* @param improv the image provider.
|
||||||
*/
|
*/
|
||||||
public Writer (BundleWriter bwriter, TileSetBundle bundle, ImageProvider improv)
|
public Writer (BundleWriter bwriter, TileSetBundle bundle, ImageProvider improv,
|
||||||
|
long newestSource)
|
||||||
{
|
{
|
||||||
this.bundle = bundle;
|
this.bundle = bundle;
|
||||||
this.bwriter = bwriter;
|
this.bwriter = bwriter;
|
||||||
this.improv = improv;
|
this.improv = improv;
|
||||||
|
this.newestSource = newestSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -399,7 +405,7 @@ public class TileSetBundler
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return new Writer(target, bundle, improv).imageBase(bundleDesc.getParent());
|
return new Writer(target, bundle, improv, newest).imageBase(bundleDesc.getParent());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -417,7 +423,29 @@ public class TileSetBundler
|
|||||||
// bundle till we're done iterating.
|
// bundle till we're done iterating.
|
||||||
HashIntMap<TileSet> toUpdate = new HashIntMap<TileSet>();
|
HashIntMap<TileSet> toUpdate = new HashIntMap<TileSet>();
|
||||||
while (iditer.hasNext()) {
|
while (iditer.hasNext()) {
|
||||||
int tileSetId = iditer.next().intValue();
|
processBundleImage(iditer.next().intValue(), target, toUpdate);
|
||||||
|
}
|
||||||
|
target.bundle.putAll(toUpdate);
|
||||||
|
|
||||||
|
writeUpdatedBundle(target);
|
||||||
|
|
||||||
|
// finally close up the jar file and call ourself done
|
||||||
|
target.bwriter.close();
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
// remove the incomplete jar file and rethrow the exception
|
||||||
|
target.bwriter.close();
|
||||||
|
if (!target.bwriter.delete()) {
|
||||||
|
log.warning("Failed to close botched bundle '" + target + "'.");
|
||||||
|
}
|
||||||
|
String errmsg = "Failed to create bundle " + target + ": " + e;
|
||||||
|
throw (IOException) new IOException(errmsg).initCause(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static void processBundleImage (
|
||||||
|
int tileSetId, Writer target, IntMap<TileSet> toUpdate) throws IOException
|
||||||
|
{
|
||||||
TileSet set = target.bundle.getTileSet(tileSetId);
|
TileSet set = target.bundle.getTileSet(tileSetId);
|
||||||
String imagePath = set.getImagePath();
|
String imagePath = set.getImagePath();
|
||||||
|
|
||||||
@@ -425,21 +453,29 @@ public class TileSetBundler
|
|||||||
if (imagePath == null) {
|
if (imagePath == null) {
|
||||||
log.warning("Tileset contains no image path " +
|
log.warning("Tileset contains no image path " +
|
||||||
"[set=" + set + "]. It ain't gonna work.");
|
"[set=" + set + "]. It ain't gonna work.");
|
||||||
continue;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
File ifile = new File(target.imageBase, imagePath);
|
||||||
|
long sourceTime = Math.max(target.newestSource, ifile.lastModified());
|
||||||
|
|
||||||
// if this is an object tileset, trim it
|
// if this is an object tileset, trim it
|
||||||
if (target.trim && (set instanceof ObjectTileSet)) {
|
if (target.trim && (set instanceof ObjectTileSet)) {
|
||||||
// set the tileset up with an image provider; we
|
|
||||||
// need to do this so that we can trim it!
|
|
||||||
set.setImageProvider(target.improv);
|
|
||||||
|
|
||||||
// add .raw if requested
|
// add .raw if requested
|
||||||
if (target.raw) {
|
if (target.raw) {
|
||||||
imagePath = adjustImagePath(imagePath);
|
imagePath = adjustImagePath(imagePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (target.bwriter.isPathNewerThan(imagePath, sourceTime)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
OutputStream dest = target.bwriter.startNewFile(imagePath);
|
OutputStream dest = target.bwriter.startNewFile(imagePath);
|
||||||
|
|
||||||
|
// set the tileset up with an image provider; we
|
||||||
|
// need to do this so that we can trim it!
|
||||||
|
set.setImageProvider(target.improv);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// create a trimmed object tileset, which will
|
// create a trimmed object tileset, which will
|
||||||
// write the trimmed tileset image to the target file
|
// write the trimmed tileset image to the target file
|
||||||
@@ -462,22 +498,22 @@ public class TileSetBundler
|
|||||||
} else {
|
} else {
|
||||||
// read the image file and convert it to our custom
|
// read the image file and convert it to our custom
|
||||||
// format in the bundle
|
// format in the bundle
|
||||||
File ifile = new File(target.imageBase, imagePath);
|
|
||||||
try {
|
try {
|
||||||
BufferedImage image = ImageIO.read(ifile);
|
BufferedImage image = ImageIO.read(ifile);
|
||||||
if (target.raw && FastImageIO.canWrite(image)) {
|
if (target.raw && FastImageIO.canWrite(image)) {
|
||||||
imagePath = adjustImagePath(imagePath);
|
imagePath = adjustImagePath(imagePath);
|
||||||
// NOTE: DirectoryTileSetBundler used to check the modification time
|
if (!target.bwriter.isPathNewerThan(imagePath, sourceTime)) {
|
||||||
// of the target image here. There may be something to it, but it
|
|
||||||
// looked unnecessary
|
|
||||||
OutputStream dest = target.bwriter.startNewFile(imagePath);
|
OutputStream dest = target.bwriter.startNewFile(imagePath);
|
||||||
set.setImagePath(imagePath);
|
set.setImagePath(imagePath);
|
||||||
FastImageIO.write(image, dest);
|
FastImageIO.write(image, dest);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
|
if (!target.bwriter.isPathNewerThan(imagePath, sourceTime)) {
|
||||||
OutputStream dest = target.bwriter.startNewFile(imagePath);
|
OutputStream dest = target.bwriter.startNewFile(imagePath);
|
||||||
FileInputStream imgin = new FileInputStream(ifile);
|
FileInputStream imgin = new FileInputStream(ifile);
|
||||||
StreamUtil.copy(imgin, dest);
|
StreamUtil.copy(imgin, dest);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
String msg = "Failure bundling image " + ifile +
|
String msg = "Failure bundling image " + ifile +
|
||||||
": " + e;
|
": " + e;
|
||||||
@@ -485,7 +521,16 @@ public class TileSetBundler
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
target.bundle.putAll(toUpdate);
|
|
||||||
|
protected static void writeUpdatedBundle (Writer target)
|
||||||
|
throws IOException
|
||||||
|
{
|
||||||
|
String meta = target.json != null ?
|
||||||
|
BundleUtil.METADATA_JSON_PATH : BundleUtil.METADATA_PATH;
|
||||||
|
|
||||||
|
if (target.bwriter.isPathNewerThan(meta, target.newestSource)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// now write a serialized representation of the tileset bundle
|
// now write a serialized representation of the tileset bundle
|
||||||
if (target.json != null) {
|
if (target.json != null) {
|
||||||
@@ -499,30 +544,17 @@ public class TileSetBundler
|
|||||||
array.add(tset);
|
array.add(tset);
|
||||||
}
|
}
|
||||||
|
|
||||||
// now write a serialized representation of the tileset bundle
|
OutputStream fout = target.bwriter.startNewFile(meta);
|
||||||
OutputStream fout = target.bwriter.startNewFile(BundleUtil.METADATA_JSON_PATH);
|
|
||||||
fout.write(array.toString().getBytes());
|
fout.write(array.toString().getBytes());
|
||||||
fout.close();
|
fout.close();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// object to the bundle jar file
|
|
||||||
ObjectOutputStream oout = new ObjectOutputStream(
|
ObjectOutputStream oout = new ObjectOutputStream(
|
||||||
target.bwriter.startNewFile(BundleUtil.METADATA_PATH));
|
target.bwriter.startNewFile(BundleUtil.METADATA_PATH));
|
||||||
oout.writeObject(target.bundle);
|
oout.writeObject(target.bundle);
|
||||||
oout.flush();
|
oout.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
// finally close up the jar file and call ourself done
|
|
||||||
target.bwriter.close();
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
// remove the incomplete jar file and rethrow the exception
|
|
||||||
target.bwriter.close();
|
|
||||||
if (!target.bwriter.delete()) {
|
|
||||||
log.warning("Failed to close botched bundle '" + target + "'.");
|
|
||||||
}
|
|
||||||
String errmsg = "Failed to create bundle " + target + ": " + e;
|
|
||||||
throw (IOException) new IOException(errmsg).initCause(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Replaces the image suffix with <code>.raw</code>. */
|
/** Replaces the image suffix with <code>.raw</code>. */
|
||||||
|
|||||||
Reference in New Issue
Block a user