mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-10 10:12:45 +00:00
Various improvements; options, version, info
Adds options to PNG importing so that any valid DMI file can be entirely built from PNG files and DMITool. Adds version string and "version" command Adds info command to get a list of states easily (the only way previously was to print the descriptor with "dmitool -vvvv verify $file" and parse with e.g. grep/sed)
This commit is contained in:
Binary file not shown.
@@ -419,6 +419,12 @@ public class DMI implements Comparator<IconState> {
|
||||
public void printInfo() {
|
||||
System.out.println(totalImages + " images, " + images.size() + " states, size "+w+"x"+h);
|
||||
}
|
||||
|
||||
public void printStateList() {
|
||||
for(IconState s: images) {
|
||||
System.out.println(s.getInfoLine());
|
||||
}
|
||||
}
|
||||
|
||||
@Override public boolean equals(Object obj) {
|
||||
if(obj == this) return true;
|
||||
|
||||
@@ -19,6 +19,21 @@ public class IconState {
|
||||
int loop;
|
||||
String hotspot;
|
||||
boolean movement;
|
||||
|
||||
public String getInfoLine() {
|
||||
String extraInfo = "";
|
||||
if(rewind) extraInfo += " rewind";
|
||||
if(frames != 1) {
|
||||
extraInfo += " loop(" + (loop==-1 ? "infinite" : loop) + ")";
|
||||
}
|
||||
if(hotspot != null) extraInfo += " hotspot('" + hotspot + "')";
|
||||
if(movement) extraInfo += " movement";
|
||||
if(extraInfo.equals("")) {
|
||||
return String.format("state \"%s\", %d dir(s), %d frame(s)", name, dirs, frames);
|
||||
} else {
|
||||
return String.format("state \"%s\", %d dir(s), %d frame(s),%s", name, dirs, frames, extraInfo);
|
||||
}
|
||||
}
|
||||
|
||||
@Override public IconState clone() {
|
||||
IconState is = new IconState(name, dirs, frames, images.clone(), delays==null ? null : delays.clone(), rewind, loop, hotspot, movement);
|
||||
@@ -148,7 +163,7 @@ public class IconState {
|
||||
out.end();
|
||||
}
|
||||
|
||||
public static IconState importFromPNG(DMI dmi, InputStream inS, String name) throws DMIException {
|
||||
public static IconState importFromPNG(DMI dmi, InputStream inS, String name, float[] delays, boolean rewind, int loop, String hotspot, boolean movement) throws DMIException {
|
||||
int w = dmi.w;
|
||||
int h = dmi.h;
|
||||
|
||||
@@ -192,15 +207,8 @@ public class IconState {
|
||||
}
|
||||
}
|
||||
|
||||
float[] delays = null;
|
||||
if(frames != 1) {
|
||||
delays = new float[frames];
|
||||
for(int i=0; i<delays.length; i++) {
|
||||
delays[i] = 1;
|
||||
}
|
||||
}
|
||||
//public IconState(String name, int dirs, int frames, Image[] images, float[] delays, boolean rewind, int loop, String hotspot, boolean movement) {
|
||||
return new IconState(name, dirs, frames, images, delays, false, -1, null, false);
|
||||
return new IconState(name, dirs, frames, images, delays, rewind, loop, hotspot, movement);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,40 +11,56 @@ import java.util.Set;
|
||||
public class Main {
|
||||
public static int VERBOSITY = 0;
|
||||
public static boolean STRICT = false;
|
||||
|
||||
public static final String VERSION = "v0.6 (7 Jan 2015)";
|
||||
|
||||
public static final String[] dirs = new String[] {
|
||||
"S", "N", "E", "W", "SE", "SW", "NE", "NW"
|
||||
};
|
||||
|
||||
|
||||
public static final String helpStr =
|
||||
"help\n" +
|
||||
"\tthis text\n" +
|
||||
|
||||
|
||||
"version\n" +
|
||||
"\tprint version and exit\n" +
|
||||
|
||||
"verify [file]\n" +
|
||||
"\tattempt to load the given file to check format\n" +
|
||||
|
||||
|
||||
"info [file]\n" +
|
||||
"\tprint information about [file], including a list of states\n" +
|
||||
|
||||
"diff [file1] [file2]\n" +
|
||||
"\tdiff between [file1] and [file2]\n" +
|
||||
|
||||
|
||||
"sort [file]\n" +
|
||||
"\tsort the icon_states in [file] into ASCIIbetical order\n" +
|
||||
|
||||
|
||||
"merge [base] [file1] [file2] [out]\n" +
|
||||
"\tmerge [file1] and [file2]'s changes from a common ancestor [base], saving the result in [out]\n" +
|
||||
"\tconflicts will be placed in [out].conflict.dmi\n" +
|
||||
|
||||
|
||||
"extract [file] [state] [out] {args}\n"+
|
||||
"\textract [state] from [file] in PNG format to [out]\n" +
|
||||
"\targs specify direction and frame; input 'f' followed by a frame specifier, and/or 'd' followed by a direction specifier\n" +
|
||||
"\tframe specifier can be a single number or number-number for a range\n" +
|
||||
"\tdirection specifier can be a single direction, or direction-direction\n" +
|
||||
"\tdirection can be 0-7 or S, N, E, W, SE, SW, NE, NW (non-case-sensitive)\n" +
|
||||
|
||||
"import [file] [state] [in]\n" +
|
||||
|
||||
"import [file] [state] [in] [options]\n" +
|
||||
"\timport a PNG image from [in] into [file], with the name [state]\n" +
|
||||
"\tinput should be in the same format given by the 'extract' command with no direction or frame arguments\n" +
|
||||
"\t(i.e. frames should be on the x-axis, and directions on the y)\n" +
|
||||
"\tpossible options:\n" +
|
||||
"\t nodup | nd | n : if the state [state] already exists in [file], replace it instead of append\n" +
|
||||
"\t rewind | rw | r : if there is more than one frame, the animation should be played forwards-backwards-forwards-[...]\n" +
|
||||
"\t loop | lp | l : loop the animation infinitely; equivalent to \"loopn -1\"\n" +
|
||||
"\t loopn N | lpn N | ln N : loop the animation N times; for infinite animations, use 'loop' or N = -1\n" +
|
||||
"\t movement | move | mov | m : [state] should be marked as a movement state\n" +
|
||||
"\t delays L | delay L | del L | d L : use the list L as a comma-separated list of delays (e.g. '1,1,2,2,1')\n" +
|
||||
"\t hotspot H | hs H | h H : use H as the hotspot for this state\n" +
|
||||
"";
|
||||
|
||||
|
||||
public static void main(String[] args) throws FileNotFoundException, IOException, DMIException {
|
||||
Deque<String> argq = new ArrayDeque<>();
|
||||
for(String s: args) {
|
||||
@@ -66,7 +82,7 @@ public class Main {
|
||||
argq.pollFirst();
|
||||
}
|
||||
String op = argq.pollFirst();
|
||||
|
||||
|
||||
switch(op) {
|
||||
case "diff": {
|
||||
if(argq.size() < 2) {
|
||||
@@ -76,7 +92,7 @@ public class Main {
|
||||
}
|
||||
String a = argq.pollFirst();
|
||||
String b = argq.pollFirst();
|
||||
|
||||
|
||||
if(VERBOSITY >= 0) System.out.println("Loading " + a);
|
||||
DMI dmi = doDMILoad(a);
|
||||
if(VERBOSITY >= 0) dmi.printInfo();
|
||||
@@ -96,11 +112,11 @@ public class Main {
|
||||
return;
|
||||
}
|
||||
String f = argq.pollFirst();
|
||||
|
||||
|
||||
if(VERBOSITY >= 0) System.out.println("Loading " + f);
|
||||
DMI dmi = doDMILoad(f);
|
||||
if(VERBOSITY >= 0) dmi.printInfo();
|
||||
|
||||
|
||||
if(VERBOSITY >= 0) System.out.println("Saving " + f);
|
||||
dmi.writeDMI(new FileOutputStream(f), true);
|
||||
break;
|
||||
@@ -118,26 +134,26 @@ public class Main {
|
||||
if(VERBOSITY >= 0) System.out.println("Loading " + baseF);
|
||||
DMI base = doDMILoad(baseF);
|
||||
if(VERBOSITY >= 0) base.printInfo();
|
||||
|
||||
|
||||
if(VERBOSITY >= 0) System.out.println("Loading " + aF);
|
||||
DMI aDMI = doDMILoad(aF);
|
||||
if(VERBOSITY >= 0) aDMI.printInfo();
|
||||
|
||||
|
||||
if(VERBOSITY >= 0) System.out.println("Loading " + bF);
|
||||
DMI bDMI = doDMILoad(bF);
|
||||
if(VERBOSITY >= 0) bDMI.printInfo();
|
||||
|
||||
|
||||
DMIDiff aDiff = new DMIDiff(base, aDMI);
|
||||
DMIDiff bDiff = new DMIDiff(base, bDMI);
|
||||
DMIDiff mergedDiff = new DMIDiff();
|
||||
DMI conflictDMI = new DMI(32, 32);
|
||||
|
||||
|
||||
Set<String> cf = aDiff.mergeDiff(bDiff, conflictDMI, mergedDiff, aF, bF);
|
||||
|
||||
|
||||
mergedDiff.applyToDMI(base);
|
||||
|
||||
|
||||
base.writeDMI(new FileOutputStream(mergedF));
|
||||
|
||||
|
||||
if(!cf.isEmpty()) {
|
||||
if(VERBOSITY >= 0) for(String s: cf) {
|
||||
System.out.println(s);
|
||||
@@ -160,10 +176,10 @@ public class Main {
|
||||
String file = argq.pollFirst(),
|
||||
state = argq.pollFirst(),
|
||||
outFile = argq.pollFirst();
|
||||
|
||||
|
||||
DMI dmi = doDMILoad(file);
|
||||
if(VERBOSITY >= 0) dmi.printInfo();
|
||||
|
||||
|
||||
IconState is = dmi.getIconState(state);
|
||||
if(is == null) {
|
||||
System.out.println("icon_state '"+state+"' does not exist!");
|
||||
@@ -172,10 +188,10 @@ public class Main {
|
||||
// minDir, Maxdir, minFrame, Maxframe
|
||||
int mDir=0, Mdir=is.dirs-1;
|
||||
int mFrame=0, Mframe=is.frames-1;
|
||||
|
||||
|
||||
while(argq.size() > 1) {
|
||||
String arg = argq.pollFirst();
|
||||
|
||||
|
||||
switch(arg) {
|
||||
case "d":
|
||||
case "dir":
|
||||
@@ -247,29 +263,105 @@ public class Main {
|
||||
String dmiFile = argq.pollFirst(),
|
||||
stateName = argq.pollFirst(),
|
||||
pngFile = argq.pollFirst();
|
||||
|
||||
|
||||
boolean noDup = false;
|
||||
if(!argq.isEmpty()) {
|
||||
switch(argq.pollFirst().toLowerCase()) {
|
||||
boolean rewind = false;
|
||||
int loop = 0;
|
||||
boolean movement = false;
|
||||
String hotspot = null;
|
||||
float[] delays = null;
|
||||
while(!argq.isEmpty()) {
|
||||
String s = argq.pollFirst();
|
||||
switch(s.toLowerCase()) {
|
||||
case "nodup":
|
||||
case "nd":
|
||||
case "n":
|
||||
noDup = true;
|
||||
break;
|
||||
case "rewind":
|
||||
case "rw":
|
||||
case "r":
|
||||
rewind = true;
|
||||
break;
|
||||
case "loop":
|
||||
case "lp":
|
||||
case "l":
|
||||
loop = -1;
|
||||
break;
|
||||
case "loopn":
|
||||
case "lpn":
|
||||
case "ln":
|
||||
if(!argq.isEmpty()) {
|
||||
String loopTimes = argq.pollFirst();
|
||||
try {
|
||||
loop = Integer.parseInt(loopTimes);
|
||||
} catch(NumberFormatException nfe) {
|
||||
System.out.println("Illegal number '" + loopTimes + "' as argument to '" + s + "'!");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
System.out.println("Argument '" + s + "' requires a numeric argument following it!");
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case "movement":
|
||||
case "move":
|
||||
case "mov":
|
||||
case "m":
|
||||
movement = true;
|
||||
break;
|
||||
case "delays":
|
||||
case "delay":
|
||||
case "del":
|
||||
case "d":
|
||||
if(!argq.isEmpty()) {
|
||||
String delaysString = argq.pollFirst();
|
||||
String[] delaysSplit = delaysString.split(",");
|
||||
delays = new float[delaysSplit.length];
|
||||
for(int i=0; i<delaysSplit.length; i++) {
|
||||
try {
|
||||
delays[i] = Integer.parseInt(delaysSplit[i]);
|
||||
} catch(NumberFormatException nfe) {
|
||||
System.out.println("Illegal number '" + delaysSplit[i] + "' as argument to '" + s + "'!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
System.out.println("Argument '" + s + "' requires a list of delays (in the format 'a,b,c,d,[...]') following it!");
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case "hotspot":
|
||||
case "hs":
|
||||
case "h":
|
||||
if(!argq.isEmpty()) {
|
||||
hotspot = argq.pollFirst();
|
||||
} else {
|
||||
System.out.println("Argument '" + s + "' requires a hotspot string following it!");
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
System.out.println("Unknown import argument '" + s + "', ignoring.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(VERBOSITY >= 0) System.out.println("Loading " + dmiFile);
|
||||
DMI toImportTo = doDMILoad(dmiFile);
|
||||
if(VERBOSITY >= 0) toImportTo.printInfo();
|
||||
//public static IconState importFromPNG(DMI dmi, InputStream inS, String name) throws DMIException {
|
||||
IconState is = IconState.importFromPNG(toImportTo, new FileInputStream(pngFile), stateName);
|
||||
|
||||
|
||||
if(!(noDup && toImportTo.setIconState(is))) {
|
||||
IconState is = IconState.importFromPNG(toImportTo, new FileInputStream(pngFile), stateName, delays, rewind, loop, hotspot, movement);
|
||||
|
||||
if(noDup) {
|
||||
if(!toImportTo.setIconState(is)) {
|
||||
toImportTo.addIconState(null, is);
|
||||
}
|
||||
} else {
|
||||
toImportTo.addIconState(null, is);
|
||||
}
|
||||
|
||||
|
||||
if(VERBOSITY >= 0) toImportTo.printInfo();
|
||||
|
||||
|
||||
if(VERBOSITY >= 0) System.out.println("Saving " + dmiFile);
|
||||
toImportTo.writeDMI(new FileOutputStream(dmiFile));
|
||||
break;
|
||||
@@ -286,6 +378,22 @@ public class Main {
|
||||
if(VERBOSITY >= 0) v.printInfo();
|
||||
break;
|
||||
}
|
||||
case "info": {
|
||||
if(argq.size() < 1) {
|
||||
System.out.println("Insufficient arguments for command!");
|
||||
System.out.println(helpStr);
|
||||
return;
|
||||
}
|
||||
String infoFile = argq.pollFirst();
|
||||
if(VERBOSITY >= 0) System.out.println("Loading " + infoFile);
|
||||
DMI info = doDMILoad(infoFile);
|
||||
info.printInfo();
|
||||
info.printStateList();
|
||||
break;
|
||||
}
|
||||
case "version":
|
||||
System.out.println(VERSION);
|
||||
return;
|
||||
default:
|
||||
System.out.println("Command '" + op + "' not found!");
|
||||
case "help":
|
||||
@@ -293,7 +401,7 @@ public class Main {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int parseDir(String s, IconState is) {
|
||||
try {
|
||||
int i = Integer.parseInt(s);
|
||||
@@ -319,7 +427,7 @@ public class Main {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int parseFrame(String s, IconState is) {
|
||||
try {
|
||||
int i = Integer.parseInt(s);
|
||||
@@ -334,7 +442,7 @@ public class Main {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static DMI doDMILoad(String file) {
|
||||
try {
|
||||
DMI dmi = new DMI(file);
|
||||
|
||||
Reference in New Issue
Block a user