Files
mikunyan/exe/mikunyan-image
2021-06-22 13:38:04 +09:00

123 lines
3.5 KiB
Ruby
Executable File

#!/usr/bin/env ruby
# frozen_string_literal: true
require 'mikunyan'
require 'fileutils'
begin
require 'usamin'
require 'usamin/overwrite'
rescue LoadError
require 'json'
end
opts = { as_asset: false, outputdir: nil, sprite: false, pretty: false }
arg = nil
i = 0
while i < ARGV.count
if ARGV[i].start_with?('-')
case ARGV[i]
when '--as-asset', '-a'
opts[:as_asset] = true
when '--outputdir', '-o'
i += 1
opts[:outputdir] = ARGV[i]
when '--sprite', '-s'
opts[:sprite] = true
when '--pretty', '-p'
opts[:pretty] = true
else
warn("Unknown option: #{ARGV[i]}")
end
else
arg ||= ARGV[i]
end
i += 1
end
unless arg
warn('Input file is not specified')
exit(1)
end
unless File.file?(arg)
warn("File not found: #{arg}")
exit(1)
end
if opts[:as_asset]
assets = [Mikunyan::Asset.file(arg)]
else
bundle = Mikunyan::AssetBundle.file(arg)
assets = bundle.assets
end
outdir = opts[:outputdir] || File.basename(arg, '.*')
FileUtils.mkpath(outdir)
if opts[:sprite]
textures = {}
textures_meta = {}
assets.each do |asset|
json = {}
asset.each_object do |obj|
next unless obj.type == 'Sprite'
next unless obj.klass
obj = obj.parse
next unless obj&.m_RD&.texture
file_id = obj.m_RD.texture.m_FileID.value
texture_asset = file_id == 0 ? asset : bundle && bundle[asset.references[file_id - 1].file_path]
texture_id = obj.m_RD.texture.m_PathID.value
next unless texture_asset && texture_id
unless textures.dig(texture_asset, texture_id)
texture_obj = texture_asset.parse_object(texture_id)
if texture_obj.is_a?(Mikunyan::CustomTypes::Texture2D)
textures[texture_asset] ||= {}
textures[texture_asset][texture_id] = texture_obj.generate_png
textures_meta[texture_asset] ||= {}
textures_meta[texture_asset][texture_id] = {
name: texture_obj.m_Name&.value, width: texture_obj.m_Width&.value, height: texture_obj.m_Height&.value,
format: texture_obj.m_TextureFormat&.value, asset: texture_asset.name, path_id: texture_id
}
end
end
next unless textures_meta[texture_asset][texture_id]
unless json.key?([file_id, texture_id])
json[[file_id, texture_id]] = textures_meta[texture_asset][texture_id].dup
json[[file_id, texture_id]][:sprites] = []
end
x = obj.m_Rect&.x&.value
y = obj.m_Rect&.y&.value
width = obj.m_Rect&.width&.value
height = obj.m_Rect&.height&.value
json[[file_id, texture_id]][:sprites] << { name: obj.object_name, x: x, y: y, width: width, height: height, path_id: obj.path_id }
texture = textures[texture_asset][texture_id]
next unless texture && x && y && width && height
texture.crop(x.round, (texture.height - height - y).round, width.round, height.round).save("#{outdir}/#{obj.object_name}.png")
end
puts opts[:pretty] ? JSON.pretty_generate(json.values) : JSON.generate(json.values)
end
else
assets.each do |asset|
json = []
asset.each_object do |obj|
next unless obj.type == 'Texture2D'
next unless obj.klass
obj = obj.parse
next unless obj.is_a?(Mikunyan::CustomTypes::Texture2D)
json << {
name: obj.object_name, width: obj.width, height: obj.height,
format: obj.texture_format, path_id: obj.path_id
}
obj.generate_png&.save("#{outdir}/#{obj.object_name}.png")
end
puts opts[:pretty] ? JSON.pretty_generate(json) : JSON.generate(json)
end
end