mirror of
https://github.com/VOREStation/VOREStation.git
synced 2026-08-25 04:57:47 +01:00
Merge pull request #9807 from mwerezak/tailicons
Fixes unathi tail overlays
This commit is contained in:
Binary file not shown.
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 20 KiB |
Binary file not shown.
@@ -0,0 +1,94 @@
|
||||
""" Python 2.7 wrapper for dmitool.
|
||||
"""
|
||||
|
||||
import os
|
||||
from subprocess import Popen, PIPE
|
||||
|
||||
_JAVA_PATH = ["java"]
|
||||
_DMITOOL_CMD = ["-jar", "dmitool.jar"]
|
||||
|
||||
def _dmitool_call(*dmitool_args, **popen_args):
|
||||
return Popen(_JAVA_PATH + _DMITOOL_CMD + [str(arg) for arg in dmitool_args], **popen_args)
|
||||
|
||||
def _safe_parse(dict, key, deferred_value):
|
||||
try:
|
||||
dict[key] = deferred_value()
|
||||
except Exception as e:
|
||||
print "Could not parse property '%s': %s"%(key, e)
|
||||
return e
|
||||
return False
|
||||
|
||||
def version():
|
||||
""" Returns the version as a string. """
|
||||
stdout, stderr = _dmitool_call("version", stdout=PIPE).communicate()
|
||||
return str(stdout).strip()
|
||||
|
||||
def help():
|
||||
""" Returns the help text as a string. """
|
||||
stdout, stderr = _dmitool_call("help", stdout=PIPE).communicate()
|
||||
return str(stdout).strip()
|
||||
|
||||
def info(filepath):
|
||||
""" Totally not a hack that parses the output from dmitool into a dictionary.
|
||||
May break at any moment.
|
||||
"""
|
||||
subproc = _dmitool_call("info", filepath, stdout=PIPE)
|
||||
stdout, stderr = subproc.communicate()
|
||||
|
||||
result = {}
|
||||
data = stdout.split(os.linesep)[1:]
|
||||
#for s in data: print s
|
||||
|
||||
#parse header line
|
||||
if len(data) > 0:
|
||||
header = data.pop(0).split(",")
|
||||
#don't need to parse states, it's redundant
|
||||
_safe_parse(result, "images", lambda: int(header[0].split()[0].strip()))
|
||||
_safe_parse(result, "size", lambda: header[2].split()[1].strip())
|
||||
|
||||
#parse state information
|
||||
states = []
|
||||
for item in data:
|
||||
if not len(item): continue
|
||||
|
||||
stateinfo = {}
|
||||
item = item.split(",", 3)
|
||||
_safe_parse(stateinfo, "name", lambda: item[0].split()[1].strip(" \""))
|
||||
_safe_parse(stateinfo, "dirs", lambda: int(item[1].split()[0].strip()))
|
||||
_safe_parse(stateinfo, "frames", lambda: int(item[2].split()[0].strip()))
|
||||
if len(item) > 3:
|
||||
stateinfo["misc"] = item[3]
|
||||
|
||||
states.append(stateinfo)
|
||||
|
||||
result["states"] = states
|
||||
return result
|
||||
|
||||
def extract_state(input_path, output_path, icon_state, direction=None, frame=None):
|
||||
""" Extracts an icon state as a png to a given path.
|
||||
If provided direction should be a string, one of S, N, E, W, SE, SW, NE, NW.
|
||||
If provided frame should be a frame number or a string of two frame number separated by a dash.
|
||||
"""
|
||||
args = ["extract", input_path, icon_state, output_path]
|
||||
if direction is not None: args.extend(("direction" , str(direction)))
|
||||
if frame is not None: args.extend(("frame" , str(frame)))
|
||||
return _dmitool_call(*args)
|
||||
|
||||
def import_state(target_path, input_path, icon_state, replace=False, delays=None, rewind=False, loop=None, ismovement=False, direction=None, frame=None):
|
||||
""" Inserts an input png given by the input_path into the target_path.
|
||||
"""
|
||||
args = ["import", target_path, icon_state, input_path]
|
||||
|
||||
if replace: args.append("nodup")
|
||||
if rewind: args.append("rewind")
|
||||
if ismovement: args.append("movement")
|
||||
if delays: args.extend(("delays", ",".join(delays)))
|
||||
if direction is not None: args.extend(("direction", direction))
|
||||
if frame is not None: args.extend(("frame", frame))
|
||||
|
||||
if loop in ("inf", "infinity"):
|
||||
args.append("loop")
|
||||
elif loop:
|
||||
args.extend(("loopn", loop))
|
||||
|
||||
return _dmitool_call(*args)
|
||||
@@ -175,7 +175,7 @@ public class IconState {
|
||||
}
|
||||
int pxW = in.imgInfo.cols;
|
||||
int pxH = in.imgInfo.rows;
|
||||
int frames = pxW / w;
|
||||
int frames = pxW / w; //frames are read along the X axis, dirs along the Y, much like export.
|
||||
int dirs = pxH / h;
|
||||
|
||||
// make sure the size is an integer multiple
|
||||
@@ -203,7 +203,7 @@ public class IconState {
|
||||
px[bY][bX + 3]);
|
||||
}
|
||||
}
|
||||
images[imageY + imageX*dirs] = new NonPalettedImage(w, h, pixels);
|
||||
images[_getIndex(imageY, imageX, dirs)] = new NonPalettedImage(w, h, pixels);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,6 +211,38 @@ public class IconState {
|
||||
return new IconState(name, dirs, frames, images, delays, rewind, loop, hotspot, movement);
|
||||
|
||||
}
|
||||
|
||||
//Converts a desired dir and frame to an index into the images array.
|
||||
public int getIndex(int dir, int frame) {
|
||||
return _getIndex(dir, frame, dirs);
|
||||
}
|
||||
|
||||
private static int _getIndex(int dir, int frame, int totalDirs) {
|
||||
return dir + frame*totalDirs;
|
||||
}
|
||||
|
||||
public void insertDir(int dir, Image[] splice) {
|
||||
int maxFrame = frames < splice.length? frames: splice.length;
|
||||
for(int frameIdx = 0; frameIdx < maxFrame; frameIdx++) {
|
||||
insertImage(dir, frameIdx, splice[frameIdx]);
|
||||
}
|
||||
}
|
||||
|
||||
public void insertFrame(int frame, Image[] splice) {
|
||||
int maxDir = dirs < splice.length? dirs: splice.length;
|
||||
for(int dirIdx = 0; dirIdx < maxDir; dirIdx++) {
|
||||
insertImage(dirIdx, frame, splice[dirIdx]);
|
||||
}
|
||||
}
|
||||
|
||||
public void insertImage(int dir, int frame, Image splice) {
|
||||
if(frame < 0 || frame >= frames)
|
||||
throw new IllegalArgumentException("Provided frame is out of range: " + frame);
|
||||
if(dir < 0 || dir >= dirs)
|
||||
throw new IllegalArgumentException("Provided dir is out of range: " + dir);
|
||||
|
||||
images[getIndex(dir, frame)] = splice;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -244,6 +276,5 @@ public class IconState {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -59,6 +59,7 @@ public class Main {
|
||||
"\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" +
|
||||
"\t direction D | dir D : replaces D with the image from [in], instead of the entire state. D can be 0-7 or S, N, E, etc. If the state does not already exist, this is ignored\n" +
|
||||
"";
|
||||
|
||||
public static void main(String[] args) throws FileNotFoundException, IOException, DMIException {
|
||||
@@ -270,6 +271,8 @@ public class Main {
|
||||
boolean movement = false;
|
||||
String hotspot = null;
|
||||
float[] delays = null;
|
||||
String replaceDir = null;
|
||||
String replaceFrame = null;
|
||||
while(!argq.isEmpty()) {
|
||||
String s = argq.pollFirst();
|
||||
switch(s.toLowerCase()) {
|
||||
@@ -341,6 +344,24 @@ public class Main {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case "dir":
|
||||
case "direction":
|
||||
if(!argq.isEmpty()) {
|
||||
replaceDir = argq.pollFirst();
|
||||
} else {
|
||||
System.out.println("Argument '" + s + "' requires a direction argument following it!");
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case "f":
|
||||
case "frame":
|
||||
if(!argq.isEmpty()) {
|
||||
replaceFrame = argq.pollFirst();
|
||||
} else {
|
||||
System.out.println("Argument '" + s + "' requires a frame argument following it!");
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
System.out.println("Unknown import argument '" + s + "', ignoring.");
|
||||
break;
|
||||
@@ -352,12 +373,46 @@ public class Main {
|
||||
if(VERBOSITY >= 0) toImportTo.printInfo();
|
||||
IconState is = IconState.importFromPNG(toImportTo, new FileInputStream(pngFile), stateName, delays, rewind, loop, hotspot, movement);
|
||||
|
||||
if(noDup) {
|
||||
if(!toImportTo.setIconState(is)) {
|
||||
//image insertion
|
||||
if(replaceDir != null || replaceFrame != null) {
|
||||
|
||||
IconState targetIs = toImportTo.getIconState(stateName);
|
||||
if(targetIs == null) {
|
||||
System.out.println("'direction' or 'frame' specified and no icon state '" + stateName + "' found, aborting!");
|
||||
return;
|
||||
}
|
||||
if(is.images.length == 0) {
|
||||
System.out.println("'direction' or 'frame' specified and imported is empty, aborting!");
|
||||
return;
|
||||
}
|
||||
|
||||
if(!noDup) targetIs = targetIs.clone();
|
||||
|
||||
int dirToReplace, frameToReplace;
|
||||
if(replaceDir != null && replaceFrame != null) {
|
||||
frameToReplace = parseFrame(replaceFrame, targetIs);
|
||||
dirToReplace = parseDir(replaceDir, targetIs);
|
||||
targetIs.insertImage(dirToReplace, frameToReplace, is.images[0]);
|
||||
}
|
||||
else if(replaceDir != null) {
|
||||
dirToReplace = parseDir(replaceDir, targetIs);
|
||||
targetIs.insertDir(dirToReplace, is.images);
|
||||
}
|
||||
else if(replaceFrame != null) {
|
||||
frameToReplace = parseFrame(replaceFrame, targetIs);
|
||||
targetIs.insertFrame(frameToReplace, is.images);
|
||||
}
|
||||
|
||||
if(!noDup) toImportTo.addIconState(null, targetIs);
|
||||
}
|
||||
else {
|
||||
if(noDup) {
|
||||
if(!toImportTo.setIconState(is)) {
|
||||
toImportTo.addIconState(null, is);
|
||||
}
|
||||
} else {
|
||||
toImportTo.addIconState(null, is);
|
||||
}
|
||||
} else {
|
||||
toImportTo.addIconState(null, is);
|
||||
}
|
||||
|
||||
if(VERBOSITY >= 0) toImportTo.printInfo();
|
||||
|
||||
Reference in New Issue
Block a user