require 'RMagick'
class TilesTask
def task_instance
Rake::Task[ task_name ]
end
end
class Tile
attr_reader :name
def initialize name
@name = name
end
end
class Tileset < TilesTask
attr_reader :name, :path, :format, :variant, :width, :height, :fullpath, :fullpath
def initialize name, path, format, variant, width, height
@name = name
@path = path
@format = format
@variant = variant
@width = width
@height = height
@fullname = "#{@name}.#{@format}"
@fullpath = "#{@path}/#{@fullname}"
if not File.exists? @fullpath # Is this an output tileset?
@fullname = "#{@name}_#{@width}x#{height}.#{@format}"
@injectpath = "#{@path}/.injected/#{variant.name}/#{@fullname}" # This must be before redefining @path
@path="#{path}/#{variant.name}"
@fullpath = "#{@path}/#{@fullname}"
else
@injectpath = "#{@path}/.injected/#{@fullname}"
end
@image = nil
@tileswritten = 0
@injected = []
@variant.task_instance.prerequisites << task_name
directory @path
directory @injectpath
file task_name => [@path] do
if @tileswritten > 0 then
puts "Creating/Writing (Injected #{@tileswritten} tiles) in Tileset: #{@fullpath}"
@image.write @fullpath
@injected.each do |injecttile|
File::new injecttile, "w"
end
end
end
end
def image
if !@image
if File.exists? @fullpath
puts "Loading #{@fullpath}"
@image = Magick::Image.read( @fullpath )[0]
else
total = @variant.tilenames.size
columns = 40
width = columns*@width
height = ((total+(columns-1))/columns)*@height
puts "Creating #{@fullpath} at #{width}x#{height} with #{columns} columns"
@image = Magick::Image.new( width, height ) do
self.background_color = Magick::Pixel.new 0, 0, 0, Magick::MaxRGB
end
end
end
@image
end
def add_source_tilegroup tilegroup
Rake::Task[ @variant.task_name ].prerequisites << task_name
total = @variant.tilenames.size
@variant.tilenames.each_with_index do |tilename,index|
tilepath = "#{tilegroup.fullpath}/#{tilename}.#{tilegroup.format}"
tiletask = "Inject tile: #{fullpath} #{tilepath}"
injecttile = "#{@injectpath}/#{tilename}"
if task_instance.prerequisites.index( injecttile ) == nil then
task_instance.prerequisites << injecttile
file injecttile => [ tilepath, @injectpath ] do
columns = image.columns/@width
#puts "#{tilename} [#{index+1} of #{total}] => #{@fullpath}"
tile = Magick::Image.read( tilepath ) do
self.size = Magick::Geometry.new( tilegroup.width, tilegroup.height )
end[0]
if tile then
@image.composite! tile.resize( @width, @height ),
(index%columns)*@width, (index/columns)*@height,
Magick::OverCompositeOp
@tileswritten += 1
end
@injected << injecttile
end
end
end
end
def task_name
"tileset: #{@fullpath}"
end
end
class TileGroup < TilesTask
attr_reader :name, :path, :format, :fullpath, :width, :height
def initialize name, path, format, width, height
@name = name
@path = path
@format = format
@width = width
@height = height
@fullpath = "#{@path}/#{@name}/#{format}"
@tileswritten = 0
directory @fullpath
task task_name => [@fullpath] do
puts "Created/Updated #{@tileswritten} tiles in TileGroup: #{@fullpath}" if @tileswritten > 1
end
end
def add_source_tileset tileset
Rake::Task[ tileset.variant.task_name ].prerequisites << task_name
total = tileset.variant.tilenames.size
columns = nil
tileset.variant.tilenames.each_with_index do |tilename,index|
tilepath = "#{@fullpath}/#{tilename}.#{format}"
if task_instance.prerequisites.index( tilepath ) == nil then
task_instance.prerequisites << tilepath
file tilepath => [tileset.fullpath,@fullpath] do
columns = tileset.image.columns/tileset.width if !columns
#puts "#{tileset.name} [#{index+1} of #{total}] => #{tilepath}"
tileset.image.crop((index%columns)*tileset.width,(index/columns)*tileset.height,tileset.width,tileset.height).resize(@width,@height).write tilepath
@tileswritten += 1
end
end
end
end
def task_name
"tilegroup: #{@fullpath}"
end
end
class Variant < TilesTask
attr_reader :name
attr_reader :tilenames
def initialize name, filename
@name = name
@tilenames = []
File.readlines( filename ).each do |line|
@tilenames << line.chomp
end
task task_name => []
end
def task_name
"variant: #{@name}"
end
end
class Variants < Hash
def initialize directory
super()
@directory = directory
FileList[ "#{directory}/*" ].each do |path|
variant_name = File::basename( path ).to_sym
self[ variant_name ] = Variant.new( variant_name, path )
end
end
end