Yeah I know :| I was just curious if a version of this app (beta or otherwise) had been circulated in any fashion.
This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.
« »
class Array
def nitems
count{|x| !x.nil?}
end
end
case a
when 1..5:
puts "It's between 1 and 5"
when 6:
puts "It's 6"
when String:
puts "You passed a string"
else
puts "You gave me #{a} -- I have no idea what to do with that."
end
code converter not found (ASCII-8BIT to UTF-8)
// Written by Eclipse
/*
// BEGIN__HARVEST_EXCEPTION_ZSTRING
<javascriptresource>
<name>Create Spritesheet from Charset animation</name>
<category>Game Development</category>
</javascriptresource>
// END__HARVEST_EXCEPTION_ZSTRING
*/
// enable double clicking from the Macintosh Finder or the Windows Explorer
#target photoshop
// debugging code
// debug level: 0-2 (0:disable, 1:break on error, 2:break at beginning)
/*
debugger;
$.level = 1;
*/
////////////////////////////////////////////////////
// script configuration
////////////////////////////////////////////////////
function configObj()
{
// document configuration
this.document = {};
// link of valid document suffixes
this.document.suffix = {
"D" : "D",
"L" : "L",
"R" : "R",
"U" : "U",
"LR": "LR",
"_" : "-",
};
// spritesheet configuration
this.spritesheet = {};
this.spritesheet.cols = 4;
this.spritesheet.rows = 4;
this.spritesheet.colWidth = 32;
this.spritesheet.rowHeight = 48;
this.spritesheet.xOffsetFormula = "Math.ceil( (config.spritesheet.colWidth - {WIDTH})/2 )";
this.spritesheet.yOffsetFormula = "(config.spritesheet.rowHeight - {HEIGHT})";
this.spritesheet.animOrder = [this.document.suffix["D"], this.document.suffix["L"], this.document.suffix["R"], this.document.suffix["U"]];
this.spritesheet.solidBackground = false;
// current animation configuration
this.current = {};
// detect the name of the current document
this.current.docName = app.activeDocument.name.replace(".psd", "");
for (var i in this.document.suffix) {
this.current.docName = this.current.docName.replace(this.document.suffix[i], "");
}
// create a list of the relevant animations
this.current.rootPath = app.activeDocument.path;
this.current.tempPath = "Z:/tmp";
this.current.savePath = this.current.rootPath;
this.current.docPaths = {};
for (var sufx in this.document.suffix) {
this.current.docPaths[this.document.suffix[sufx]] = this.current.rootPath+"/"+this.current.docName+this.document.suffix["_"]+this.document.suffix[sufx]+".psd";
}
delete this.current.docPaths[this.document.suffix["_"]];
// create a list of the animations that exist
this.current.validDocs = {};
for (var doc in this.current.docPaths) {
var df = File(this.current.docPaths[doc]);
if (df.exists) {
this.current.validDocs[doc] = this.current.docPaths[doc];
}
}
}
////////////////////////////////////////////////////
// starting dialog window
// config : the config object (passed by reference)
////////////////////////////////////////////////////
function dialogStart(cfg)
{
// create new window
var dlg = new Window("dialog", "Generate RMXP Charset from Photoshop animation files", [100, 100, 700, 500]);
// add Animation Info panel
dlg.msgPnl = dlg.add("panel", [15, 15, 580, 220], "Animation File Info:");
// solid bg?
dlg.msgPnl.aiSolidBgText = dlg.msgPnl.add("StaticText", [20, 20, 300, 60], "Do the animation files have a solid background?");
dlg.msgPnl.aiSolidBg = dlg.msgPnl.add("CheckBox", [300, 17, 320, 45], cfg.spritesheet.solidBackground);
dlg.msgPnl.aiSolidBgWarningText1 = dlg.msgPnl.add("StaticText", [340, 20, 550, 40], "If the animation files have a");
dlg.msgPnl.aiSolidBgWarningText2 = dlg.msgPnl.add("StaticText", [340, 40, 550, 60], "transparent background, the script");
dlg.msgPnl.aiSolidBgWarningText3 = dlg.msgPnl.add("StaticText", [340, 60, 550, 80], "will take much longer to execute.");
// detected files
dlg.msgPnl.detectedFilesTextPnl = dlg.add("panel", [35, 85, 300, 200], "Files Detected:");
// list detected files
var y = 0;
for (var doc in cfg.current.validDocs) {
dlg.msgPnl.detectedFilesTextPnl.add( "StaticText", [20, y+20, 100, y+70], cfg.current.validDocs[doc].substr(cfg.current.validDocs[doc].lastIndexOf("/")+1) );
y += 20;
}
// add New Spritesheet Info panel
dlg.ssPnl = dlg.add("panel", [15, 240, 580, 340], "New Spritesheet Info:");
// num spritesheet columns
dlg.ssPnl.ssColsText1 = dlg.ssPnl.add("StaticText", [20, 22, 120, 40], "Column Width:");
dlg.ssPnl.ssCols = dlg.ssPnl.add("EditText", [125, 20, 160, 40], cfg.spritesheet.colWidth);
dlg.ssPnl.ssColsText2 = dlg.ssPnl.add("StaticText", [165, 22, 180, 40], "px");
// num spritesheet rows
dlg.ssPnl.ssRowsText1 = dlg.ssPnl.add("StaticText", [20, 52, 120, 70], "Row Height:");
dlg.ssPnl.ssRows = dlg.ssPnl.add("EditText", [125, 50, 160, 70], cfg.spritesheet.rowHeight);
dlg.ssPnl.ssRowsText2 = dlg.ssPnl.add("StaticText", [165, 52, 180, 40], "px");
// add accept button...
dlg.beginBtn = dlg.add("button", [195, 360, 295, 380], "Begin", {name:"ok"});
// add canel button.
dlg.cancelBtn = dlg.add("button", [315, 360, 415, 380], "Cancel", {name:"ok"});
// when BEGIN is clicked
dlg.beginBtn.onClick = function() {
config.spritesheet.colWidth = parseInt(dlg.ssPnl.ssCols.text);
config.spritesheet.rowHeight = parseInt(dlg.ssPnl.ssRows.text);
alert(dlg.msgPnl.aiSolidBg.value);
config.spritesheet.solidBackground = (dlg.msgPnl.aiSolidBg.value == "true") ? true : false;
/*// insert author into active documentinfo...
activeDocument.info.title = dlg.msgPnl.msgAuthor.text;
// insert copyright notice into active documentinfo...
activeDocument.info.copyrightNotice = dlg.msgPnl.msgCpyVermerk.text;*/
this.ena = true;
this.parent.close(0);
}
// when CANCEL is clicked
dlg.cancelBtn.onClick = function() {
this.ena = false;
this.parent.close(0);
//ObjectCraft();
}
// show dialog window
dlg.show();
}
////////////////////////////////////////////////////
// clean up a path name
// pathStr : the path
////////////////////////////////////////////////////
function cleanPathStr(pathStr)
{
var pth = pathStr;
while (pth != pth.replace("//", "/")) {
pth = pth.replace("//", "/");
}
return pth;
}
////////////////////////////////////////////////////
// close all open documents
// save_options : file save options
////////////////////////////////////////////////////
function closeAllDocuments(save_options)
{
if (save_options == null) {
save_options = SaveOptions.PROMPTTOSAVECHANGES;
}
while (app.documents.length) {
app.activeDocument.close(save_options);
}
}
////////////////////////////////////////////////////
// export image in bitmap format
// path : the path to the new file
// filename : the new files name
////////////////////////////////////////////////////
function exportImageToBMP(path, filename)
{
try
{
var pth = cleanPathStr(path+"/"+filename);
imgFile = new File(pth);
var options = new BMPSaveOptions();
//options.quality = 100;
options.depth = BMPDepthType.SIXTEEN;
options.rleCompression = false;
//options.alphaChannels = true;
app.activeDocument.saveAs(imgFile, options, true);
}
catch (e)
{ // display error
alert("Error encountered when saving the image! \r\r" + e);
return; // quit
}
}
////////////////////////////////////////////////////
// export image in PNG format (24-bit)
// path : the path to the new file
// filename : the new files name
////////////////////////////////////////////////////
function saveForWebPNG(path, filename)
{
var opts, file, p;
opts = new ExportOptionsSaveForWeb();
opts.format = SaveDocumentType.PNG;
opts.PNG8 = false;
opts.quality = 100;
if (filename.length > 27) {
p = cleanPathStr(path+"/temp.png");
file = new File(p);
app.activeDocument.exportDocument(file, ExportType.SAVEFORWEB, opts);
file.rename(filename + ".png");
}
else {
p = cleanPathStr(path+"/"+filename+".png");
file = new File(p);
app.activeDocument.exportDocument(file, ExportType.SAVEFORWEB, opts);
}
}
////////////////////////////////////////////////////
// transform - flip layer
// type : 0 = Horizontal, 1 = Vertical
////////////////////////////////////////////////////
function flipLayer(layer, type)
{
var x_scl, y_scl;
switch (type) {
case 0:
x_scl = -100;
y_scl = 100;
break;
case 1:
x_scl = 100;
y_scl = -100;
break;
}
layer.resize(new UnitValue(x_scl,'%'), new UnitValue(y_scl,'%'));
}
////////////////////////////////////////////////////
// transform - flip layer
// lyr : a layer object
// x : x position (pixels)
// y : y position (pixels)
////////////////////////////////////////////////////
function positionLayer(lyr, x, y)
{
// if can not move layer return
if(lyr.iisBackgroundLayer || lyr.positionLocked) return
// get the layer bounds
var layerBounds = lyr.bounds;
// get top left position
var layerX = layerBounds[0].value;
var layerY = layerBounds[1].value;
// the difference between where layer needs to be and is now
var deltaX = x-layerX;
var deltaY = y-layerY;
// move the layer into position
lyr.translate(deltaX, deltaY);
}
////////////////////////////////////////////////////
// calculate spritesheet frame offsets
// fh : file handle
// cfg : the config object
// o : the offset object (p: x,y)
////////////////////////////////////////////////////
function calculateFrameOffsets(fh, cfg, o)
{
if (!(o instanceof Object)) {
var o = {};
o.x = 0;
o.y = 0;
}
// if the animations have a solid background,
// no offset is needed
if (cfg.spritesheet.solidBackground === true) {
o.x = 0;
o.y = 0;
} else {
// if the animations have a transparent background,
// we must scan every pixel of each frame to determine the pixel offset
var sampler = fh.colorSamplers.add([0, 0]);
framePixelCheck_X:
for (var px = 0; px < fh.width; px ++) {
for (var py = 0; py < fh.height; py++) {
sampler.move([UnitValue(px, "px"), UnitValue(py, "px")]);
var pColor = undefined;
// try to grab pixel data for [px,py]
try {
pColor = sampler.color;
// if there is no pixel at [px,py] , exception will be thrown
} catch(err) { }
// if there is a pixel at [px,py]
if (pColor != undefined) {
// a pixel exists
o.x = px;
break framePixelCheck_X;
} else { // no pixel at [px,py]
continue;
}
}
}
framePixelCheck_Y:
for (var py = 0; py < fh.height; py++) {
for (var px = 0; px < fh.width; px ++) {
sampler.move([UnitValue(px, "px"), UnitValue(py, "px")]);
var pColor = undefined;
// try to grab pixel data for [px,py]
try {
pColor = sampler.color;
// if there is no pixel at [px,py] , exception will be thrown
} catch(err) { }
// if there is a pixel at [px,py]
if (pColor != undefined) {
// a pixel exists
o.y = py;
break framePixelCheck_Y;
} else { // no pixel at [px,py]
continue;
}
}
}
}
}
////////////////////////////////////////////////////
// main method
////////////////////////////////////////////////////
function main()
{
// initialize config
var config = new configObj();
// bring up starting dialog
dialogStart(config);
app.displayDialogs = DialogModes.NO;
closeAllDocuments();
// open only relevant animation files
var doc;
for (var idx in config.current.validDocs) {
doc = File(config.current.validDocs[idx]);
if (doc.exists) {
var f = open(doc);
} else {
delete config.document.suffix[idx];
}
}
// save all files as animated gif's
var animFiles = [];
for (var i = 0; i < app.documents.length; i++) {
// keep track of file properties
app.activeDocument = app.documents[i];
var fobj = {};
fobj.filename = app.documents[i].name.replace(".psd", "");
fobj.file_ext = ".gif";
fobj.path = config.current.tempPath+"/"+fobj.filename+fobj.file_ext;
animFiles.push(fobj);
// delete the file if it already exists
var aFile = File(fobj.path);
aFile.remove();
// save for web options
var options = new ExportOptionsSaveForWeb();
options.ditherAmount = 0;
options.dither = Dither.NOISE;
options.palette = Palette.LOCALADAPTIVE;
options.format = SaveDocumentType.COMPUSERVEGIF;
/*options.format = SaveDocumentType.COMPUSERVEGIF;
options.colors = 256;
options.dither = Dither.NONE;
options.ditherAmount = 100;
options.palette = Palette.LOCALSELECTIVE;
options.interlaced = true;
options.lossy = 0;*/
// export the image
app.activeDocument.exportDocument(aFile, ExportType.SAVEFORWEB, options);
}
closeAllDocuments(SaveOptions.DONOTSAVECHANGES);
// open only relevant animation files (open saved animated gifs)
var animFrameFiles = [];
for (var i = 0; i < animFiles.length; i++) {
// for each animation file
var cur_file = open(File(animFiles[i].path));
app.activeDocument = cur_file;
// hide all layers first
var layers = app.activeDocument.layers;
for (var j = 0; j < layers.length; j++) {
try {
layers[j].visible = false;
} catch(err) { }
}
// export each layer as a seperate image
for (var j = layers.length-1; j >= 0; j--) {
var flipAndRepeat = false;
app.activeDocument.activeLayer = layers[j];
try {
app.activeDocument.activeLayer.visible = true;
// face direction
var basefn = animFiles[i].filename.substring(0, animFiles[i].filename.indexOf(config.document.suffix["_"]));
var face_dir = animFiles[i].filename.substring(animFiles[i].filename.indexOf(config.document.suffix["_"])+1);
var aframe = (layers.length-1) - j;
// if the animation file is Left/Right, save Left facing frame first
if (face_dir == config.document.suffix["LR"]) {
flipAndRepeat = true;
face_dir = config.document.suffix["L"];
}
// save frame as PNG
var export_fname = basefn + config.document.suffix["_"] + face_dir + aframe;
saveForWebPNG(config.current.tempPath, export_fname);
// keep track of saved images
if (!(animFrameFiles[face_dir] instanceof Array)) {
animFrameFiles[face_dir] = [];
}
animFrameFiles[face_dir][aframe] = config.current.tempPath+"/"+export_fname+".png";
// if the animation file is Left/Right, save Right facing frame
if (flipAndRepeat === true) {
flipLayer(app.activeDocument.activeLayer, 0);
var r_fname = basefn + config.document.suffix["_"] + config.document.suffix["R"] + aframe;
saveForWebPNG(config.current.tempPath, r_fname);
if (!(animFrameFiles[config.document.suffix["R"]] instanceof Array)) {
animFrameFiles[config.document.suffix["R"]] = [];
}
animFrameFiles[config.document.suffix["R"]][aframe] = config.current.tempPath+"/"+r_fname+".png";
}
app.activeDocument.activeLayer.visible = false;
} catch(err) { }
}
cur_file.close(SaveOptions.DONOTSAVECHANGES);
// export visible layers to seperate files
//$.evalFile("C:/Program Files/Adobe/Adobe Photoshop CS5 (64 Bit)/Presets/Scripts/Export Layers To Files.jsx");
}
// create a new document and insert the animation frames
// create document
var charsetWidth = config.spritesheet.cols * config.spritesheet.colWidth;
var charsetHeight = config.spritesheet.rows * config.spritesheet.rowHeight;
var charsetRef = app.documents.add(charsetWidth, charsetHeight, 300, "newCharset", NewDocumentMode.RGB, DocumentFill.TRANSPARENT);
// loop through animation frames
for (var i in config.spritesheet.animOrder) {
var wDirFrames = animFrameFiles[config.spritesheet.animOrder[i]];
for (var j in wDirFrames) {
// open frame
var aFile = open(File(wDirFrames[j]));
// duplicate layer into the new document
aFile.layers[0].duplicate(charsetRef);
// calculate frame offsets
var offset = {};
calculateFrameOffsets(aFile, config, offset);
// position the new layer properly
var new_x = j * config.spritesheet.colWidth;
var new_y = i * config.spritesheet.rowHeight;
//offset.x = 0;//eval(config.spritesheet.xOffsetFormula.replace("{WIDTH}", aFile.width));
//offset.y = 0;//eval(config.spritesheet.yOffsetFormula.replace("{HEIGHT}", aFile.height));
app.activeDocument = charsetRef;
positionLayer(charsetRef.layers[0], new_x+offset.x, new_y+offset.y);
// close frame
aFile.close(SaveOptions.DONOTSAVECHANGES);
}
}
// save new charset as PNG
saveForWebPNG(config.current.savePath, config.current.docName);
// cleanup - remove temp files
for (var i = 0; i < animFiles.length; i++) {
var f = File(animFiles[i].path);
f.remove();
}
for (var i in config.spritesheet.animOrder) {
for (var j in animFrameFiles[config.spritesheet.animOrder[i]]) {
var f = File(animFrameFiles[config.spritesheet.animOrder[i]][j]);
f.remove();
}
}
// end main method
}
// execute script
main();