sprite-packer.rb 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. require_relative 'common'
  2. options = get_options(__FILE__)
  3. sprite_path = options['sprite_path']
  4. csv_path = options['generate_config_path']
  5. atlas_path = options['generate_atlas_path']
  6. padding = options['padding_size']
  7. recreate_dir atlas_path
  8. ensure_dir csv_path
  9. # $ gem install chunky_png
  10. # $ gem install binpack
  11. require 'chunky_png'
  12. require 'binpack'
  13. require 'csv'
  14. Point = Struct.new(:x, :y)
  15. Box = Struct.new(:top_left, :bottom_right)
  16. csv_atlas = CSV.open("#{csv_path}/atlas.csv", 'wb')
  17. csv_atlas << ['Id', 'File']
  18. csv_atlas << ['', '']
  19. csv_atlas << [':id', ':path']
  20. csv_sprite = CSV.open("#{csv_path}/sprite.csv", 'wb')
  21. csv_sprite << ['Id', 'AtlasId', 'X', 'Y', 'Width', 'Height']
  22. csv_sprite << ['', '', '', '']
  23. csv_sprite << [':id', '@atlas', ':int', ':int', ':int', ':int']
  24. Dir["#{sprite_path}/*"].each do |path|
  25. atlas_name = convert_case(File::basename(path))
  26. next unless File::directory?(path)
  27. atlas_size = 32
  28. bins = []
  29. loop do
  30. bins.clear
  31. begin
  32. sprites = Dir["#{path}/*"].collect do |file|
  33. sprite = ChunkyPNG::Image.from_file(file)
  34. sprite.define_singleton_method :file do
  35. return file
  36. end
  37. sprite
  38. end
  39. items = sprites.collect { |sprite| Binpack::Item.new(sprite, sprite.width, sprite.height) }
  40. bins = Binpack::Bin.pack(items, [], Binpack::Bin.new(atlas_size, atlas_size, padding))
  41. raise 'too small' if bins.size > 1
  42. break
  43. rescue
  44. atlas_size *= 2
  45. break if atlas_size >= 2048
  46. end
  47. end
  48. bins.each do |bin|
  49. atlas = ChunkyPNG::Image.new(atlas_size, atlas_size, ChunkyPNG::Color::TRANSPARENT)
  50. bin.items.each do |item|
  51. unit, x, y = *item
  52. puts "#{x}, #{y}"
  53. atlas.compose!(unit.obj, x, y)
  54. csv_sprite << [convert_case(File.basename(unit.obj.file, '.png')), atlas_name, x, y, unit.width, unit.height]
  55. end
  56. atlas_file = "#{atlas_path}/#{File::basename(path)}.png"
  57. atlas.save atlas_file
  58. csv_atlas << [atlas_name, File.basename(atlas_file)]
  59. end
  60. end