Created
October 1, 2010 12:46
-
-
Save oberhamsi/606161 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* @fileOverview | |
* | |
* Montage single sprite images from Reiner's Tileset into a single spritemap. | |
* | |
* Every Sprite has multiple images: one per animation (e.g., walk, shoot, etc). | |
* Each row of the spritemap corresponds to a direction (n,s,w) in alphabetical order. | |
* The columns are the steps of a particular animation for a direction. | |
* | |
* requires ImageMagick | |
*/ | |
var {list, join, write, list, isFile, isDirectory} = require('fs'); | |
var {system, command} = require('ringo/subprocess'); | |
var sys = require('system'); | |
var strings = require('ringo/utils/strings'); | |
var arrays = require('ringo/utils/arrays'); | |
var $f = require('ringo/utils/strings').format; | |
//var {Parser} = require('ringo/args'); | |
var {get} = require('ringo/httpclient'); | |
// "tipping over sw0011.png" | |
// "stopped n0001.png" | |
var FILE_REGEX = /(.*) ([^0-9]{1,2})([^\.]+)\.png/; | |
var RAW_FILE_REGEX = /(.*) ([^0-9]{1,2})([^\.]+)\.bmp/; | |
/** | |
* Montage animations as described by output of `getAnimationInfo()` in | |
* directory `dir` into a single spritemap. | |
*/ | |
function montage(dir, animations) { | |
for each (var animation in animations) { | |
if (isNaN(animation.count)) { | |
print ('invalid animation count ', animation.toSource()); | |
continue; | |
} | |
var tilingArgs = ['-background', 'none', | |
'-geometry', '+0+0', | |
'-tile', (animation.count + 1) + 'x', | |
animation.name + '.png' | |
]; | |
var allArgs = ["montage"].concat(animation.files).concat(tilingArgs).concat({dir: dir}); | |
system.apply(this, allArgs); | |
} | |
return; | |
}; | |
/** | |
* Returns #rgb string for top left pixel in image | |
*/ | |
function getBackgroundColor(file) { | |
var args = ['convert', file, '-crop', '1x1+0+0','-unique-colors', 'txt:-']; | |
var output = command.apply(this, args); | |
var matches = output.match('(#[^ ]+)') | |
return matches[1]; | |
}; | |
/** | |
* @returns {Object} an object describing the animations defined by the image files. | |
*/ | |
function getAnimationInfo(dir) { | |
var files = list(dir); | |
var animations = {}; | |
files.forEach(function(file) { | |
var parts = file.match(FILE_REGEX); | |
if (!parts) return; | |
var animation = parts[1]; | |
var direction = parts[2]; | |
var number = parseInt(parts[3], 10); | |
var cani = animations[animation]; | |
if (cani === undefined) { | |
cani = animations[animation] = { | |
name: animation, | |
count: number, | |
directions: [direction], | |
files: [] | |
} | |
} | |
cani.files.push(file); | |
if (!arrays.contains(cani.directions, direction)) { | |
cani.directions.push(direction); | |
} | |
if (number > cani.count) { | |
cani.count = number; | |
} | |
}); | |
for each (var animation in animations) { | |
animation.files.sort(); | |
}; | |
return animations; | |
}; | |
/** | |
* download url to file | |
*/ | |
function download(url, file) { | |
var response = get(url); | |
write(file, response.contentBytes, 'wb'); | |
return; | |
}; | |
/** | |
* unpack file to dir | |
*/ | |
function unpack(file, dir) { | |
command.apply(this, | |
['unzip','-n', file, '-d', dir] | |
); | |
}; | |
/** | |
* recursively fix file encoding to utf8 in diretory | |
*/ | |
function fixFileEncoding(dir) { | |
var args = ['convmv', '-r', '--notest', '-f', 'latin1', '-t', 'utf8', './', {dir: dir}]; | |
command.apply(this, args); | |
return; | |
}; | |
/** | |
* convert bmp found in directory to png with background being transparent | |
*/ | |
function toTransparentPng(dir) { | |
var files = list(dir); | |
var color = getBackgroundColor(join(dir, files[1])); | |
var args = ['mogrify', '-transparent', color, '-format', 'png', '*bmp', {dir: dir}]; | |
system.apply(this, args); | |
} | |
/** | |
* get directories below given directory or directory itself, which hold animation pictures | |
*/ | |
function getAnimationDirectories(root) { | |
var directories = list(root); | |
var animationDirectories = []; | |
if (directories.length && isFile(join(root, directories[1]))) { | |
animationDirectories = [root]; | |
} else { | |
directories.forEach(function(directory) { | |
if (!isDirectory(directory)) return; | |
// try first file in directory | |
var potentialFiles = list(join(root, directory)); | |
var isAnimation = potentialFiles.some(function(file) { | |
return file.match(RAW_FILE_REGEX) !== null; | |
}); | |
if (isAnimation) { | |
animationDirectories.push(join(root, directory)); | |
} | |
}); | |
} | |
return animationDirectories; | |
}; | |
function main(args) { | |
/** | |
* Print script help | |
*/ | |
function help() { | |
print('Create a spritemap from Reiners Tileset'); | |
print('Usage:'); | |
print(' ringo ' + script + ' download url'); | |
print('Options:'); | |
print (parser.help()); | |
return; | |
}; | |
var script = args.shift(); | |
// option: --idle stopped --noloop dying ... | |
// provide good defaults and search for them in file | |
// var parser = new Parser(); | |
// parser.addOption('s', 'source', 'repository', 'Path to repository'); | |
// var opts = parser.parse(args); | |
// FIXME rename stopped and other broken? | |
var zipUrl = args.shift(); | |
var zipFile = join(module.directory, zipUrl.split('/').slice(-1)[0]); | |
print ('downloading'); | |
download(zipUrl, zipFile); | |
var zipDir = join(zipFile.split('.').slice(0,-1), '/'); | |
print ('unpacking'); | |
unpack(zipFile, zipDir); | |
fixFileEncoding(zipDir); | |
print ('to transparent png'); | |
var animationDirectories = getAnimationDirectories(zipDir); | |
animationDirectories.forEach(function(ad) { | |
toTransparentPng(ad); | |
}); | |
print ('composing spritemap'); | |
animationDirectories.forEach(function(animationDirectory) { | |
var animations = getAnimationInfo(animationDirectory); | |
montage(animationDirectory, animations); | |
}); | |
// drop T_ prefix, replace %20, drop file ext | |
var fileName = zipFile.split('.').slice(-1)[0]; | |
var spriteName = fileName.split('.')[0].replace('%20', '_').substr(2); | |
print (spriteName); | |
var targetDir = join(module.directory, 'animations', spriteName) | |
print (targetDir); | |
return; | |
}; | |
if (require.main == module.id) { | |
try { | |
main(sys.args); | |
} catch (error) { | |
print(error); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment