more and more update
This commit is contained in:
@@ -15,3 +15,5 @@
|
|||||||
*.bundle
|
*.bundle
|
||||||
|
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
.idea/
|
||||||
|
*.iml
|
||||||
|
|||||||
+72
-71
@@ -1,101 +1,102 @@
|
|||||||
#!/usr/bin/env ruby
|
#!/usr/bin/env ruby
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require 'mikunyan'
|
require 'mikunyan'
|
||||||
require 'mikunyan/decoders'
|
|
||||||
require 'fileutils'
|
require 'fileutils'
|
||||||
begin
|
begin
|
||||||
require 'usamin'
|
require 'usamin'
|
||||||
require 'usamin/overwrite'
|
require 'usamin/overwrite'
|
||||||
rescue LoadError
|
rescue LoadError
|
||||||
require 'json'
|
require 'json'
|
||||||
end
|
end
|
||||||
|
|
||||||
opts = {:as_asset => false, :outputdir => nil, :sprite => false, :pretty => false}
|
opts = { as_asset: false, outputdir: nil, sprite: false, pretty: false }
|
||||||
arg = nil
|
arg = nil
|
||||||
i = 0
|
i = 0
|
||||||
while i < ARGV.count
|
while i < ARGV.count
|
||||||
if ARGV[i].start_with?('-')
|
if ARGV[i].start_with?('-')
|
||||||
case ARGV[i]
|
case ARGV[i]
|
||||||
when '--as-asset', '-a'
|
when '--as-asset', '-a'
|
||||||
opts[:as_asset] = true
|
opts[:as_asset] = true
|
||||||
when '--outputdir', '-o'
|
when '--outputdir', '-o'
|
||||||
i += 1
|
i += 1
|
||||||
opts[:outputdir] = ARGV[i]
|
opts[:outputdir] = ARGV[i]
|
||||||
when '--sprite', '-s'
|
when '--sprite', '-s'
|
||||||
opts[:sprite] = true
|
opts[:sprite] = true
|
||||||
when '--pretty', '-p'
|
when '--pretty', '-p'
|
||||||
opts[:pretty] = true
|
opts[:pretty] = true
|
||||||
else
|
|
||||||
warn("Unknown option: #{ARGV[i]}")
|
|
||||||
end
|
|
||||||
else
|
else
|
||||||
arg = ARGV[i] unless arg
|
warn("Unknown option: #{ARGV[i]}")
|
||||||
end
|
end
|
||||||
i += 1
|
else
|
||||||
|
arg ||= ARGV[i]
|
||||||
|
end
|
||||||
|
i += 1
|
||||||
end
|
end
|
||||||
|
|
||||||
unless arg
|
unless arg
|
||||||
warn("Input file is not specified")
|
warn('Input file is not specified')
|
||||||
exit(1)
|
exit(1)
|
||||||
end
|
end
|
||||||
|
|
||||||
unless File.file?(arg)
|
unless File.file?(arg)
|
||||||
warn("File not found: #{arg}")
|
warn("File not found: #{arg}")
|
||||||
exit(1)
|
exit(1)
|
||||||
end
|
end
|
||||||
|
|
||||||
assets = []
|
assets = opts[:as_asset] ? [Mikunyan::Asset.file(arg)] : Mikunyan::AssetBundle.file(arg).assets
|
||||||
|
|
||||||
if opts[:as_asset]
|
|
||||||
assets = [Mikunyan::Asset.file(arg, File.basename(arg, '.*'))]
|
|
||||||
else
|
|
||||||
assets = Mikunyan::AssetBundle.file(arg).assets
|
|
||||||
end
|
|
||||||
|
|
||||||
outdir = opts[:outputdir] || File.basename(arg, '.*')
|
outdir = opts[:outputdir] || File.basename(arg, '.*')
|
||||||
FileUtils.mkpath(outdir)
|
FileUtils.mkpath(outdir)
|
||||||
|
|
||||||
assets.each do |asset|
|
assets.each do |asset|
|
||||||
if opts[:sprite]
|
if opts[:sprite]
|
||||||
json = {}
|
json = {}
|
||||||
textures = {}
|
textures = {}
|
||||||
|
|
||||||
asset.objects.select{|o| asset.object_type(o) == 'Sprite'}.each do |o|
|
asset.each_object do |obj|
|
||||||
obj = asset.parse_object(o)
|
next unless obj.type == 'Sprite'
|
||||||
next unless obj
|
obj = obj.parse
|
||||||
name = obj.m_Name.value
|
next unless obj
|
||||||
tex_id = obj.m_RD.texture.m_PathID.value
|
texture_id = obj.m_RD&.texture&.m_PathID&.value
|
||||||
|
next unless texture_id
|
||||||
|
|
||||||
unless textures[tex_id]
|
unless textures.key?(texture_id)
|
||||||
tex_obj = asset.parse_object(tex_id)
|
texture_obj = asset.parse_object(texture_id)
|
||||||
if tex_obj
|
if texture_obj.is_a?(Mikunyan::CustomTypes::Texture2D)
|
||||||
textures[tex_id] = Mikunyan::ImageDecoder.decode_object(tex_obj)
|
textures[texture_id] = texture_obj.generate_png
|
||||||
json[tex_id] = {:name => tex_obj.m_Name.value, :width => textures[tex_id].width, :height => textures[tex_id].height, :path_id => tex_id, :sprites => []} if textures[tex_id]
|
json[texture_id] = {
|
||||||
end
|
name: texture_obj.m_Name&.value, width: texture_obj.m_Width&.value, height: texture_obj.m_Height&.value,
|
||||||
end
|
format: texture_obj.m_TextureFormat&.value, path_id: texture_id, sprites: []
|
||||||
|
}
|
||||||
if textures[tex_id]
|
|
||||||
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[tex_id][:sprites] << {:name => name, :x => x, :y => y, :width => width, :height => height, :path_id => o.path_id}
|
|
||||||
textures[tex_id].crop(x.round, (textures[tex_id].height - height - y).round, width.round, height.round).save("#{outdir}/#{name}.png")
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
puts opts[:pretty] ? JSON.pretty_generate(json.values) : JSON.generate(json.values)
|
end
|
||||||
else
|
|
||||||
json = []
|
x = obj.m_Rect&.x&.value
|
||||||
asset.objects.select{|o| asset.object_type(o) == 'Texture2D'}.each do |o|
|
y = obj.m_Rect&.y&.value
|
||||||
obj = asset.parse_object(o)
|
width = obj.m_Rect&.width&.value
|
||||||
next unless obj
|
height = obj.m_Rect&.height&.value
|
||||||
name = obj.m_Name.value
|
|
||||||
image = Mikunyan::ImageDecoder.decode_object(obj)
|
json[texture_id][:sprites] << { name: obj.object_name, x: x, y: y, width: width, height: height, path_id: obj.path_id }
|
||||||
if image
|
|
||||||
json << {:name => name, :width => image.width, :height => image.height, :path_id => o.path_id}
|
next unless textures[texture_id] && x && y && width && height
|
||||||
image.save("#{outdir}/#{name}.png")
|
textures[texture_id].crop(
|
||||||
end
|
x.round, (textures[texture_id].height - height - y).round, width.round, height.round
|
||||||
end
|
).save("#{outdir}/#{obj.object_name}.png")
|
||||||
puts opts[:pretty] ? JSON.pretty_generate(json) : JSON.generate(json)
|
|
||||||
end
|
end
|
||||||
|
puts opts[:pretty] ? JSON.pretty_generate(json.values) : JSON.generate(json.values)
|
||||||
|
else
|
||||||
|
json = []
|
||||||
|
asset.each_object do |obj|
|
||||||
|
next unless obj.type == 'Texture2D'
|
||||||
|
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
|
end
|
||||||
|
|||||||
+46
-65
@@ -1,89 +1,70 @@
|
|||||||
#!/usr/bin/env ruby
|
#!/usr/bin/env ruby
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require 'mikunyan'
|
require 'mikunyan'
|
||||||
require 'base64'
|
require 'base64'
|
||||||
|
|
||||||
def obj64(obj)
|
def obj64(obj)
|
||||||
if obj.class == Hash
|
if obj.is_a?(Hash)
|
||||||
obj.map{|k, v| [k, obj64(v)]}.to_h
|
obj.map{|k, v| [k, obj64(v)]}.to_h
|
||||||
elsif obj.class == Array
|
elsif obj.is_a?(Array)
|
||||||
obj.map{|e| obj64(e)}
|
obj.map{|e| obj64(e)}
|
||||||
elsif obj.class == String
|
elsif obj.is_a?(String)
|
||||||
if obj.encoding == Encoding::UTF_8
|
if obj.encoding == Encoding::UTF_8
|
||||||
obj
|
obj
|
||||||
else
|
|
||||||
Base64::strict_encode64(obj)
|
|
||||||
end
|
|
||||||
else
|
else
|
||||||
obj
|
Base64.strict_encode64(obj)
|
||||||
end
|
end
|
||||||
|
else
|
||||||
|
obj
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
opts = {:as_asset => false, :pretty => false, :yaml => false}
|
opts = { as_asset: false, pretty: false, yaml: false }
|
||||||
arg = nil
|
arg = nil
|
||||||
i = 0
|
i = 0
|
||||||
while i < ARGV.count
|
while i < ARGV.count
|
||||||
if ARGV[i].start_with?('-')
|
if ARGV[i].start_with?('-')
|
||||||
case ARGV[i]
|
case ARGV[i]
|
||||||
when '--as-asset', '-a'
|
when '--as-asset', '-a'
|
||||||
opts[:as_asset] = true
|
opts[:as_asset] = true
|
||||||
when '--pretty', '-p'
|
when '--pretty', '-p'
|
||||||
opts[:pretty] = true
|
opts[:pretty] = true
|
||||||
when '--yaml', '-y'
|
when '--yaml', '-y'
|
||||||
opts[:yaml] = true
|
opts[:yaml] = true
|
||||||
else
|
|
||||||
warn("Unknown option: #{ARGV[i]}")
|
|
||||||
end
|
|
||||||
else
|
else
|
||||||
arg = ARGV[i] unless arg
|
warn("Unknown option: #{ARGV[i]}")
|
||||||
end
|
end
|
||||||
i += 1
|
else
|
||||||
|
arg ||= ARGV[i]
|
||||||
|
end
|
||||||
|
i += 1
|
||||||
end
|
end
|
||||||
|
|
||||||
if opts[:pretty] && opts[:yaml]
|
warn('Option --pretty is ignored if --yaml is specified.') if opts[:pretty] && opts[:yaml]
|
||||||
warn("Option --pretty is ignored if --yaml is specified.")
|
|
||||||
end
|
|
||||||
|
|
||||||
unless File.file?(arg)
|
unless File.file?(arg)
|
||||||
warn("File not found: #{arg}")
|
warn("File not found: #{arg}")
|
||||||
exit(1)
|
exit(1)
|
||||||
end
|
end
|
||||||
|
|
||||||
assets = {}
|
assets = opts[:as_asset] ? [Mikunyan::Asset.file(arg)] : Mikunyan::AssetBundle.file(arg).assets
|
||||||
|
assets = assets.map{|asset| [asset.name, asset.each_object.map(&:parse_simple)]}.to_h
|
||||||
if opts[:as_asset]
|
|
||||||
asset = Mikunyan::Asset.file(arg, arg.match(/([^\/]*?)(\.[^.]*)?\z/)[1])
|
|
||||||
objs = []
|
|
||||||
asset.path_ids.each do |e|
|
|
||||||
obj = asset.parse_object_simple(e)
|
|
||||||
objs << obj
|
|
||||||
end
|
|
||||||
assets[asset.name] = objs
|
|
||||||
else
|
|
||||||
bundle = Mikunyan::AssetBundle.file(arg)
|
|
||||||
bundle.assets.each do |asset|
|
|
||||||
objs = []
|
|
||||||
asset.path_ids.each do |e|
|
|
||||||
obj = asset.parse_object_simple(e)
|
|
||||||
objs << obj
|
|
||||||
end
|
|
||||||
assets[asset.name] = objs
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if opts[:yaml]
|
if opts[:yaml]
|
||||||
require 'yaml'
|
require 'yaml'
|
||||||
puts YAML.dump(assets)
|
puts YAML.dump(assets)
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
require 'usamin'
|
require 'usamin'
|
||||||
require 'usamin/overwrite'
|
require 'usamin/overwrite'
|
||||||
rescue LoadError
|
rescue LoadError
|
||||||
require 'json'
|
require 'json'
|
||||||
end
|
end
|
||||||
assets = assets.map{|k, v| [k, obj64(v)]}.to_h
|
assets = assets.map{|k, v| [k, obj64(v)]}.to_h
|
||||||
if opts[:pretty]
|
if opts[:pretty]
|
||||||
puts JSON.pretty_generate(assets)
|
puts JSON.pretty_generate(assets)
|
||||||
else
|
else
|
||||||
puts JSON.generate(assets)
|
puts JSON.generate(assets)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,13 +1,7 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require 'mikunyan/version'
|
require 'mikunyan/version'
|
||||||
|
|
||||||
require 'mikunyan/asset_bundle'
|
require 'mikunyan/asset_bundle'
|
||||||
require 'mikunyan/asset'
|
|
||||||
require 'mikunyan/binary_reader'
|
|
||||||
require 'mikunyan/object_value'
|
|
||||||
require 'mikunyan/type_tree'
|
|
||||||
require 'mikunyan/constants'
|
|
||||||
|
|
||||||
# Module for deserializing Unity Assets and AssetBundles
|
# Module for deserializing Unity Assets and AssetBundles
|
||||||
module Mikunyan
|
module Mikunyan
|
||||||
|
|||||||
+190
-221
@@ -1,5 +1,10 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'mikunyan/type_tree'
|
||||||
|
require 'mikunyan/constants'
|
||||||
|
require 'mikunyan/object_value'
|
||||||
|
require 'mikunyan/base_object'
|
||||||
|
|
||||||
module Mikunyan
|
module Mikunyan
|
||||||
# Class for representing Unity Asset
|
# Class for representing Unity Asset
|
||||||
# @attr_reader [String] name Asset name
|
# @attr_reader [String] name Asset name
|
||||||
@@ -8,18 +13,19 @@ module Mikunyan
|
|||||||
# @attr_reader [Integer] target_platform target platform number
|
# @attr_reader [Integer] target_platform target platform number
|
||||||
# @attr_reader [Symbol] endian data endianness (:little or :big)
|
# @attr_reader [Symbol] endian data endianness (:little or :big)
|
||||||
# @attr_reader [Array<Mikunyan::Asset::Klass>] klasses defined classes
|
# @attr_reader [Array<Mikunyan::Asset::Klass>] klasses defined classes
|
||||||
# @attr_reader [Array<Mikunyan::Asset::ObjectData>] objects included objects
|
# @attr_reader [Array<Mikunyan::Asset::ObjectEntry>] objects contained objects
|
||||||
# @attr_reader [Array<Integer>] add_ids ?
|
# @attr_reader [Array<Mikunyan::Asset::LocalObjectEntry>] add_ids ?
|
||||||
# @attr_reader [Array<Mikunyan::Asset::Reference>] references reference data
|
# @attr_reader [Array<Mikunyan::Asset::Reference>] references reference data
|
||||||
class Asset
|
class Asset
|
||||||
attr_reader :name, :format, :generator_version, :target_platform, :endian, :klasses, :objects, :add_ids, :references, :res_s
|
attr_reader :name, :format, :generator_version, :target_platform, :endian, :klasses, :objects, :add_ids, :references
|
||||||
|
|
||||||
# Struct for representing Asset class definition
|
# Struct for representing Asset class definition
|
||||||
# @attr [Integer] class_id class ID
|
# @attr [Integer] class_id class ID
|
||||||
|
# @attr [Boolean] stripped?
|
||||||
# @attr [Integer,nil] script_id script ID
|
# @attr [Integer,nil] script_id script ID
|
||||||
# @attr [String] hash hash value (16 or 32 bytes)
|
# @attr [String] hash hash value (16 or 32 bytes)
|
||||||
# @attr [Mikunyan::TypeTree, nil] type_tree given TypeTree
|
# @attr [Mikunyan::TypeTree, nil] type_tree given TypeTree
|
||||||
Klass = Struct.new(:class_id, :script_id, :hash, :type_tree)
|
Klass = Struct.new(:class_id, :stripped?, :script_id, :hash, :type_tree)
|
||||||
|
|
||||||
# Struct for representing Asset object information
|
# Struct for representing Asset object information
|
||||||
# @attr [Integer] path_id path ID
|
# @attr [Integer] path_id path ID
|
||||||
@@ -30,7 +36,29 @@ module Mikunyan
|
|||||||
# @attr [Integer,nil] class_idx class definition index
|
# @attr [Integer,nil] class_idx class definition index
|
||||||
# @attr [Boolean] destroyed? destroyed or not
|
# @attr [Boolean] destroyed? destroyed or not
|
||||||
# @attr [String] data binary data of object
|
# @attr [String] data binary data of object
|
||||||
ObjectData = Struct.new(:path_id, :offset, :size, :type_id, :class_id, :class_idx, :destroyed?, :data)
|
# @attr [Mikunyan::Asset] parent_asset
|
||||||
|
# @attr [Klass] klass
|
||||||
|
ObjectEntry = Struct.new(
|
||||||
|
:path_id, :offset, :size, :type_id, :class_id, :class_idx, :destroyed?, :stripped?,
|
||||||
|
:data, :parent_asset, :klass,
|
||||||
|
keyword_init: true
|
||||||
|
) do
|
||||||
|
def parse
|
||||||
|
parent_asset.parse_object(self)
|
||||||
|
end
|
||||||
|
|
||||||
|
def parse_simple
|
||||||
|
parent_asset.parse_object_simple(self)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Returns object type name string
|
||||||
|
# @return [String,nil] type name
|
||||||
|
def type
|
||||||
|
klass&.type_tree&.tree&.type || Mikunyan::Constants::CLASS_ID2NAME[class_id]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
LocalObjectEntry = Struct.new(:file_id, :local_id)
|
||||||
|
|
||||||
# Struct for representing Asset reference information
|
# Struct for representing Asset reference information
|
||||||
# @attr [String] path path
|
# @attr [String] path path
|
||||||
@@ -39,13 +67,20 @@ module Mikunyan
|
|||||||
# @attr [String] file_path Asset name
|
# @attr [String] file_path Asset name
|
||||||
Reference = Struct.new(:path, :guid, :type, :file_path)
|
Reference = Struct.new(:path, :guid, :type, :file_path)
|
||||||
|
|
||||||
|
# Strcut for container information
|
||||||
|
# @attr [String] name
|
||||||
|
# @attr [Integer] preload_index
|
||||||
|
# @attr [Integer] path_id
|
||||||
|
ContainerInfo = Struct.new(:name, :preload_index, :preload_size, :file_id, :path_id)
|
||||||
|
|
||||||
# Load Asset from binary string
|
# Load Asset from binary string
|
||||||
# @param [String] bin binary data
|
# @param [String,IO] bin binary data
|
||||||
# @param [String] name Asset name
|
# @param [String] name Asset name
|
||||||
|
# @param [String] resource resource data
|
||||||
# @param [String] res_s resS data
|
# @param [String] res_s resS data
|
||||||
# @return [Mikunyan::Asset] deserialized Asset object
|
# @return [Mikunyan::Asset] deserialized Asset object
|
||||||
def self.load(bin, name, res_s = nil)
|
def self.load(bin, name, resource = nil, res_s = nil)
|
||||||
r = Asset.new(name, res_s)
|
r = Asset.new(name, resource, res_s)
|
||||||
r.send(:load, bin)
|
r.send(:load, bin)
|
||||||
r
|
r
|
||||||
end
|
end
|
||||||
@@ -56,7 +91,15 @@ module Mikunyan
|
|||||||
# @return [Mikunyan::Asset] deserialized Asset object
|
# @return [Mikunyan::Asset] deserialized Asset object
|
||||||
def self.file(file, name = nil)
|
def self.file(file, name = nil)
|
||||||
name ||= File.basename(name, '.*')
|
name ||= File.basename(name, '.*')
|
||||||
Asset.load(File.binread(file), name)
|
File.open(file, 'rb') do |io|
|
||||||
|
Asset.load(io, name)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Same as objects.each
|
||||||
|
# @return [Enumerator<Mikunyan::Asset::ObjectEntry>,Array<Mikunyan::Asset::ObjectEntry>]
|
||||||
|
def each_object(&block)
|
||||||
|
@objects.each(&block)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns list of all path IDs
|
# Returns list of all path IDs
|
||||||
@@ -68,273 +111,199 @@ module Mikunyan
|
|||||||
# Returns list of containers
|
# Returns list of containers
|
||||||
# @return [Array<Hash>,nil] list of all containers
|
# @return [Array<Hash>,nil] list of all containers
|
||||||
def containers
|
def containers
|
||||||
obj = parse_object(1)
|
obj = @path_id_table[1]
|
||||||
return nil unless obj&.m_Container && obj.m_Container.array?
|
return nil unless obj.klass&.type_tree&.tree&.type == 'AssetBundle'
|
||||||
obj.m_Container.value.map do |e|
|
parse_object(obj).m_Container.value.map do |e|
|
||||||
{ name: e.first.value, preload_index: e.second.preloadIndex.value, path_id: e.second.asset.m_PathID.value }
|
ContainerInfo.new(e.first.value, e.second.preloadIndex.value, e.second.preloadSize.value, e.second.asset.m_FileID.value, e.second.asset.m_PathID.value)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Parse object of given path ID
|
# Parse object of given path ID
|
||||||
# @param [Integer,ObjectData] path_id path ID or object
|
# @param [Integer,ObjectEntry] obj path ID or object
|
||||||
# @return [Mikunyan::ObjectValue,nil] parsed object
|
# @return [Mikunyan::BaseObject,nil] parsed object
|
||||||
def parse_object(path_id)
|
def parse_object(obj)
|
||||||
if path_id.class == Integer
|
obj = @path_id_table[obj] if obj.class == Integer
|
||||||
obj = @objects.find{|e| e.path_id == path_id}
|
return nil unless obj.klass&.type_tree
|
||||||
return nil unless obj
|
value_klass = Mikunyan::CustomTypes.get_custom_type(obj.klass.type_tree.tree.type, obj.class_id)
|
||||||
elsif path_id.class == ObjectData
|
ret = parse_object_private(BinaryReader.new(obj.data, @endian), obj.klass.type_tree.tree, value_klass)
|
||||||
obj = path_id
|
ret.object_entry = obj
|
||||||
else
|
ret
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
klass = (obj.class_idx ? @klasses[obj.class_idx] : @klasses.find{|e| e.class_id == obj.class_id} || @klasses.find{|e| e.class_id == obj.type_id})
|
|
||||||
type_tree = Asset.parse_type_tree(klass)
|
|
||||||
return nil unless type_tree
|
|
||||||
|
|
||||||
parse_object_private(BinaryReader.new(obj.data, @endian), type_tree)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Parse object of given path ID and simplify it
|
# Parse object of given path ID and simplify it
|
||||||
# @param [Integer,ObjectData] path_id path ID or object
|
# @param [Integer,ObjectEntry] obj path ID or object
|
||||||
# @return [Hash,nil] parsed object
|
# @return [Hash,nil] parsed object
|
||||||
def parse_object_simple(path_id)
|
def parse_object_simple(obj)
|
||||||
Asset.object_simplify(parse_object(path_id))
|
parse_object(obj)&.simplify
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns object type name string
|
# Returns object type name string
|
||||||
# @param [Integer,ObjectData] path_id path ID or object
|
# @param [Integer,ObjectEntry] obj path ID or object
|
||||||
# @return [String,nil] type name
|
# @return [String,nil] type name
|
||||||
def object_type(path_id)
|
def object_type(obj)
|
||||||
if path_id.class == Integer
|
obj = @path_id_table[obj] if obj.class == Integer
|
||||||
obj = @objects.find{|e| e.path_id == path_id}
|
obj&.type
|
||||||
return nil unless obj
|
end
|
||||||
elsif path_id.class == ObjectData
|
|
||||||
obj = path_id
|
def self.object_simplify(obj)
|
||||||
else
|
obj.is_a?(ObjectValue) ? obj.simplify : obj
|
||||||
return nil
|
|
||||||
end
|
|
||||||
klass = (obj.class_idx ? @klasses[obj.class_idx] : @klasses.find{|e| e.class_id == obj.class_id} || @klasses.find{|e| e.class_id == obj.type_id})
|
|
||||||
if klass&.type_tree && klass.type_tree.nodes[0]
|
|
||||||
klass.type_tree.nodes[0].type
|
|
||||||
elsif klass
|
|
||||||
Mikunyan::CLASS_ID[klass.class_id]
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def initialize(name, res_s = nil)
|
def initialize(name, resource = nil, res_s = nil)
|
||||||
@name = name
|
@name = name
|
||||||
@endian = :big
|
@endian = :big
|
||||||
|
@resource = resource
|
||||||
@res_s = res_s
|
@res_s = res_s
|
||||||
end
|
end
|
||||||
|
|
||||||
def load(bin)
|
def load(bin)
|
||||||
br = BinaryReader.new(bin)
|
br = BinaryReader.new(bin)
|
||||||
metadata_size = br.i32u
|
|
||||||
size = br.i32u
|
meta_size = br.i32u
|
||||||
|
file_size = br.i32u
|
||||||
@format = br.i32u
|
@format = br.i32u
|
||||||
data_offset = br.i32u
|
data_offset = br.i32u
|
||||||
|
|
||||||
if @format >= 9
|
if @format >= 9
|
||||||
@endian = :little if br.i32 == 0
|
@endian = br.bool ? :big : :little
|
||||||
br.endian = @endian
|
br.adv(3)
|
||||||
end
|
|
||||||
|
|
||||||
@generator_version = br.cstr
|
|
||||||
@target_platform = br.i32
|
|
||||||
@klasses = []
|
|
||||||
|
|
||||||
if @format >= 17
|
|
||||||
has_type_trees = (br.i8 != 0)
|
|
||||||
type_tree_count = br.i32u
|
|
||||||
type_tree_count.times do
|
|
||||||
class_id = br.i32
|
|
||||||
br.adv(1)
|
|
||||||
script_id = br.i16
|
|
||||||
hash = if class_id < 0 || class_id == 114
|
|
||||||
br.read(32)
|
|
||||||
else
|
|
||||||
br.read(16)
|
|
||||||
end
|
|
||||||
@klasses << Klass.new(class_id, script_id, hash, has_type_trees ? TypeTree.load(br) : TypeTree.load_default(hash))
|
|
||||||
end
|
|
||||||
elsif @format >= 13
|
|
||||||
has_type_trees = (br.i8 != 0)
|
|
||||||
type_tree_count = br.i32u
|
|
||||||
type_tree_count.times do
|
|
||||||
class_id = br.i32
|
|
||||||
hash = if class_id < 0
|
|
||||||
br.read(32)
|
|
||||||
else
|
|
||||||
br.read(16)
|
|
||||||
end
|
|
||||||
@klasses << Klass.new(class_id, nil, hash, has_type_trees ? TypeTree.load(br) : TypeTree.load_default(hash))
|
|
||||||
end
|
|
||||||
else
|
else
|
||||||
@type_trees = {}
|
br.pos = file_size - meta_size
|
||||||
type_tree_count = br.i32u
|
@endian = br.bool ? :big : :little
|
||||||
type_tree_count.times do
|
end
|
||||||
class_id = br.i32
|
br.endian = @endian
|
||||||
@klasses << Klass.new(class_id, nil, nil, @format == 10 || @format == 12 ? TypeTree.load(br) : TypeTree.load_legacy(br))
|
|
||||||
|
@generator_version = br.cstr if @format >= 7
|
||||||
|
@target_platform = br.i32 if @format >= 8
|
||||||
|
has_type_trees = @format >= 13 ? br.bool : true
|
||||||
|
type_count = br.i32u
|
||||||
|
|
||||||
|
@klasses = Array.new(type_count) do
|
||||||
|
class_id = br.i32s
|
||||||
|
stripped = br.bool if @format >= 16
|
||||||
|
script_id = br.i16 if @format >= 17
|
||||||
|
hash = br.read(@format < 16 && class_id < 0 || @format >= 16 && class_id == 114 ? 32 : 16) if @format >= 13
|
||||||
|
type_tree = has_type_trees ? TypeTree.load(br, @format) : TypeTree.load_default(class_id, hash)
|
||||||
|
Klass.new(class_id, stripped, script_id, hash, type_tree)
|
||||||
|
end
|
||||||
|
|
||||||
|
wide_path_id = @format >= 14 || @format >= 7 && br.i32 != 0
|
||||||
|
|
||||||
|
object_count = br.i32u
|
||||||
|
@objects = Array.new(object_count) do
|
||||||
|
br.align(4) if @format >= 14
|
||||||
|
if @format >= 16
|
||||||
|
ObjectEntry.new(
|
||||||
|
path_id: wide_path_id ? br.i64s : br.i32s, offset: br.i32u, size: br.i32u,
|
||||||
|
class_idx: br.i32u, stripped?: @format == 16 ? br.bool : nil,
|
||||||
|
parent_asset: self
|
||||||
|
)
|
||||||
|
else
|
||||||
|
ObjectEntry.new(
|
||||||
|
path_id: wide_path_id ? br.i64s : br.i32s, offset: br.i32u, size: br.i32u,
|
||||||
|
type_id: br.i32, class_id: br.i16, destroyed?: br.i16 == 1, stripped?: @format == 15 ? br.bool : nil,
|
||||||
|
parent_asset: self
|
||||||
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
long_object_ids = (@format >= 14 || (7 <= @format && @format <= 13 && br.i32 != 0))
|
@path_id_table = @objects.map{|e| [e.path_id, e]}.to_h
|
||||||
|
|
||||||
@objects = []
|
|
||||||
object_count = br.i32u
|
|
||||||
object_count.times do
|
|
||||||
br.align(4) if @format >= 14
|
|
||||||
path_id = long_object_ids ? br.i64 : br.i32
|
|
||||||
offset = br.i32u
|
|
||||||
size = br.i32u
|
|
||||||
@objects << if @format >= 17
|
|
||||||
ObjectData.new(path_id, offset, size, nil, nil, br.i32u, @format <= 10 && br.i16 != 0)
|
|
||||||
else
|
|
||||||
ObjectData.new(path_id, offset, size, br.i32, br.i16, nil, @format <= 10 && br.i16 != 0)
|
|
||||||
end
|
|
||||||
br.adv(2) if 11 <= @format && @format <= 16
|
|
||||||
br.adv(1) if 15 <= @format && @format <= 16
|
|
||||||
end
|
|
||||||
|
|
||||||
if @format >= 11
|
if @format >= 11
|
||||||
@add_ids = []
|
|
||||||
add_id_count = br.i32u
|
add_id_count = br.i32u
|
||||||
add_id_count.times do
|
@add_ids = Array.new(add_id_count) do
|
||||||
br.align(4) if @format >= 14
|
br.align(4) if @format >= 14
|
||||||
@add_ids << [(long_object_ids ? br.i64 : br.i32), br.i32]
|
LocalObjectEntry.new(br.i32u, wide_path_id ? br.i64s : br.i32s)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if @format >= 6
|
reference_count = br.i32u
|
||||||
@references = []
|
@references = Array.new(reference_count) do
|
||||||
reference_count = br.i32u
|
Reference.new(@format >= 6 ? br.cstr : nil, @format >= 5 ? br.read(16) : nil, @format >= 5 ? br.i32s : nil, br.cstr)
|
||||||
reference_count.times do
|
|
||||||
@references << Reference.new(br.cstr, br.read(16), br.i32, br.cstr)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@comment = br.cstr if @format >= 5
|
||||||
|
|
||||||
@objects.each do |e|
|
@objects.each do |e|
|
||||||
br.jmp(data_offset + e.offset)
|
br.jmp(data_offset + e.offset)
|
||||||
e.data = br.read(e.size)
|
e.data = br.read(e.size)
|
||||||
|
e.klass = e.class_idx ? @klasses[e.class_idx] : @klasses.find{|e2| e2.class_id == e.class_id} || @klasses.find{|e2| e2.class_id == e.type_id}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def parse_object_private(br, type_tree)
|
# @param [Mikunyan::BinaryReader] br
|
||||||
r = nil
|
# @param [Mikunyan::TypeTree::Node] node
|
||||||
node = type_tree[:node]
|
def parse_object_private(br, node, klass = ObjectValue)
|
||||||
children = type_tree[:children]
|
ret = klass.new(node.name, node.type, br.endian)
|
||||||
|
children = node.children
|
||||||
|
|
||||||
if node.array?
|
if children.empty?
|
||||||
data = nil
|
pos = br.pos
|
||||||
size = parse_object_private(br, children.find{|e| e[:name] == 'size'}).value
|
ret.value =
|
||||||
data_type_tree = children.find{|e| e[:name] == 'data'}
|
case node.type
|
||||||
data = if node.type == 'TypelessData'
|
when 'bool'
|
||||||
br.read(size * data_type_tree[:node].size)
|
br.bool
|
||||||
else
|
when 'SInt8'
|
||||||
size.times.map{parse_object_private(br, data_type_tree)}
|
br.i8s
|
||||||
end
|
when 'UInt8'
|
||||||
r = ObjectValue.new(node.name, node.type, br.endian, data)
|
br.i8u
|
||||||
elsif node.size == -1
|
when 'SInt16', 'short'
|
||||||
r = ObjectValue.new(node.name, node.type, br.endian)
|
br.i16s
|
||||||
if children.size == 1 && children[0][:name] == 'Array' && children[0][:node].type == 'Array' && children[0][:node].array?
|
when 'UInt16', 'unsigned short'
|
||||||
if node.type == 'string'
|
br.i16u
|
||||||
size = parse_object_private(br, children[0][:children].find{|e| e[:name] == 'size'}).value
|
when 'SInt32', 'int'
|
||||||
r.value = br.read(size * children[0][:children].find{|e| e[:name] == 'data'}[:node].size).force_encoding('utf-8')
|
br.i32s
|
||||||
br.align(4) if children[0][:node].flags & 0x4000 != 0
|
when 'UInt32', 'unsigned int', 'Type*'
|
||||||
|
br.i32u
|
||||||
|
when 'SInt64', 'long long'
|
||||||
|
br.i64s
|
||||||
|
when 'UInt64', 'unsigned long long'
|
||||||
|
br.i64u
|
||||||
|
when 'float'
|
||||||
|
br.float
|
||||||
|
when 'double'
|
||||||
|
br.double
|
||||||
else
|
else
|
||||||
r.value = parse_object_private(br, children[0]).value
|
br.read(node.size)
|
||||||
end
|
end
|
||||||
elsif node.type == 'StreamingInfo'
|
br.jmp(pos + node.size) if node.size >= 0
|
||||||
children.each{|child| r[child[:name]] = parse_object_private(br, child)}
|
elsif node.array?
|
||||||
r.value = @res_s.byteslice(r['offset'].value, r['size'].value) if r['path'].value == "archive:/#{name}/#{name}.resS"
|
|
||||||
else
|
|
||||||
children.each do |child|
|
|
||||||
r[child[:name]] = parse_object_private(br, child)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
elsif !children.empty?
|
|
||||||
pos = br.pos
|
|
||||||
r = ObjectValue.new(node.name, node.type, br.endian)
|
|
||||||
r.is_struct = true
|
|
||||||
children.each do |child|
|
children.each do |child|
|
||||||
r[child[:name]] = parse_object_private(br, child)
|
next ret[child.name] = parse_object_private(br, child) unless child.name == 'data'
|
||||||
|
size = ret['size']&.value || raise('`size` node must appear before `data` node in array node')
|
||||||
|
ret.value =
|
||||||
|
if child.children.empty? && (!child.need_align? || br.pos % 4 == 0 && child.size % 4 == 0)
|
||||||
|
if node.type == 'TypelessData'
|
||||||
|
br.read(size * child.size)
|
||||||
|
elsif child.type == 'char'
|
||||||
|
# string
|
||||||
|
br.read(size * child.size).force_encoding('utf-8')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
ret.value ||= Array.new(size){parse_object_private(br, child)}
|
||||||
|
ret['data'] = ret.value
|
||||||
end
|
end
|
||||||
|
elsif children.size == 1 && children[0].array? && children[0].type == 'Array' && children[0].name == 'Array'
|
||||||
|
ret = parse_object_private(br, children[0])
|
||||||
|
ret.name = node.name
|
||||||
|
ret.type = node.type
|
||||||
else
|
else
|
||||||
pos = br.pos
|
ret.attr = children.map{|c| [c.name, parse_object_private(br, c)]}.to_h
|
||||||
value = nil
|
if node.type == 'StreamingInfo'
|
||||||
case node.type
|
ret.value =
|
||||||
when 'bool'
|
if ret['path'].value == "archive:/#{name}/#{name}.resource"
|
||||||
value = (br.i8 != 0)
|
@resource&.byteslice(ret['offset'].value, ret['size'].value)
|
||||||
when 'SInt8'
|
elsif ret['path'].value == "archive:/#{name}/#{name}.resS"
|
||||||
value = br.i8s
|
@res_s&.byteslice(ret['offset'].value, ret['size'].value)
|
||||||
when 'UInt8', 'char'
|
end
|
||||||
value = br.i8u
|
|
||||||
when 'SInt16', 'short'
|
|
||||||
value = br.i16s
|
|
||||||
when 'UInt16', 'unsigned short'
|
|
||||||
value = br.i16u
|
|
||||||
when 'SInt32', 'int'
|
|
||||||
value = br.i32s
|
|
||||||
when 'UInt32', 'unsigned int'
|
|
||||||
value = br.i32u
|
|
||||||
when 'SInt64', 'long long'
|
|
||||||
value = br.i64s
|
|
||||||
when 'UInt64', 'unsigned long long'
|
|
||||||
value = br.i64u
|
|
||||||
when 'float'
|
|
||||||
value = br.float
|
|
||||||
when 'double'
|
|
||||||
value = br.double
|
|
||||||
when 'ColorRGBA'
|
|
||||||
value = [br.i8u, br.i8u, br.i8u, br.i8u]
|
|
||||||
else
|
else
|
||||||
value = br.read(node.size)
|
ret.is_struct = true
|
||||||
end
|
end
|
||||||
br.jmp(pos + node.size)
|
|
||||||
r = ObjectValue.new(node.name, node.type, br.endian, value)
|
|
||||||
end
|
end
|
||||||
br.align(4) if node.flags & 0x4000 != 0
|
br.align(4) if node.need_align?
|
||||||
r
|
ret
|
||||||
end
|
|
||||||
|
|
||||||
def self.object_simplify(obj)
|
|
||||||
if obj.class != ObjectValue
|
|
||||||
obj
|
|
||||||
elsif obj.type == 'pair'
|
|
||||||
[object_simplify(obj['first']), object_simplify(obj['second'])]
|
|
||||||
elsif obj.type == 'map' && obj.array?
|
|
||||||
obj.value.map{|e| [object_simplify(e['first']), object_simplify(e['second'])]}.to_h
|
|
||||||
elsif obj.value?
|
|
||||||
object_simplify(obj.value)
|
|
||||||
elsif obj.array?
|
|
||||||
obj.value.map{|e| object_simplify(e)}
|
|
||||||
else
|
|
||||||
hash = {}
|
|
||||||
obj.keys.each do |key|
|
|
||||||
hash[key] = object_simplify(obj[key])
|
|
||||||
end
|
|
||||||
hash
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.parse_type_tree(klass)
|
|
||||||
return nil unless klass.type_tree
|
|
||||||
nodes = klass.type_tree.nodes
|
|
||||||
tree = {}
|
|
||||||
stack = []
|
|
||||||
nodes.each do |node|
|
|
||||||
this = { name: node.name, node: node, children: [] }
|
|
||||||
if node.depth == 0
|
|
||||||
tree = this
|
|
||||||
else
|
|
||||||
stack[node.depth - 1][:children] << this
|
|
||||||
end
|
|
||||||
stack[node.depth] = this
|
|
||||||
end
|
|
||||||
tree
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -2,19 +2,36 @@
|
|||||||
|
|
||||||
require 'extlz4'
|
require 'extlz4'
|
||||||
require 'extlzma'
|
require 'extlzma'
|
||||||
|
require 'mikunyan/asset'
|
||||||
|
require 'mikunyan/binary_reader'
|
||||||
|
|
||||||
module Mikunyan
|
module Mikunyan
|
||||||
# Class for representing Unity AssetBundle
|
# Class for representing Unity AssetBundle
|
||||||
# @attr_reader [String] signature file signature (UnityRaw or UnityFS)
|
# @attr_reader [String] signature file signature (UnityRaw or UnityFS)
|
||||||
# @attr_reader [Integer] format file format number
|
# @attr_reader [Integer] format file format number
|
||||||
# @attr_reader [String] unity_version version string of Unity to use this AssetBundle
|
# @attr_reader [String] unity_version version string of Unity for this AssetBundle
|
||||||
# @attr_reader [String] generator_version version string of generator
|
# @attr_reader [String] generator_version version string of generator
|
||||||
# @attr_reader [Array<Mikunyan::Asset>] assets included Assets
|
# @attr_reader [String] guid unique identifier (can be zero)
|
||||||
|
# @attr_reader [Array<Mikunyan::Asset>] assets contained Assets
|
||||||
class AssetBundle
|
class AssetBundle
|
||||||
attr_reader :signature, :format, :unity_version, :generator_version, :assets
|
attr_reader :signature, :format, :unity_version, :generator_version, :guid, :assets, :blobs
|
||||||
|
|
||||||
# Load AssetBundle from binary string
|
AssetEntry = Struct.new(:name, :data, :blob?, :status, keyword_init: true)
|
||||||
# @param [String] bin binary data
|
|
||||||
|
# @param [String,Integer] index
|
||||||
|
# @return [Mikunyan::Asset,nil]
|
||||||
|
def [](index)
|
||||||
|
index.is_a?(String) ? @assets.find{|e| e.name == index} : @assets[index]
|
||||||
|
end
|
||||||
|
|
||||||
|
# Same as assets.each
|
||||||
|
# @return [Enumerator<Mikunyan::Asset>,Array<Mikunyan::Asset>]
|
||||||
|
def each_asset(&block)
|
||||||
|
@assets.each(&block)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Loads AssetBundle from binary string
|
||||||
|
# @param [String,IO] bin binary data
|
||||||
# @return [Mikunyan::AssetBundle] deserialized AssetBundle object
|
# @return [Mikunyan::AssetBundle] deserialized AssetBundle object
|
||||||
def self.load(bin)
|
def self.load(bin)
|
||||||
r = AssetBundle.new
|
r = AssetBundle.new
|
||||||
@@ -22,11 +39,13 @@ module Mikunyan
|
|||||||
r
|
r
|
||||||
end
|
end
|
||||||
|
|
||||||
# Load AssetBundle from file
|
# Loads AssetBundle from file
|
||||||
# @param [String] file file name
|
# @param [String] file file name
|
||||||
# @return [Mikunyan::AssetBundle] deserialized AssetBundle object
|
# @return [Mikunyan::AssetBundle] deserialized AssetBundle object
|
||||||
def self.file(file)
|
def self.file(file)
|
||||||
AssetBundle.load(File.binread(file))
|
File.open(file, 'rb') do |io|
|
||||||
|
AssetBundle.load(io)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
@@ -34,84 +53,71 @@ module Mikunyan
|
|||||||
def load(bin)
|
def load(bin)
|
||||||
br = BinaryReader.new(bin)
|
br = BinaryReader.new(bin)
|
||||||
@signature = br.cstr
|
@signature = br.cstr
|
||||||
|
raise("Invalid signature: #{@signature}") unless @signature.start_with?('Unity')
|
||||||
|
|
||||||
@format = br.i32
|
@format = br.i32
|
||||||
@unity_version = br.cstr
|
@unity_version = br.cstr
|
||||||
@generator_version = br.cstr
|
@generator_version = br.cstr
|
||||||
|
|
||||||
case @signature
|
@format < 6 ? load_unity_raw(br) : load_unity_fs(br)
|
||||||
when 'UnityRaw'
|
|
||||||
load_unity_raw(br, false)
|
|
||||||
when 'UnityFS'
|
|
||||||
load_unity_fs(br)
|
|
||||||
when 'UnityWeb'
|
|
||||||
if @format <= 3
|
|
||||||
load_unity_raw(br, true)
|
|
||||||
else
|
|
||||||
load_unity_fs(br)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
raise("Unknown signature: #{@signature}")
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def load_unity_raw(br, compressed)
|
# @param [Mikunyan::BinaryReader] br
|
||||||
|
def load_unity_raw(br)
|
||||||
@assets = []
|
@assets = []
|
||||||
|
|
||||||
file_size = br.i32u
|
_file_size = br.i32u
|
||||||
header_size = br.i32u
|
header_size = br.i32u
|
||||||
|
br.pos = header_size
|
||||||
if compressed
|
# この部分全然わからん(ファイルの最後まで読まないとダメらしい?)
|
||||||
br.adv(4)
|
block = br.read(nil)
|
||||||
block_count = br.i32u
|
data = @signature == 'UnityRaw' ? block : uncompress_lzma(block, true)
|
||||||
blocks = block_count.times.map{{ c: br.i32u, u: br.i32u }}
|
br = BinaryReader.new(data)
|
||||||
br.jmp(header_size)
|
|
||||||
data = ''
|
|
||||||
blocks.each{|b| data << LZMA.decode(br.read(b[:c]))}
|
|
||||||
br = BinaryReader.new(data)
|
|
||||||
else
|
|
||||||
br.jmp(header_size)
|
|
||||||
end
|
|
||||||
|
|
||||||
asset_count = br.i32u
|
asset_count = br.i32u
|
||||||
asset_count.times do
|
asset_entries = Array.new(asset_count) do
|
||||||
asset_pos = br.pos
|
name = br.cstr
|
||||||
asset_name = br.cstr
|
offset = br.i32u
|
||||||
asset_header_size = br.i32u
|
size = br.i32u
|
||||||
asset_size = br.i32u
|
is_asset = ['', '.assets'].include?(split_name(name)[1]) && size > 16
|
||||||
br.jmp(asset_pos + asset_header_size - 4)
|
AssetEntry.new(name: name, data: br.read_abs(size, offset), blob?: !is_asset)
|
||||||
asset_data = br.read(asset_size)
|
|
||||||
asset = Asset.load(asset_data, asset_name)
|
|
||||||
@assets << asset
|
|
||||||
end
|
end
|
||||||
|
process_asset_entries(asset_entries)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# @param [Mikunyan::BinaryReader] br
|
||||||
def load_unity_fs(br)
|
def load_unity_fs(br)
|
||||||
@assets = []
|
|
||||||
|
|
||||||
file_size = br.i64u
|
file_size = br.i64u
|
||||||
ci_block_size = br.i32u
|
ci_block_size = br.i32u
|
||||||
ui_block_size = br.i32u
|
ui_block_size = br.i32u
|
||||||
flags = br.i32u
|
flags = br.i32u
|
||||||
|
|
||||||
head = BinaryReader.new(uncompress(flags & 0x80 == 0 ? br.read(ci_block_size) : br.read_abs(ci_block_size, file_size - ci_block_size), ui_block_size, flags))
|
head = BinaryReader.new(uncompress(flags & 0x80 == 0 ? br.read(ci_block_size) : br.read_abs(ci_block_size, file_size - ci_block_size), ui_block_size, flags))
|
||||||
guid = head.read(16)
|
@guid = head.read(16)
|
||||||
|
|
||||||
blocks = []
|
|
||||||
block_count = head.i32u
|
block_count = head.i32u
|
||||||
block_count.times{blocks << { u: head.i32u, c: head.i32u, f: head.i16u }}
|
raw_data = Array.new(block_count) do
|
||||||
|
u_size = head.i32u
|
||||||
|
c_size = head.i32u
|
||||||
|
flags = head.i16u
|
||||||
|
uncompress(br.read(c_size), u_size, flags)
|
||||||
|
end.join
|
||||||
|
|
||||||
asset_blocks = []
|
|
||||||
asset_count = head.i32u
|
asset_count = head.i32u
|
||||||
asset_count.times{asset_blocks << { offset: head.i64u, size: head.i64u, status: head.i32, name: head.cstr }}
|
asset_entries = Array.new(asset_count) do
|
||||||
|
offset = head.i64u
|
||||||
|
size = head.i64u
|
||||||
|
status = head.i32
|
||||||
|
AssetEntry.new(name: head.cstr, data: raw_data.byteslice(offset, size), blob?: status != 4, status: status)
|
||||||
|
end
|
||||||
|
process_asset_entries(asset_entries)
|
||||||
|
end
|
||||||
|
|
||||||
raw_data = ''
|
def process_asset_entries(asset_entries)
|
||||||
blocks.each{|b| raw_data << uncompress(br.read(b[:c]), b[:u], b[:f])}
|
@blobs = asset_entries.select(&:blob?).map{|e| [e.name, e.data]}.to_h
|
||||||
|
@assets = asset_entries.reject(&:blob?).map do |e|
|
||||||
asset_blocks.each do |b|
|
basename = split_name(e.name)[0]
|
||||||
next if b[:name].end_with?('.resS')
|
Asset.load(e.data, e.name, @blobs["#{basename}.resource"], @blobs["#{basename}.resS"])
|
||||||
res_s = asset_blocks.find{|e| e[:name] == "#{b[:name]}.resS"}
|
|
||||||
asset = Asset.load(raw_data.byteslice(b[:offset], b[:size]), b[:name], res_s && raw_data.byteslice(res_s[:offset], res_s[:size]))
|
|
||||||
@assets << asset
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -119,16 +125,33 @@ module Mikunyan
|
|||||||
case flags & 0x3f
|
case flags & 0x3f
|
||||||
when 0
|
when 0
|
||||||
block
|
block
|
||||||
# when 1
|
when 1
|
||||||
# LZMA
|
uncompress_lzma(block)
|
||||||
when 2, 3
|
when 2, 3
|
||||||
LZ4.raw_decode(block, max_dest_size)
|
LZ4.block_decode(block, max_dest_size)
|
||||||
# when 4
|
# when 4
|
||||||
# LZHMA
|
# LZHMA
|
||||||
else
|
else
|
||||||
warn("Unknown compression flag: #{@flags}")
|
warn("Unknown compression flag: #{flags}")
|
||||||
block
|
block
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def uncompress_lzma(block, with_max_len = false)
|
||||||
|
prop = block.ord
|
||||||
|
filter = LZMA.lzma1(dictsize: block.unpack1('@1V'), lc: prop % 9, lp: (prop / 9) % 5, pb: prop / 45)
|
||||||
|
max_len = block.unpack1('@5V') | block.unpack1('@9V') << 32 if with_max_len
|
||||||
|
StringIO.open(block) do |io|
|
||||||
|
io.seek(with_max_len ? 13 : 5)
|
||||||
|
LZMA.raw_decode(io, filter) do |lzma|
|
||||||
|
lzma.read(max_len)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def split_name(str)
|
||||||
|
m = str.match(/\A(.*?)(\.[^.]*)?\z/)
|
||||||
|
[m[1], m[2] || '']
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'mikunyan/object_value'
|
||||||
|
|
||||||
|
module Mikunyan
|
||||||
|
# Class for representing decoded base object
|
||||||
|
class BaseObject < Mikunyan::ObjectValue
|
||||||
|
attr_accessor :object_entry
|
||||||
|
|
||||||
|
def path_id
|
||||||
|
@object_entry&.path_id
|
||||||
|
end
|
||||||
|
|
||||||
|
def object_name
|
||||||
|
@attr['m_Name']&.value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
module CustomTypes
|
||||||
|
def self.get_custom_type(name, class_id = nil)
|
||||||
|
class_id ||= Mikunyan::Constants::CLASS_NAME2ID[name]
|
||||||
|
@custom_types&.[]([class_id, name]) || Mikunyan::BaseObject
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.set_custom_type(klass, name, class_id = nil)
|
||||||
|
class_id ||= Mikunyan::Constants::CLASS_NAME2ID[name]
|
||||||
|
@custom_types ||= {}
|
||||||
|
@custom_types[[class_id, name].freeze] = klass
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
require 'mikunyan/types/text_asset'
|
||||||
|
require 'mikunyan/types/texture2d'
|
||||||
@@ -5,18 +5,16 @@ require 'bin_utils'
|
|||||||
module Mikunyan
|
module Mikunyan
|
||||||
# Class for manipulating binary string
|
# Class for manipulating binary string
|
||||||
# @attr [Symbol] endian endianness
|
# @attr [Symbol] endian endianness
|
||||||
# @attr [Integer] pos position
|
|
||||||
# @attr [Integer] length data size
|
|
||||||
class BinaryReader
|
class BinaryReader
|
||||||
attr_accessor :endian, :pos, :length
|
attr_accessor :endian
|
||||||
|
|
||||||
# Constructor
|
# Constructor
|
||||||
# @param [String] data binary string
|
# @param [IO,String] io binary String or IO
|
||||||
# @param [Symbol] endian endianness
|
# @param [Symbol] endian endianness
|
||||||
def initialize(data, endian = :big)
|
def initialize(io, endian = :big)
|
||||||
@data = data
|
@io = io.is_a?(String) ? StringIO.new(io, 'r') : io.dup
|
||||||
@pos = 0
|
@io.binmode
|
||||||
@length = data.bytesize
|
@base_pos = @io.pos
|
||||||
@endian = endian
|
@endian = endian
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -26,137 +24,117 @@ module Mikunyan
|
|||||||
@endian == :little
|
@endian == :little
|
||||||
end
|
end
|
||||||
|
|
||||||
# Jump to given position
|
# Tells current potision
|
||||||
# @param [Integer] pos position
|
# @return [Integer]
|
||||||
def jmp(pos = 0)
|
def pos
|
||||||
@pos = pos
|
@io.pos - @base_pos
|
||||||
end
|
end
|
||||||
|
|
||||||
# Advance position given size
|
# Jumps to given position
|
||||||
|
# @param [Integer] pos position
|
||||||
|
def jmp(jmp_pos = 0)
|
||||||
|
@io.pos = jmp_pos + @base_pos
|
||||||
|
end
|
||||||
|
alias pos= jmp
|
||||||
|
|
||||||
|
# Advances position given size
|
||||||
# @param [Integer] size size
|
# @param [Integer] size size
|
||||||
def adv(size = 0)
|
def adv(size = 0)
|
||||||
@pos += size
|
@io.seek(size, IO::SEEK_CUR)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Round up position to multiple of given size
|
# Rounds up position to multiple of given size
|
||||||
# @param [Integer] size size
|
# @param [Integer] size size
|
||||||
def align(size)
|
def align(size)
|
||||||
@pos = (@pos + size - 1) / size * size
|
rem = pos % size
|
||||||
|
adv(size - rem) if rem > 0
|
||||||
end
|
end
|
||||||
|
|
||||||
# Read given size of binary string and seek
|
# Reads given size of binary string and seek
|
||||||
# @param [Integer] size size
|
# @param [Integer] size size
|
||||||
# @return [String] data
|
# @return [String] data
|
||||||
def read(size)
|
def read(size)
|
||||||
data = @data.byteslice(@pos, size)
|
ret = @io.read(size)
|
||||||
@pos += size
|
raise EOFError if ret.nil? || size && ret.bytesize < size
|
||||||
data
|
ret
|
||||||
end
|
end
|
||||||
|
|
||||||
# Read given size of binary string from specified position. This method does not seek.
|
# Reads given size of binary string from specified position. This method does not seek.
|
||||||
# @param [Integer] size size
|
# @param [Integer] size size
|
||||||
# @param [Integer] pos position
|
# @param [Integer] pos position
|
||||||
# @return [String] data
|
# @return [String] data
|
||||||
def read_abs(size, pos)
|
def read_abs(size, jmp_pos)
|
||||||
@data.byteslice(pos, size)
|
orig_pos = pos
|
||||||
|
jmp(jmp_pos)
|
||||||
|
ret = read(size)
|
||||||
|
jmp(orig_pos)
|
||||||
|
ret
|
||||||
end
|
end
|
||||||
|
|
||||||
# Read string until null character
|
# Reads string until null character
|
||||||
# @return [String] string
|
# @return [String] string
|
||||||
def cstr
|
def cstr
|
||||||
r = @data.unpack1("@#{pos}Z*")
|
raise EOFError if @io.eof?
|
||||||
@pos += r.bytesize + 1
|
@io.each_byte.take_while(&:nonzero?).pack('C*')
|
||||||
r
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Read 8bit signed integer
|
# Reads an 8bit bool value
|
||||||
def i8
|
def bool
|
||||||
i8s
|
i8u != 0
|
||||||
end
|
end
|
||||||
|
|
||||||
# Read 8bit signed integer
|
# Reads an 8bit signed integer value
|
||||||
def i8s
|
def i8s
|
||||||
r = BinUtils.get_sint8(@data, @pos)
|
BinUtils.get_sint8(read(1))
|
||||||
@pos += 1
|
|
||||||
r
|
|
||||||
end
|
end
|
||||||
|
alias i8 i8s
|
||||||
|
|
||||||
# Read 8bit unsigned integer
|
# Reads an 8bit unsigned integer value
|
||||||
def i8u
|
def i8u
|
||||||
r = BinUtils.get_int8(@data, @pos)
|
@io.getbyte
|
||||||
@pos += 1
|
|
||||||
r
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Read 16bit signed integer
|
# Reads a 16bit signed integer value
|
||||||
def i16
|
|
||||||
i16s
|
|
||||||
end
|
|
||||||
|
|
||||||
# Read 16bit signed integer
|
|
||||||
def i16s
|
def i16s
|
||||||
r = little? ? BinUtils.get_sint16_le(@data, @pos) : BinUtils.get_sint16_be(@data, @pos)
|
little? ? BinUtils.get_sint16_le(read(2)) : BinUtils.get_sint16_be(read(2))
|
||||||
@pos += 2
|
|
||||||
r
|
|
||||||
end
|
end
|
||||||
|
alias i16 i16s
|
||||||
|
|
||||||
# Read 16bit unsigned integer
|
# Reads a 16bit unsigned integer value
|
||||||
def i16u
|
def i16u
|
||||||
r = little? ? BinUtils.get_int16_le(@data, @pos) : BinUtils.get_int16_be(@data, @pos)
|
little? ? BinUtils.get_int16_le(read(2)) : BinUtils.get_int16_be(read(2))
|
||||||
@pos += 2
|
|
||||||
r
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Read 32bit signed integer
|
# Reads a 32bit signed integer value
|
||||||
def i32
|
|
||||||
i32s
|
|
||||||
end
|
|
||||||
|
|
||||||
# Read 32bit signed integer
|
|
||||||
def i32s
|
def i32s
|
||||||
r = little? ? BinUtils.get_sint32_le(@data, @pos) : BinUtils.get_sint32_be(@data, @pos)
|
little? ? BinUtils.get_sint32_le(read(4)) : BinUtils.get_sint32_be(read(4))
|
||||||
@pos += 4
|
|
||||||
r
|
|
||||||
end
|
end
|
||||||
|
alias i32 i32s
|
||||||
|
|
||||||
# Read 32bit unsigned integer
|
# Reads a 32bit unsigned integer value
|
||||||
def i32u
|
def i32u
|
||||||
r = little? ? BinUtils.get_int32_le(@data, @pos) : BinUtils.get_int32_be(@data, @pos)
|
little? ? BinUtils.get_int32_le(read(4)) : BinUtils.get_int32_be(read(4))
|
||||||
@pos += 4
|
|
||||||
r
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Read 64bit signed integer
|
# Reads a 64bit signed integer value
|
||||||
def i64
|
|
||||||
i64s
|
|
||||||
end
|
|
||||||
|
|
||||||
# Read 64bit signed integer
|
|
||||||
def i64s
|
def i64s
|
||||||
r = little? ? BinUtils.get_sint64_le(@data, @pos) : BinUtils.get_sint64_be(@data, @pos)
|
little? ? BinUtils.get_sint64_le(read(8)) : BinUtils.get_sint64_be(read(8))
|
||||||
@pos += 8
|
|
||||||
r
|
|
||||||
end
|
end
|
||||||
|
alias i64 i64s
|
||||||
|
|
||||||
# Read 64bit unsigned integer
|
# Reads a 64bit unsigned integer value
|
||||||
def i64u
|
def i64u
|
||||||
r = little? ? BinUtils.get_int64_le(@data, @pos) : BinUtils.get_int64_be(@data, @pos)
|
little? ? BinUtils.get_int64_le(read(8)) : BinUtils.get_int64_be(read(8))
|
||||||
@pos += 8
|
|
||||||
r
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Read 32bit floating point value
|
# Reads a 32bit floating point value
|
||||||
def float
|
def float
|
||||||
r = little? ? @data.byteslice(@pos, 4).unpack1('e') : @data.byteslice(@pos, 4).unpack1('g')
|
little? ? read(4).unpack1('e') : read(4).unpack1('g')
|
||||||
@pos += 4
|
|
||||||
r
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Read 64bit floating point value
|
# Reads a 64bit floating point value
|
||||||
def double
|
def double
|
||||||
r = little? ? @data.byteslice(@pos, 8).unpack1('E') : @data.byteslice(@pos, 8).unpack1('G')
|
little? ? read(8).unpack1('E') : read(8).unpack1('G')
|
||||||
@pos += 8
|
|
||||||
r
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
+504
-341
@@ -1,347 +1,510 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Mikunyan
|
module Mikunyan
|
||||||
private
|
# Module for defining and uzing constants
|
||||||
|
module Constants
|
||||||
|
# @param [Integer] pos position value
|
||||||
|
# @param [String] buffer string buffer
|
||||||
|
# @return [String,nil]
|
||||||
|
def self.get_string_or_default(pos, buffer)
|
||||||
|
pos & 0x80000000 == 0 ? buffer.unpack1("@#{pos}Z*") : STRING_TABLE[pos & 0x7fffffff]
|
||||||
|
end
|
||||||
|
|
||||||
STRING_TABLE = {
|
STRING_TABLE = {
|
||||||
0 => 'AABB',
|
0 => 'AABB',
|
||||||
5 => 'AnimationClip',
|
5 => 'AnimationClip',
|
||||||
19 => 'AnimationCurve',
|
19 => 'AnimationCurve',
|
||||||
34 => 'AnimationState',
|
34 => 'AnimationState',
|
||||||
49 => 'Array',
|
49 => 'Array',
|
||||||
55 => 'Base',
|
55 => 'Base',
|
||||||
60 => 'BitField',
|
60 => 'BitField',
|
||||||
69 => 'bitset',
|
69 => 'bitset',
|
||||||
76 => 'bool',
|
76 => 'bool',
|
||||||
81 => 'char',
|
81 => 'char',
|
||||||
86 => 'ColorRGBA',
|
86 => 'ColorRGBA',
|
||||||
96 => 'Component',
|
96 => 'Component',
|
||||||
106 => 'data',
|
106 => 'data',
|
||||||
111 => 'deque',
|
111 => 'deque',
|
||||||
117 => 'double',
|
117 => 'double',
|
||||||
124 => 'dynamic_array',
|
124 => 'dynamic_array',
|
||||||
138 => 'FastPropertyName',
|
138 => 'FastPropertyName',
|
||||||
155 => 'first',
|
155 => 'first',
|
||||||
161 => 'float',
|
161 => 'float',
|
||||||
167 => 'Font',
|
167 => 'Font',
|
||||||
172 => 'GameObject',
|
172 => 'GameObject',
|
||||||
183 => 'Generic Mono',
|
183 => 'Generic Mono',
|
||||||
196 => 'GradientNEW',
|
196 => 'GradientNEW',
|
||||||
208 => 'GUID',
|
208 => 'GUID',
|
||||||
213 => 'GUIStyle',
|
213 => 'GUIStyle',
|
||||||
222 => 'int',
|
222 => 'int',
|
||||||
226 => 'list',
|
226 => 'list',
|
||||||
231 => 'long long',
|
231 => 'long long',
|
||||||
241 => 'map',
|
241 => 'map',
|
||||||
245 => 'Matrix4x4f',
|
245 => 'Matrix4x4f',
|
||||||
256 => 'MdFour',
|
256 => 'MdFour',
|
||||||
263 => 'MonoBehaviour',
|
263 => 'MonoBehaviour',
|
||||||
277 => 'MonoScript',
|
277 => 'MonoScript',
|
||||||
288 => 'm_ByteSize',
|
288 => 'm_ByteSize',
|
||||||
299 => 'm_Curve',
|
299 => 'm_Curve',
|
||||||
307 => 'm_EditorClassIdentifier',
|
307 => 'm_EditorClassIdentifier',
|
||||||
331 => 'm_EditorHideFlags',
|
331 => 'm_EditorHideFlags',
|
||||||
349 => 'm_Enabled',
|
349 => 'm_Enabled',
|
||||||
359 => 'm_ExtensionPtr',
|
359 => 'm_ExtensionPtr',
|
||||||
374 => 'm_GameObject',
|
374 => 'm_GameObject',
|
||||||
387 => 'm_Index',
|
387 => 'm_Index',
|
||||||
395 => 'm_IsArray',
|
395 => 'm_IsArray',
|
||||||
405 => 'm_IsStatic',
|
405 => 'm_IsStatic',
|
||||||
416 => 'm_MetaFlag',
|
416 => 'm_MetaFlag',
|
||||||
427 => 'm_Name',
|
427 => 'm_Name',
|
||||||
434 => 'm_ObjectHideFlags',
|
434 => 'm_ObjectHideFlags',
|
||||||
452 => 'm_PrefabInternal',
|
452 => 'm_PrefabInternal',
|
||||||
469 => 'm_PrefabParentObject',
|
469 => 'm_PrefabParentObject',
|
||||||
490 => 'm_Script',
|
490 => 'm_Script',
|
||||||
499 => 'm_StaticEditorFlags',
|
499 => 'm_StaticEditorFlags',
|
||||||
519 => 'm_Type',
|
519 => 'm_Type',
|
||||||
526 => 'm_Version',
|
526 => 'm_Version',
|
||||||
536 => 'Object',
|
536 => 'Object',
|
||||||
543 => 'pair',
|
543 => 'pair',
|
||||||
548 => 'PPtr<Component>',
|
548 => 'PPtr<Component>',
|
||||||
564 => 'PPtr<GameObject>',
|
564 => 'PPtr<GameObject>',
|
||||||
581 => 'PPtr<Material>',
|
581 => 'PPtr<Material>',
|
||||||
596 => 'PPtr<MonoBehaviour>',
|
596 => 'PPtr<MonoBehaviour>',
|
||||||
616 => 'PPtr<MonoScript>',
|
616 => 'PPtr<MonoScript>',
|
||||||
633 => 'PPtr<Object>',
|
633 => 'PPtr<Object>',
|
||||||
646 => 'PPtr<Prefab>',
|
646 => 'PPtr<Prefab>',
|
||||||
659 => 'PPtr<Sprite>',
|
659 => 'PPtr<Sprite>',
|
||||||
672 => 'PPtr<TextAsset>',
|
672 => 'PPtr<TextAsset>',
|
||||||
688 => 'PPtr<Texture>',
|
688 => 'PPtr<Texture>',
|
||||||
702 => 'PPtr<Texture2D>',
|
702 => 'PPtr<Texture2D>',
|
||||||
718 => 'PPtr<Transform>',
|
718 => 'PPtr<Transform>',
|
||||||
734 => 'Prefab',
|
734 => 'Prefab',
|
||||||
741 => 'Quaternionf',
|
741 => 'Quaternionf',
|
||||||
753 => 'Rectf',
|
753 => 'Rectf',
|
||||||
759 => 'RectInt',
|
759 => 'RectInt',
|
||||||
767 => 'RectOffset',
|
767 => 'RectOffset',
|
||||||
778 => 'second',
|
778 => 'second',
|
||||||
785 => 'set',
|
785 => 'set',
|
||||||
789 => 'short',
|
789 => 'short',
|
||||||
795 => 'size',
|
795 => 'size',
|
||||||
800 => 'SInt16',
|
800 => 'SInt16',
|
||||||
807 => 'SInt32',
|
807 => 'SInt32',
|
||||||
814 => 'SInt64',
|
814 => 'SInt64',
|
||||||
821 => 'SInt8',
|
821 => 'SInt8',
|
||||||
827 => 'staticvector',
|
827 => 'staticvector',
|
||||||
840 => 'string',
|
840 => 'string',
|
||||||
847 => 'TextAsset',
|
847 => 'TextAsset',
|
||||||
857 => 'TextMesh',
|
857 => 'TextMesh',
|
||||||
866 => 'Texture',
|
866 => 'Texture',
|
||||||
874 => 'Texture2D',
|
874 => 'Texture2D',
|
||||||
884 => 'Transform',
|
884 => 'Transform',
|
||||||
894 => 'TypelessData',
|
894 => 'TypelessData',
|
||||||
907 => 'UInt16',
|
907 => 'UInt16',
|
||||||
914 => 'UInt32',
|
914 => 'UInt32',
|
||||||
921 => 'UInt64',
|
921 => 'UInt64',
|
||||||
928 => 'UInt8',
|
928 => 'UInt8',
|
||||||
934 => 'unsigned int',
|
934 => 'unsigned int',
|
||||||
947 => 'unsigned long long',
|
947 => 'unsigned long long',
|
||||||
966 => 'unsigned short',
|
966 => 'unsigned short',
|
||||||
981 => 'vector',
|
981 => 'vector',
|
||||||
988 => 'Vector2f',
|
988 => 'Vector2f',
|
||||||
997 => 'Vector3f',
|
997 => 'Vector3f',
|
||||||
1006 => 'Vector4f',
|
1006 => 'Vector4f',
|
||||||
1015 => 'm_ScriptingClassIdentifier',
|
1015 => 'm_ScriptingClassIdentifier',
|
||||||
1042 => 'Gradient'
|
1042 => 'Gradient',
|
||||||
}.freeze
|
1051 => 'Type*',
|
||||||
|
1057 => 'int2_storage',
|
||||||
|
1070 => 'int3_storage',
|
||||||
|
1083 => 'BoundsInt',
|
||||||
|
1093 => 'm_CorrespondingSourceObject',
|
||||||
|
1121 => 'm_PrefabInstance',
|
||||||
|
1138 => 'm_PrefabAsset'
|
||||||
|
}.freeze
|
||||||
|
|
||||||
CLASS_ID = {
|
CLASS_ID_TABLE = [
|
||||||
1 => 'GameObject',
|
[0, 'Object'],
|
||||||
2 => 'Component',
|
[1, 'GameObject'],
|
||||||
3 => 'LevelGameManager',
|
[2, 'Component'],
|
||||||
4 => 'Transform',
|
[3, 'LevelGameManager'],
|
||||||
5 => 'TimeManager',
|
[4, 'Transform'],
|
||||||
6 => 'GlobalGameManager',
|
[5, 'TimeManager'],
|
||||||
8 => 'Behaviour',
|
[6, 'GlobalGameManager'],
|
||||||
9 => 'GameManager',
|
[8, 'Behaviour'],
|
||||||
11 => 'AudioManager',
|
[9, 'GameManager'],
|
||||||
12 => 'ParticleAnimator',
|
[11, 'AudioManager'],
|
||||||
13 => 'InputManager',
|
[12, 'ParticleAnimator'],
|
||||||
15 => 'EllipsoidParticleEmitter',
|
[13, 'InputManager'],
|
||||||
17 => 'Pipeline',
|
[15, 'EllipsoidParticleEmitter'],
|
||||||
18 => 'EditorExtension',
|
[17, 'Pipeline'],
|
||||||
19 => 'Physics2DSettings',
|
[18, 'EditorExtension'],
|
||||||
20 => 'Camera',
|
[19, 'Physics2DSettings'],
|
||||||
21 => 'Material',
|
[20, 'Camera'],
|
||||||
23 => 'MeshRenderer',
|
[21, 'Material'],
|
||||||
25 => 'Renderer',
|
[23, 'MeshRenderer'],
|
||||||
26 => 'ParticleRenderer',
|
[25, 'Renderer'],
|
||||||
27 => 'Texture',
|
[26, 'ParticleRenderer'],
|
||||||
28 => 'Texture2D',
|
[27, 'Texture'],
|
||||||
29 => 'SceneSettings',
|
[28, 'Texture2D'],
|
||||||
30 => 'GraphicsSettings',
|
[29, 'Scene'],
|
||||||
33 => 'MeshFilter',
|
[29, 'SceneSettings'],
|
||||||
41 => 'OcclusionPortal',
|
[29, 'OcclusionCullingSettings'],
|
||||||
43 => 'Mesh',
|
[30, 'RenderManager'],
|
||||||
45 => 'Skybox',
|
[30, 'GraphicsSettings'],
|
||||||
47 => 'QualitySettings',
|
[33, 'MeshFilter'],
|
||||||
48 => 'Shader',
|
[41, 'OcclusionPortal'],
|
||||||
49 => 'TextAsset',
|
[43, 'Mesh'],
|
||||||
50 => 'Rigidbody2D',
|
[45, 'Skybox'],
|
||||||
51 => 'Physics2DManager',
|
[47, 'QualitySettings'],
|
||||||
53 => 'Collider2D',
|
[48, 'Shader'],
|
||||||
54 => 'Rigidbody',
|
[49, 'TextAsset'],
|
||||||
55 => 'PhysicsManager',
|
[50, 'Rigidbody2D'],
|
||||||
56 => 'Collider',
|
[51, 'Physics2DManager'],
|
||||||
57 => 'Joint',
|
[52, 'NotificationManager'],
|
||||||
58 => 'CircleCollider2D',
|
[53, 'Collider2D'],
|
||||||
59 => 'HingeJoint',
|
[54, 'Rigidbody'],
|
||||||
60 => 'PolygonCollider2D',
|
[55, 'PhysicsManager'],
|
||||||
61 => 'BoxCollider2D',
|
[56, 'Collider'],
|
||||||
62 => 'PhysicsMaterial2D',
|
[57, 'Joint'],
|
||||||
64 => 'MeshCollider',
|
[58, 'CircleCollider2D'],
|
||||||
65 => 'BoxCollider',
|
[59, 'HingeJoint'],
|
||||||
66 => 'SpriteCollider2D',
|
[60, 'PolygonCollider2D'],
|
||||||
68 => 'EdgeCollider2D',
|
[61, 'BoxCollider2D'],
|
||||||
72 => 'ComputeShader',
|
[62, 'PhysicsMaterial2D'],
|
||||||
74 => 'AnimationClip',
|
[64, 'MeshCollider'],
|
||||||
75 => 'ConstantForce',
|
[65, 'BoxCollider'],
|
||||||
76 => 'WorldParticleCollider',
|
[66, 'SpriteCollider2D'],
|
||||||
78 => 'TagManager',
|
[66, 'CompositeCollider2D'],
|
||||||
81 => 'AudioListener',
|
[68, 'EdgeCollider2D'],
|
||||||
82 => 'AudioSource',
|
[70, 'CapsuleCollider2D'],
|
||||||
83 => 'AudioClip',
|
[71, 'AnimationManager'],
|
||||||
84 => 'RenderTexture',
|
[72, 'ComputeShader'],
|
||||||
87 => 'MeshParticleEmitter',
|
[74, 'AnimationClip'],
|
||||||
88 => 'ParticleEmitter',
|
[75, 'ConstantForce'],
|
||||||
89 => 'Cubemap',
|
[76, 'WorldParticleCollider'],
|
||||||
90 => 'Avatar',
|
[78, 'TagManager'],
|
||||||
91 => 'AnimatorController',
|
[81, 'AudioListener'],
|
||||||
92 => 'GUILayer',
|
[82, 'AudioSource'],
|
||||||
93 => 'RuntimeAnimatorController',
|
[83, 'AudioClip'],
|
||||||
94 => 'ScriptMapper',
|
[84, 'RenderTexture'],
|
||||||
95 => 'Animator',
|
[86, 'CustomRenderTexture'],
|
||||||
96 => 'TrailRenderer',
|
[87, 'MeshParticleEmitter'],
|
||||||
98 => 'DelayedCallManager',
|
[88, 'ParticleEmitter'],
|
||||||
102 => 'TextMesh',
|
[89, 'Cubemap'],
|
||||||
104 => 'RenderSettings',
|
[90, 'Avatar'],
|
||||||
108 => 'Light',
|
[91, 'AnimatorController'],
|
||||||
109 => 'CGProgram',
|
[92, 'GUILayer'],
|
||||||
110 => 'BaseAnimationTrack',
|
[93, 'RuntimeAnimatorController'],
|
||||||
111 => 'Animation',
|
[94, 'ScriptMapper'],
|
||||||
114 => 'MonoBehaviour',
|
[95, 'Animator'],
|
||||||
115 => 'MonoScript',
|
[96, 'TrailRenderer'],
|
||||||
116 => 'MonoManager',
|
[98, 'DelayedCallManager'],
|
||||||
117 => 'Texture3D',
|
[102, 'TextMesh'],
|
||||||
118 => 'NewAnimationTrack',
|
[104, 'RenderSettings'],
|
||||||
119 => 'Projector',
|
[108, 'Light'],
|
||||||
120 => 'LineRenderer',
|
[109, 'CGProgram'],
|
||||||
121 => 'Flare',
|
[110, 'BaseAnimationTrack'],
|
||||||
122 => 'Halo',
|
[111, 'Animation'],
|
||||||
123 => 'LensFlare',
|
[114, 'MonoBehaviour'],
|
||||||
124 => 'FlareLayer',
|
[115, 'MonoScript'],
|
||||||
125 => 'HaloLayer',
|
[116, 'MonoManager'],
|
||||||
126 => 'NavMeshAreas',
|
[117, 'Texture3D'],
|
||||||
127 => 'HaloManager',
|
[118, 'NewAnimationTrack'],
|
||||||
128 => 'Font',
|
[119, 'Projector'],
|
||||||
129 => 'PlayerSettings',
|
[120, 'LineRenderer'],
|
||||||
130 => 'NamedObject',
|
[121, 'Flare'],
|
||||||
131 => 'GUITexture',
|
[122, 'Halo'],
|
||||||
132 => 'GUIText',
|
[123, 'LensFlare'],
|
||||||
133 => 'GUIElement',
|
[124, 'FlareLayer'],
|
||||||
134 => 'PhysicMaterial',
|
[125, 'HaloLayer'],
|
||||||
135 => 'SphereCollider',
|
[126, 'NavMeshLayers'],
|
||||||
136 => 'CapsuleCollider',
|
[126, 'NavMeshAreas'],
|
||||||
137 => 'SkinnedMeshRenderer',
|
[126, 'NavMeshProjectSettings'],
|
||||||
138 => 'FixedJoint',
|
[127, 'HaloManager'],
|
||||||
140 => 'RaycastCollider',
|
[128, 'Font'],
|
||||||
141 => 'BuildSettings',
|
[129, 'PlayerSettings'],
|
||||||
142 => 'AssetBundle',
|
[130, 'NamedObject'],
|
||||||
143 => 'CharacterController',
|
[131, 'GUITexture'],
|
||||||
144 => 'CharacterJoint',
|
[132, 'GUIText'],
|
||||||
145 => 'SpringJoint',
|
[133, 'GUIElement'],
|
||||||
146 => 'WheelCollider',
|
[134, 'PhysicMaterial'],
|
||||||
147 => 'ResourceManager',
|
[135, 'SphereCollider'],
|
||||||
148 => 'NetworkView',
|
[136, 'CapsuleCollider'],
|
||||||
149 => 'NetworkManager',
|
[137, 'SkinnedMeshRenderer'],
|
||||||
150 => 'PreloadData',
|
[138, 'FixedJoint'],
|
||||||
152 => 'MovieTexture',
|
[140, 'RaycastCollider'],
|
||||||
153 => 'ConfigurableJoint',
|
[141, 'BuildSettings'],
|
||||||
154 => 'TerrainCollider',
|
[142, 'AssetBundle'],
|
||||||
155 => 'MasterServerInterface',
|
[143, 'CharacterController'],
|
||||||
156 => 'TerrainData',
|
[144, 'CharacterJoint'],
|
||||||
157 => 'LightmapSettings',
|
[145, 'SpringJoint'],
|
||||||
158 => 'WebCamTexture',
|
[146, 'WheelCollider'],
|
||||||
159 => 'EditorSettings',
|
[147, 'ResourceManager'],
|
||||||
160 => 'InteractiveCloth',
|
[148, 'NetworkView'],
|
||||||
161 => 'ClothRenderer',
|
[149, 'NetworkManager'],
|
||||||
162 => 'EditorUserSettings',
|
[150, 'PreloadData'],
|
||||||
163 => 'SkinnedCloth',
|
[152, 'MovieTexture'],
|
||||||
164 => 'AudioReverbFilter',
|
[153, 'ConfigurableJoint'],
|
||||||
165 => 'AudioHighPassFilter',
|
[154, 'TerrainCollider'],
|
||||||
166 => 'AudioChorusFilter',
|
[155, 'MasterServerInterface'],
|
||||||
167 => 'AudioReverbZone',
|
[156, 'TerrainData'],
|
||||||
168 => 'AudioEchoFilter',
|
[157, 'LightmapSettings'],
|
||||||
169 => 'AudioLowPassFilter',
|
[158, 'WebCamTexture'],
|
||||||
170 => 'AudioDistortionFilter',
|
[159, 'EditorSettings'],
|
||||||
171 => 'SparseTexture',
|
[160, 'InteractiveCloth'],
|
||||||
180 => 'AudioBehaviour',
|
[161, 'ClothRenderer'],
|
||||||
181 => 'AudioFilter',
|
[162, 'EditorUserSettings'],
|
||||||
182 => 'WindZone',
|
[163, 'SkinnedCloth'],
|
||||||
183 => 'Cloth',
|
[164, 'AudioReverbFilter'],
|
||||||
184 => 'SubstanceArchive',
|
[165, 'AudioHighPassFilter'],
|
||||||
185 => 'ProceduralMaterial',
|
[166, 'AudioChorusFilter'],
|
||||||
186 => 'ProceduralTexture',
|
[167, 'AudioReverbZone'],
|
||||||
191 => 'OffMeshLink',
|
[168, 'AudioEchoFilter'],
|
||||||
192 => 'OcclusionArea',
|
[169, 'AudioLowPassFilter'],
|
||||||
193 => 'Tree',
|
[170, 'AudioDistortionFilter'],
|
||||||
194 => 'NavMeshObsolete',
|
[171, 'SparseTexture'],
|
||||||
195 => 'NavMeshAgent',
|
[180, 'AudioBehaviour'],
|
||||||
196 => 'NavMeshSettings',
|
[181, 'AudioFilter'],
|
||||||
197 => 'LightProbesLegacy',
|
[182, 'WindZone'],
|
||||||
198 => 'ParticleSystem',
|
[183, 'Cloth'],
|
||||||
199 => 'ParticleSystemRenderer',
|
[184, 'SubstanceArchive'],
|
||||||
200 => 'ShaderVariantCollection',
|
[185, 'ProceduralMaterial'],
|
||||||
205 => 'LODGroup',
|
[186, 'ProceduralTexture'],
|
||||||
206 => 'BlendTree',
|
[187, 'Texture2DArray'],
|
||||||
207 => 'Motion',
|
[188, 'CubemapArray'],
|
||||||
208 => 'NavMeshObstacle',
|
[191, 'OffMeshLink'],
|
||||||
210 => 'TerrainInstance',
|
[192, 'OcclusionArea'],
|
||||||
212 => 'SpriteRenderer',
|
[193, 'Tree'],
|
||||||
213 => 'Sprite',
|
[194, 'NavMesh'],
|
||||||
214 => 'CachedSpriteAtlas',
|
[194, 'NavMeshObsolete'],
|
||||||
215 => 'ReflectionProbe',
|
[195, 'NavMeshAgent'],
|
||||||
216 => 'ReflectionProbes',
|
[196, 'NavMeshSettings'],
|
||||||
218 => 'Terrain',
|
[197, 'LightProbeCloud'],
|
||||||
220 => 'LightProbeGroup',
|
[197, 'LightProbesLegacy'],
|
||||||
221 => 'AnimatorOverrideController',
|
[198, 'ParticleSystem'],
|
||||||
222 => 'CanvasRenderer',
|
[199, 'ParticleSystemRenderer'],
|
||||||
223 => 'Canvas',
|
[200, 'ShaderVariantCollection'],
|
||||||
224 => 'RectTransform',
|
[205, 'LODGroup'],
|
||||||
225 => 'CanvasGroup',
|
[206, 'BlendTree'],
|
||||||
226 => 'BillboardAsset',
|
[207, 'Motion'],
|
||||||
227 => 'BillboardRenderer',
|
[208, 'NavMeshObstacle'],
|
||||||
228 => 'SpeedTreeWindAsset',
|
[210, 'TerrainInstance'],
|
||||||
229 => 'AnchoredJoint2D',
|
[210, 'SortingGroup'],
|
||||||
230 => 'Joint2D',
|
[212, 'SpriteRenderer'],
|
||||||
231 => 'SpringJoint2D',
|
[213, 'Sprite'],
|
||||||
232 => 'DistanceJoint2D',
|
[214, 'CachedSpriteAtlas'],
|
||||||
233 => 'HingeJoint2D',
|
[215, 'ReflectionProbe'],
|
||||||
234 => 'SliderJoint2D',
|
[216, 'ReflectionProbes'],
|
||||||
235 => 'WheelJoint2D',
|
[218, 'Terrain'],
|
||||||
238 => 'NavMeshData',
|
[220, 'LightProbeGroup'],
|
||||||
240 => 'AudioMixer',
|
[221, 'AnimatorOverrideController'],
|
||||||
241 => 'AudioMixerController',
|
[222, 'CanvasRenderer'],
|
||||||
243 => 'AudioMixerGroupController',
|
[223, 'Canvas'],
|
||||||
244 => 'AudioMixerEffectController',
|
[224, 'RectTransform'],
|
||||||
245 => 'AudioMixerSnapshotController',
|
[225, 'CanvasGroup'],
|
||||||
246 => 'PhysicsUpdateBehaviour2D',
|
[226, 'BillboardAsset'],
|
||||||
247 => 'ConstantForce2D',
|
[227, 'BillboardRenderer'],
|
||||||
248 => 'Effector2D',
|
[228, 'SpeedTreeWindAsset'],
|
||||||
249 => 'AreaEffector2D',
|
[229, 'AnchoredJoint2D'],
|
||||||
250 => 'PointEffector2D',
|
[230, 'Joint2D'],
|
||||||
251 => 'PlatformEffector2D',
|
[231, 'SpringJoint2D'],
|
||||||
252 => 'SurfaceEffector2D',
|
[232, 'DistanceJoint2D'],
|
||||||
258 => 'LightProbes',
|
[233, 'HingeJoint2D'],
|
||||||
271 => 'SampleClip',
|
[234, 'SliderJoint2D'],
|
||||||
272 => 'AudioMixerSnapshot',
|
[235, 'WheelJoint2D'],
|
||||||
273 => 'AudioMixerGroup',
|
[236, 'ClusterInputManager'],
|
||||||
290 => 'AssetBundleManifest',
|
[237, 'BaseVideoTexture'],
|
||||||
1001 => 'Prefab',
|
[238, 'NavMeshData'],
|
||||||
1002 => 'EditorExtensionImpl',
|
[240, 'AudioMixer'],
|
||||||
1003 => 'AssetImporter',
|
[241, 'AudioMixerController'],
|
||||||
1004 => 'AssetDatabase',
|
[243, 'AudioMixerGroupController'],
|
||||||
1005 => 'Mesh3DSImporter',
|
[244, 'AudioMixerEffectController'],
|
||||||
1006 => 'TextureImporter',
|
[245, 'AudioMixerSnapshotController'],
|
||||||
1007 => 'ShaderImporter',
|
[246, 'PhysicsUpdateBehaviour2D'],
|
||||||
1008 => 'ComputeShaderImporter',
|
[247, 'ConstantForce2D'],
|
||||||
1011 => 'AvatarMask',
|
[248, 'Effector2D'],
|
||||||
1020 => 'AudioImporter',
|
[249, 'AreaEffector2D'],
|
||||||
1026 => 'HierarchyState',
|
[250, 'PointEffector2D'],
|
||||||
1027 => 'GUIDSerializer',
|
[251, 'PlatformEffector2D'],
|
||||||
1028 => 'AssetMetaData',
|
[252, 'SurfaceEffector2D'],
|
||||||
1029 => 'DefaultAsset',
|
[253, 'BuoyancyEffector2D'],
|
||||||
1030 => 'DefaultImporter',
|
[254, 'RelativeJoint2D'],
|
||||||
1031 => 'TextScriptImporter',
|
[255, 'FixedJoint2D'],
|
||||||
1032 => 'SceneAsset',
|
[256, 'FrictionJoint2D'],
|
||||||
1034 => 'NativeFormatImporter',
|
[257, 'TargetJoint2D'],
|
||||||
1035 => 'MonoImporter',
|
[258, 'LightProbes'],
|
||||||
1037 => 'AssetServerCache',
|
[259, 'LightProbeProxyVolume'],
|
||||||
1038 => 'LibraryAssetImporter',
|
[271, 'SampleClip'],
|
||||||
1040 => 'ModelImporter',
|
[272, 'AudioMixerSnapshot'],
|
||||||
1041 => 'FBXImporter',
|
[273, 'AudioMixerGroup'],
|
||||||
1042 => 'TrueTypeFontImporter',
|
[280, 'NScreenBridge'],
|
||||||
1044 => 'MovieImporter',
|
[290, 'AssetBundleManifest'],
|
||||||
1045 => 'EditorBuildSettings',
|
[292, 'UnityAdsSettings'],
|
||||||
1046 => 'DDSImporter',
|
[292, 'UnityAdsManager'],
|
||||||
1048 => 'InspectorExpandedState',
|
[300, 'RuntimeInitializeOnLoadManager'],
|
||||||
1049 => 'AnnotationManager',
|
[301, 'CloudWebServicesManager'],
|
||||||
1050 => 'PluginImporter',
|
[303, 'UnityAnalyticsManager'],
|
||||||
1051 => 'EditorUserBuildSettings',
|
[304, 'CrashReportManager'],
|
||||||
1052 => 'PVRImporter',
|
[305, 'PerformanceReportingManager'],
|
||||||
1053 => 'ASTCImporter',
|
[310, 'UnityConnectSettings'],
|
||||||
1054 => 'KTXImporter',
|
[319, 'AvatarMask'],
|
||||||
1101 => 'AnimatorStateTransition',
|
[320, 'PlayableDirector'],
|
||||||
1102 => 'AnimatorState',
|
[328, 'VideoPlayer'],
|
||||||
1105 => 'HumanTemplate',
|
[329, 'VideoClip'],
|
||||||
1107 => 'AnimatorStateMachine',
|
[330, 'ParticleSystemForceField'],
|
||||||
1108 => 'PreviewAssetType',
|
[331, 'SpriteMask'],
|
||||||
1109 => 'AnimatorTransition',
|
[362, 'WorldAnchor'],
|
||||||
1110 => 'SpeedTreeImporter',
|
[363, 'OcclusionCullingData'],
|
||||||
1111 => 'AnimatorTransitionBase',
|
[1000, 'SmallestEditorClassID'],
|
||||||
1112 => 'SubstanceImporter',
|
[1001, 'Prefab'], # 1001480554
|
||||||
1113 => 'LightmapParameters',
|
[1001, 'PrefabInstance'],
|
||||||
1120 => 'LightmapSnapshot'
|
[1002, 'EditorExtensionImpl'],
|
||||||
}.freeze
|
[1003, 'AssetImporter'],
|
||||||
|
[1004, 'AssetDatabase'],
|
||||||
|
[1004, 'AssetDatabaseV1'],
|
||||||
|
[1005, 'Mesh3DSImporter'],
|
||||||
|
[1006, 'TextureImporter'],
|
||||||
|
[1007, 'ShaderImporter'],
|
||||||
|
[1008, 'ComputeShaderImporter'],
|
||||||
|
[1011, 'AvatarMask'],
|
||||||
|
[1020, 'AudioImporter'],
|
||||||
|
[1026, 'HierarchyState'],
|
||||||
|
[1027, 'GUIDSerializer'],
|
||||||
|
[1028, 'AssetMetaData'],
|
||||||
|
[1029, 'DefaultAsset'],
|
||||||
|
[1030, 'DefaultImporter'],
|
||||||
|
[1031, 'TextScriptImporter'],
|
||||||
|
[1032, 'SceneAsset'],
|
||||||
|
[1034, 'NativeFormatImporter'],
|
||||||
|
[1035, 'MonoImporter'],
|
||||||
|
[1037, 'AssetServerCache'],
|
||||||
|
[1038, 'LibraryAssetImporter'],
|
||||||
|
[1040, 'ModelImporter'],
|
||||||
|
[1041, 'FBXImporter'],
|
||||||
|
[1042, 'TrueTypeFontImporter'],
|
||||||
|
[1044, 'MovieImporter'],
|
||||||
|
[1045, 'EditorBuildSettings'],
|
||||||
|
[1046, 'DDSImporter'],
|
||||||
|
[1048, 'InspectorExpandedState'],
|
||||||
|
[1049, 'AnnotationManager'],
|
||||||
|
[1050, 'MonoAssemblyImporter'],
|
||||||
|
[1050, 'PluginImporter'],
|
||||||
|
[1051, 'EditorUserBuildSettings'],
|
||||||
|
[1052, 'PVRImporter'],
|
||||||
|
[1053, 'ASTCImporter'],
|
||||||
|
[1054, 'KTXImporter'],
|
||||||
|
[1055, 'IHVImageFormatImporter'],
|
||||||
|
[1101, 'Transition'],
|
||||||
|
[1101, 'AnimatorStateTransition'],
|
||||||
|
[1102, 'State'],
|
||||||
|
[1102, 'AnimatorState'],
|
||||||
|
[1105, 'HumanTemplate'],
|
||||||
|
[1107, 'StateMachine'],
|
||||||
|
[1107, 'AnimatorStateMachine'],
|
||||||
|
[1108, 'PreviewAssetType'],
|
||||||
|
[1108, 'PreviewAnimationClip'],
|
||||||
|
[1109, 'AnimatorTransition'],
|
||||||
|
[1110, 'SpeedTreeImporter'],
|
||||||
|
[1111, 'AnimatorTransitionBase'],
|
||||||
|
[1112, 'SubstanceImporter'],
|
||||||
|
[1113, 'LightmapParameters'],
|
||||||
|
[1120, 'LightmapSnapshot'],
|
||||||
|
[1120, 'LightingDataAsset'],
|
||||||
|
[1121, 'GISRaster'],
|
||||||
|
[1122, 'GISRasterImporter'],
|
||||||
|
[1123, 'CadImporter'],
|
||||||
|
[1124, 'SketchUpImporter'],
|
||||||
|
[1125, 'BuildReport'],
|
||||||
|
[1126, 'PackedAssets'],
|
||||||
|
[1127, 'VideoClipImporter'],
|
||||||
|
[2000, 'ActivationLogComponent'],
|
||||||
|
[100000, 'int'],
|
||||||
|
[100001, 'bool'],
|
||||||
|
[100002, 'float'],
|
||||||
|
[100003, 'MonoObject'],
|
||||||
|
[100004, 'Collision'],
|
||||||
|
[100005, 'Vector3f'],
|
||||||
|
[100006, 'RootMotionData'],
|
||||||
|
[100007, 'Collision2D'],
|
||||||
|
[100008, 'AudioMixerLiveUpdateFloat'],
|
||||||
|
[100009, 'AudioMixerLiveUpdateBool'],
|
||||||
|
[100010, 'Polygon2D'],
|
||||||
|
[100011, 'void'],
|
||||||
|
[19719996, 'TilemapCollider2D'],
|
||||||
|
[41386430, 'AssetImporterLog'],
|
||||||
|
[73398921, 'VFXRenderer'],
|
||||||
|
[76251197, 'SerializableManagedRefTestClass'],
|
||||||
|
[156049354, 'Grid'],
|
||||||
|
[181963792, 'Preset'],
|
||||||
|
[277625683, 'EmptyObject'],
|
||||||
|
[285090594, 'IConstraint'],
|
||||||
|
[293259124, 'TestObjectWithSpecialLayoutOne'],
|
||||||
|
[294290339, 'AssemblyDefinitionReferenceImporter'],
|
||||||
|
[334799969, 'SiblingDerived'],
|
||||||
|
[342846651, 'TestObjectWithSerializedMapStringNonAlignedStruct'],
|
||||||
|
[367388927, 'SubDerived'],
|
||||||
|
[369655926, 'AssetImportInProgressProxy'],
|
||||||
|
[382020655, 'PluginBuildInfo'],
|
||||||
|
[426301858, 'EditorProjectAccess'],
|
||||||
|
[468431735, 'PrefabImporter'],
|
||||||
|
[478637458, 'TestObjectWithSerializedArray'],
|
||||||
|
[478637459, 'TestObjectWithSerializedAnimationCurve'],
|
||||||
|
[483693784, 'TilemapRenderer'],
|
||||||
|
[638013454, 'SpriteAtlasDatabase'],
|
||||||
|
[641289076, 'AudioBuildInfo'],
|
||||||
|
[644342135, 'CachedSpriteAtlasRuntimeData'],
|
||||||
|
[646504946, 'RendererFake'],
|
||||||
|
[662584278, 'AssemblyDefinitionReferenceAsset'],
|
||||||
|
[668709126, 'BuiltAssetBundleInfoSet'],
|
||||||
|
[687078895, 'SpriteAtlas'],
|
||||||
|
[877146078, 'PlatformModuleSetup'],
|
||||||
|
[895512359, 'AimConstraint'],
|
||||||
|
[937362698, 'VFXManager'],
|
||||||
|
[994735392, 'VisualEffectSubgraph'],
|
||||||
|
[994735403, 'VisualEffectSubgraphOperator'],
|
||||||
|
[994735404, 'VisualEffectSubgraphBlock'],
|
||||||
|
[1001480554, 'Prefab'],
|
||||||
|
[1027052791, 'LocalizationImporter'],
|
||||||
|
[1091556383, 'Derived'],
|
||||||
|
[1111377672, 'PropertyModificationsTargetTestObject'],
|
||||||
|
[1114811875, 'ReferencesArtifactGenerator'],
|
||||||
|
[1152215463, 'AssemblyDefinitionAsset'],
|
||||||
|
[1154873562, 'SceneVisibilityState'],
|
||||||
|
[1183024399, 'LookAtConstraint'],
|
||||||
|
[1223240404, 'MultiArtifactTestImporter'],
|
||||||
|
[1268269756, 'GameObjectRecorder'],
|
||||||
|
[1325145578, 'LightingDataAssetParent'],
|
||||||
|
[1386491679, 'PresetManager'],
|
||||||
|
[1392443030, 'TestObjectWithSpecialLayoutTwo'],
|
||||||
|
[1403656975, 'StreamingManager'],
|
||||||
|
[1480428607, 'LowerResBlitTexture'],
|
||||||
|
[1542919678, 'StreamingController'],
|
||||||
|
[1571458007, 'RenderPassAttachment'],
|
||||||
|
[1628831178, 'TestObjectVectorPairStringBool'],
|
||||||
|
[1742807556, 'GridLayout'],
|
||||||
|
[1766753193, 'AssemblyDefinitionImporter'],
|
||||||
|
[1773428102, 'ParentConstraint'],
|
||||||
|
[1803986026, 'FakeComponent'],
|
||||||
|
[1818360608, 'PositionConstraint'],
|
||||||
|
[1818360609, 'RotationConstraint'],
|
||||||
|
[1818360610, 'ScaleConstraint'],
|
||||||
|
[1839735485, 'Tilemap'],
|
||||||
|
[1896753125, 'PackageManifest'],
|
||||||
|
[1896753126, 'PackageManifestImporter'],
|
||||||
|
[1953259897, 'TerrainLayer'],
|
||||||
|
[1971053207, 'SpriteShapeRenderer'],
|
||||||
|
[1977754360, 'NativeObjectType'],
|
||||||
|
[1981279845, 'TestObjectWithSerializedMapStringBool'],
|
||||||
|
[1995898324, 'SerializableManagedHost'],
|
||||||
|
[2058629509, 'VisualEffectAsset'],
|
||||||
|
[2058629510, 'VisualEffectImporter'],
|
||||||
|
[2058629511, 'VisualEffectResource'],
|
||||||
|
[2059678085, 'VisualEffectObject'],
|
||||||
|
[2083052967, 'VisualEffect'],
|
||||||
|
[2083778819, 'LocalizationAsset'],
|
||||||
|
[2089858483, 'ScriptedImporter']
|
||||||
|
]
|
||||||
|
|
||||||
|
CLASS_ID2NAME = CLASS_ID_TABLE.to_h.freeze
|
||||||
|
CLASS_ID = CLASS_ID2NAME # compatibility
|
||||||
|
CLASS_NAME2ID = CLASS_ID_TABLE.map(&:reverse).to_h.freeze
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
warn 'Warning: `mikunyan/decoders` is deprecated and will be removed at a future release.'
|
||||||
|
|
||||||
require 'mikunyan/decoders/image_decoder'
|
require 'mikunyan/decoders/image_decoder'
|
||||||
|
|
||||||
module Mikunyan
|
module Mikunyan
|
||||||
|
|||||||
@@ -9,475 +9,496 @@ require 'bin_utils'
|
|||||||
require 'mikunyan/decoders/native'
|
require 'mikunyan/decoders/native'
|
||||||
|
|
||||||
module Mikunyan
|
module Mikunyan
|
||||||
# Class for image decoding tools
|
module Decoder
|
||||||
class ImageDecoder
|
# Class for image decoding tools
|
||||||
# Decode image from Mikunyan::ObjectValue
|
class ImageDecoder
|
||||||
# @param [Mikunyan::ObjectValue] object object to decode
|
# Decode image from Mikunyan::ObjectValue
|
||||||
# @return [ChunkyPNG::Image,nil] decoded image
|
# @param [Mikunyan::ObjectValue] object object to decode
|
||||||
def self.decode_object(object)
|
# @return [ChunkyPNG::Image,nil] decoded image
|
||||||
return nil unless object.class == ObjectValue
|
def self.decode_object(object)
|
||||||
|
return nil unless object.is_a?(ObjectValue)
|
||||||
|
|
||||||
endian = object.endian
|
endian = object.endian
|
||||||
width = object['m_Width']
|
width = object['m_Width']&.value
|
||||||
height = object['m_Height']
|
height = object['m_Height']&.value
|
||||||
bin = object['image data']
|
bin = object['image data']&.value
|
||||||
fmt = object['m_TextureFormat']
|
fmt = object['m_TextureFormat']&.value
|
||||||
return nil unless width && height && bin && fmt
|
return nil unless width && height && bin && fmt
|
||||||
|
|
||||||
width = width.value
|
bin = object['m_StreamData']&.value if bin.empty?
|
||||||
height = height.value
|
|
||||||
bin = bin.value
|
|
||||||
fmt = fmt.value
|
|
||||||
|
|
||||||
if bin.empty? && object['m_StreamData']
|
|
||||||
bin = object['m_StreamData'].value
|
|
||||||
return nil unless bin
|
return nil unless bin
|
||||||
end
|
|
||||||
|
|
||||||
case fmt
|
case fmt
|
||||||
when 1
|
when 1 # Alpha8
|
||||||
decode_a8(width, height, bin)
|
decode_a8(width, height, bin)
|
||||||
when 2
|
when 2 # ARGB4444
|
||||||
decode_argb4444(width, height, bin, endian)
|
decode_argb4444(width, height, bin, endian)
|
||||||
when 3
|
when 3 # RGB24
|
||||||
decode_rgb24(width, height, bin)
|
decode_rgb24(width, height, bin)
|
||||||
when 4
|
when 4 # RGBA32
|
||||||
decode_rgba32(width, height, bin)
|
decode_rgba32(width, height, bin)
|
||||||
when 5
|
when 5 # ARGB32
|
||||||
decode_argb32(width, height, bin)
|
decode_argb32(width, height, bin)
|
||||||
when 7
|
when 7 # RGB565
|
||||||
decode_rgb565(width, height, bin, endian)
|
decode_rgb565(width, height, bin, endian)
|
||||||
when 9
|
when 9 # R16
|
||||||
decode_r16(width, height, bin)
|
decode_r16(width, height, bin)
|
||||||
when 10
|
when 10 # DXT1
|
||||||
decode_dxt1(width, height, bin)
|
decode_dxt1(width, height, bin)
|
||||||
when 12
|
when 12 # DXT5
|
||||||
decode_dxt5(width, height, bin)
|
decode_dxt5(width, height, bin)
|
||||||
when 13
|
when 13 # RGBA4444
|
||||||
decode_rgba4444(width, height, bin, endian)
|
decode_rgba4444(width, height, bin, endian)
|
||||||
when 14
|
when 14 # BGRA32
|
||||||
decode_bgra32(width, height, bin)
|
decode_bgra32(width, height, bin)
|
||||||
when 15
|
when 15 # RHalf
|
||||||
decode_rhalf(width, height, bin, endian)
|
decode_rhalf(width, height, bin, endian)
|
||||||
when 16
|
when 16 # RGHalf
|
||||||
decode_rghalf(width, height, bin, endian)
|
decode_rghalf(width, height, bin, endian)
|
||||||
when 17
|
when 17 # RGBAHalf
|
||||||
decode_rgbahalf(width, height, bin, endian)
|
decode_rgbahalf(width, height, bin, endian)
|
||||||
when 18
|
when 18 # RFloat
|
||||||
decode_rfloat(width, height, bin, endian)
|
decode_rfloat(width, height, bin, endian)
|
||||||
when 19
|
when 19 # RGFloat
|
||||||
decode_rgfloat(width, height, bin, endian)
|
decode_rgfloat(width, height, bin, endian)
|
||||||
when 20
|
when 20 # RGBAFloat
|
||||||
decode_rgbafloat(width, height, bin, endian)
|
decode_rgbafloat(width, height, bin, endian)
|
||||||
when 22
|
# when 21 # YUY2
|
||||||
decode_rgb9e5float(width, height, bin, endian)
|
when 22 # RGB9e5Float
|
||||||
when 34
|
decode_rgb9e5float(width, height, bin, endian)
|
||||||
decode_etc1(width, height, bin)
|
# when 24 # BC6H
|
||||||
when 45
|
# when 25 # BC7
|
||||||
decode_etc2rgb(width, height, bin)
|
# when 26 # BC4
|
||||||
when 46
|
# when 27 # BC5
|
||||||
decode_etc2rgba1(width, height, bin)
|
# when 28 # DXT1Crunched
|
||||||
when 47
|
# when 29 # DXT5Crunched
|
||||||
decode_etc2rgba8(width, height, bin)
|
# when 30 # PVRTC_RGB2
|
||||||
when 48, 54
|
# when 31, -127 # PVRTC_RGBA2, PVRTC_2BPP_RGBA
|
||||||
decode_astc(width, height, 4, bin)
|
# when 32 # PVRTC_RGB4
|
||||||
when 49, 55
|
# when 33 # PVRTC_RGBA4
|
||||||
decode_astc(width, height, 5, bin)
|
when 34 # ETC_RGB4
|
||||||
when 50, 56
|
decode_etc1(width, height, bin)
|
||||||
decode_astc(width, height, 6, bin)
|
# when 41 # EAC_R
|
||||||
when 51, 57
|
# when 42 # EAC_R_SIGNED
|
||||||
decode_astc(width, height, 8, bin)
|
# when 43 # EAC_RG
|
||||||
when 52, 58
|
# when 44 # EAC_RG_SIGNED
|
||||||
decode_astc(width, height, 10, bin)
|
when 45 # ETC2_RGB
|
||||||
when 53, 59
|
decode_etc2rgb(width, height, bin)
|
||||||
decode_astc(width, height, 12, bin)
|
when 46 # ETC2_RGBA1
|
||||||
when 62
|
decode_etc2rgba1(width, height, bin)
|
||||||
decode_rg16(width, height, bin)
|
when 47 # ETC2_RGBA8
|
||||||
when 63
|
decode_etc2rgba8(width, height, bin)
|
||||||
decode_r8(width, height, bin)
|
when 48, 54, 66 # ASTC_RGB_4x4, ASTC_RGBA_4x4, ASTC_HDR_4x4
|
||||||
end
|
decode_astc(width, height, 4, bin)
|
||||||
end
|
when 49, 55, 67 # ASTC_RGB_5x5, ASTC_RGBA_5x5, ASTC_HDR_5x5
|
||||||
|
decode_astc(width, height, 5, bin)
|
||||||
# Decode image from RGBA4444 binary
|
when 50, 56, 68 # ASTC_RGB_6x6, ASTC_RGBA_6x6, ASTC_HDR_6x6
|
||||||
# @param [Integer] width image width
|
decode_astc(width, height, 6, bin)
|
||||||
# @param [Integer] height image height
|
when 51, 57, 69 # ASTC_RGB_8x8, ASTC_RGBA_8x8, ASTC_HDR_8x8
|
||||||
# @param [String] bin binary to decode
|
decode_astc(width, height, 8, bin)
|
||||||
# @param [Symbol] endian endianness of binary
|
when 52, 58, 70 # ASTC_10x10, ASTC_RGBA_10x10, ASTC_HDR_10x10
|
||||||
# @return [ChunkyPNG::Image] decoded image
|
decode_astc(width, height, 10, bin)
|
||||||
def self.decode_rgba4444(width, height, bin, endian = :big)
|
when 53, 59, 71 # ASTC_RGB_12x12, ASTC_RGBA_12x12, ASTC_HDR_12x12
|
||||||
mem = String.new(capacity: width * height * 4)
|
decode_astc(width, height, 12, bin)
|
||||||
(width * height).times do |i|
|
# when 60 # ETC_RGB4_3DS
|
||||||
c = endian == :little ? BinUtils.get_int16_le(bin, i * 2) : BinUtils.get_int16_be(bin, i * 2)
|
# when 61 # ETC_RGBA8_3DS
|
||||||
c = ((c & 0xf000) << 12) | ((c & 0x0f00) << 8) | ((c & 0x00f0) << 4) | (c & 0x000f)
|
when 62 # RG16
|
||||||
BinUtils.append_int32_be!(mem, c << 4 | c)
|
decode_rg16(width, height, bin)
|
||||||
end
|
when 63 # R8
|
||||||
ChunkyPNG::Image.from_rgba_stream(width, height, mem).flip
|
decode_r8(width, height, bin)
|
||||||
end
|
# when 64 # ETC_RGB4Crunched
|
||||||
|
# when 65 # ETC2_RGBA8Crunched
|
||||||
# Decode image from ARGB4444 binary
|
|
||||||
# @param [Integer] width image width
|
|
||||||
# @param [Integer] height image height
|
|
||||||
# @param [String] bin binary to decode
|
|
||||||
# @param [Symbol] endian endianness of binary
|
|
||||||
# @return [ChunkyPNG::Image] decoded image
|
|
||||||
def self.decode_argb4444(width, height, bin, endian = :big)
|
|
||||||
mem = String.new(capacity: width * height * 4)
|
|
||||||
(width * height).times do |i|
|
|
||||||
c = endian == :little ? BinUtils.get_int16_le(bin, i * 2) : BinUtils.get_int16_be(bin, i * 2)
|
|
||||||
c = ((c & 0x0f00) << 16) | ((c & 0x00f0) << 12) | ((c & 0x000f) << 8) | ((c & 0xf000) >> 12)
|
|
||||||
BinUtils.append_int32_be!(mem, c << 4 | c)
|
|
||||||
end
|
|
||||||
ChunkyPNG::Image.from_rgba_stream(width, height, mem).flip
|
|
||||||
end
|
|
||||||
|
|
||||||
# Decode image from RGB565 binary
|
|
||||||
# @param [Integer] width image width
|
|
||||||
# @param [Integer] height image height
|
|
||||||
# @param [String] bin binary to decode
|
|
||||||
# @param [Symbol] endian endianness of binary
|
|
||||||
# @return [ChunkyPNG::Image] decoded image
|
|
||||||
def self.decode_rgb565(width, height, bin, endian = :big)
|
|
||||||
ChunkyPNG::Image.from_rgba_stream(width, height, DecodeHelper.decode_rgb565(bin, width * height, endian == :big)).flip
|
|
||||||
end
|
|
||||||
|
|
||||||
# Decode image from A8 binary
|
|
||||||
# @param [Integer] width image width
|
|
||||||
# @param [Integer] height image height
|
|
||||||
# @param [String] bin binary to decode
|
|
||||||
# @return [ChunkyPNG::Image] decoded image
|
|
||||||
def self.decode_a8(width, height, bin)
|
|
||||||
mem = String.new(capacity: width * height * 3)
|
|
||||||
(width * height).times do |i|
|
|
||||||
c = BinUtils.get_int8(bin, i)
|
|
||||||
BinUtils.append_int8!(mem, c, c, c)
|
|
||||||
end
|
|
||||||
ChunkyPNG::Image.from_rgb_stream(width, height, mem).flip
|
|
||||||
end
|
|
||||||
|
|
||||||
# Decode image from R8 binary
|
|
||||||
# @param [Integer] width image width
|
|
||||||
# @param [Integer] height image height
|
|
||||||
# @param [String] bin binary to decode
|
|
||||||
# @return [ChunkyPNG::Image] decoded image
|
|
||||||
def self.decode_r8(width, height, bin)
|
|
||||||
decode_a8(width, height, bin)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Decode image from RG16 binary
|
|
||||||
# @param [Integer] width image width
|
|
||||||
# @param [Integer] height image height
|
|
||||||
# @param [String] bin binary to decode
|
|
||||||
# @return [ChunkyPNG::Image] decoded image
|
|
||||||
def self.decode_rg16(width, height, bin)
|
|
||||||
mem = String.new(capacity: width * height * 3)
|
|
||||||
(width * height).times do |i|
|
|
||||||
BinUtils.append_int16_int8_be!(mem, BinUtils.get_int16_be(bin, i * 2), 0)
|
|
||||||
end
|
|
||||||
ChunkyPNG::Image.from_rgb_stream(width, height, mem).flip
|
|
||||||
end
|
|
||||||
|
|
||||||
# Decode image from RGB24 binary
|
|
||||||
# @param [Integer] width image width
|
|
||||||
# @param [Integer] height image height
|
|
||||||
# @param [String] bin binary to decode
|
|
||||||
# @return [ChunkyPNG::Image] decoded image
|
|
||||||
def self.decode_rgb24(width, height, bin)
|
|
||||||
ChunkyPNG::Image.from_rgb_stream(width, height, bin).flip
|
|
||||||
end
|
|
||||||
|
|
||||||
# Decode image from RGBA32 binary
|
|
||||||
# @param [Integer] width image width
|
|
||||||
# @param [Integer] height image height
|
|
||||||
# @param [String] bin binary to decode
|
|
||||||
# @return [ChunkyPNG::Image] decoded image
|
|
||||||
def self.decode_rgba32(width, height, bin)
|
|
||||||
ChunkyPNG::Image.from_rgba_stream(width, height, bin).flip
|
|
||||||
end
|
|
||||||
|
|
||||||
# Decode image from ARGB32 binary
|
|
||||||
# @param [Integer] width image width
|
|
||||||
# @param [Integer] height image height
|
|
||||||
# @param [String] bin binary to decode
|
|
||||||
# @return [ChunkyPNG::Image] decoded image
|
|
||||||
def self.decode_argb32(width, height, bin)
|
|
||||||
mem = String.new(capacity: width * height * 4)
|
|
||||||
(width * height).times do |i|
|
|
||||||
c = BinUtils.get_int32_be(bin, i * 4)
|
|
||||||
BinUtils.append_int32_be!(mem, ((c & 0x00ffffff) << 8) | ((c & 0xff000000) >> 24))
|
|
||||||
end
|
|
||||||
ChunkyPNG::Image.from_rgba_stream(width, height, mem).flip
|
|
||||||
end
|
|
||||||
|
|
||||||
# Decode image from BGRA32 binary
|
|
||||||
# @param [Integer] width image width
|
|
||||||
# @param [Integer] height image height
|
|
||||||
# @param [String] bin binary to decode
|
|
||||||
# @return [ChunkyPNG::Image] decoded image
|
|
||||||
def self.decode_bgra32(width, height, bin)
|
|
||||||
mem = String.new(capacity: width * height * 4)
|
|
||||||
(width * height).times do |i|
|
|
||||||
c = BinUtils.get_int32_le(bin, i * 4)
|
|
||||||
BinUtils.append_int32_be!(mem, ((c & 0x00ffffff) << 8) | ((c & 0xff000000) >> 24))
|
|
||||||
end
|
|
||||||
ChunkyPNG::Image.from_rgba_stream(width, height, mem).flip
|
|
||||||
end
|
|
||||||
|
|
||||||
# Decode image from R16 binary
|
|
||||||
# @param [Integer] width image width
|
|
||||||
# @param [Integer] height image height
|
|
||||||
# @param [String] bin binary to decode
|
|
||||||
# @param [Symbol] endian endianness of binary
|
|
||||||
# @return [ChunkyPNG::Image] decoded image
|
|
||||||
def self.decode_r16(width, height, bin, endian = :big)
|
|
||||||
mem = String.new(capacity: width * height * 3)
|
|
||||||
(width * height).times do |i|
|
|
||||||
c = endian == :little ? BinUtils.get_int16_le(bin, i * 2) : BinUtils.get_int16_be(bin, i * 2)
|
|
||||||
c = f2i(r / 65535.0)
|
|
||||||
BinUtils.append_int8!(mem, c, c, c)
|
|
||||||
end
|
|
||||||
ChunkyPNG::Image.from_rgb_stream(width, height, mem).flip
|
|
||||||
end
|
|
||||||
|
|
||||||
# Decode image from RGB9e5 binary
|
|
||||||
# @param [Integer] width image width
|
|
||||||
# @param [Integer] height image height
|
|
||||||
# @param [String] bin binary to decode
|
|
||||||
# @param [Symbol] endian endianness of binary
|
|
||||||
# @return [ChunkyPNG::Image] decoded image
|
|
||||||
def self.decode_rgb9e5float(width, height, bin, endian = :big)
|
|
||||||
mem = String.new(capacity: width * height * 3)
|
|
||||||
(width * height).times do |i|
|
|
||||||
n = endian == :little ? BinUtils.get_int32_le(bin, i * 4) : BinUtils.get_int32_be(bin, i * 4)
|
|
||||||
e = (n & 0xf8000000) >> 27
|
|
||||||
r = (n & 0x7fc0000) >> 9
|
|
||||||
g = (n & 0x3fe00) >> 9
|
|
||||||
b = n & 0x1ff
|
|
||||||
r = (r / 512r + 1) * (2**(e - 15))
|
|
||||||
g = (g / 512r + 1) * (2**(e - 15))
|
|
||||||
b = (b / 512r + 1) * (2**(e - 15))
|
|
||||||
BinUtils.append_int8!(mem, f2i(r), f2i(g), f2i(b))
|
|
||||||
end
|
|
||||||
ChunkyPNG::Image.from_rgb_stream(width, height, mem).flip
|
|
||||||
end
|
|
||||||
|
|
||||||
# Decode image from R Half-float binary
|
|
||||||
# @param [Integer] width image width
|
|
||||||
# @param [Integer] height image height
|
|
||||||
# @param [String] bin binary to decode
|
|
||||||
# @param [Symbol] endian endianness of binary
|
|
||||||
# @return [ChunkyPNG::Image] decoded image
|
|
||||||
def self.decode_rhalf(width, height, bin, endian = :big)
|
|
||||||
mem = String.new(capacity: width * height * 3)
|
|
||||||
(width * height).times do |i|
|
|
||||||
c = f2i(n2f(endian == :little ? BinUtils.get_int16_le(bin, i * 2) : BinUtils.get_int16_be(bin, i * 2)))
|
|
||||||
BinUtils.append_int8!(mem, c, c, c)
|
|
||||||
end
|
|
||||||
ChunkyPNG::Image.from_rgb_stream(width, height, mem).flip
|
|
||||||
end
|
|
||||||
|
|
||||||
# Decode image from RG Half-float binary
|
|
||||||
# @param [Integer] width image width
|
|
||||||
# @param [Integer] height image height
|
|
||||||
# @param [String] bin binary to decode
|
|
||||||
# @param [Symbol] endian endianness of binary
|
|
||||||
# @return [ChunkyPNG::Image] decoded image
|
|
||||||
def self.decode_rghalf(width, height, bin, endian = :big)
|
|
||||||
mem = String.new(capacity: width * height * 3)
|
|
||||||
(width * height).times do |i|
|
|
||||||
r = f2i(n2f(endian == :little ? BinUtils.get_int16_le(bin, i * 4) : BinUtils.get_int16_be(bin, i * 4)))
|
|
||||||
g = f2i(n2f(endian == :little ? BinUtils.get_int16_le(bin, i * 4 + 2) : BinUtils.get_int16_be(bin, i * 4 + 2)))
|
|
||||||
BinUtils.append_int8!(mem, r, g, 0)
|
|
||||||
end
|
|
||||||
ChunkyPNG::Image.from_rgb_stream(width, height, mem).flip
|
|
||||||
end
|
|
||||||
|
|
||||||
# Decode image from RGBA Half-float binary
|
|
||||||
# @param [Integer] width image width
|
|
||||||
# @param [Integer] height image height
|
|
||||||
# @param [String] bin binary to decode
|
|
||||||
# @param [Symbol] endian endianness of binary
|
|
||||||
# @return [ChunkyPNG::Image] decoded image
|
|
||||||
def self.decode_rgbahalf(width, height, bin, endian = :big)
|
|
||||||
mem = String.new(capacity: width * height * 4)
|
|
||||||
(width * height).times do |i|
|
|
||||||
r = f2i(n2f(endian == :little ? BinUtils.get_int16_le(bin, i * 8) : BinUtils.get_int16_be(bin, i * 8)))
|
|
||||||
g = f2i(n2f(endian == :little ? BinUtils.get_int16_le(bin, i * 8 + 2) : BinUtils.get_int16_be(bin, i * 8 + 2)))
|
|
||||||
b = f2i(n2f(endian == :little ? BinUtils.get_int16_le(bin, i * 8 + 4) : BinUtils.get_int16_be(bin, i * 8 + 4)))
|
|
||||||
a = f2i(n2f(endian == :little ? BinUtils.get_int16_le(bin, i * 8 + 6) : BinUtils.get_int16_be(bin, i * 8 + 6)))
|
|
||||||
BinUtils.append_int8!(mem, r, g, b, a)
|
|
||||||
end
|
|
||||||
ChunkyPNG::Image.from_rgba_stream(width, height, mem).flip
|
|
||||||
end
|
|
||||||
|
|
||||||
# Decode image from R float binary
|
|
||||||
# @param [Integer] width image width
|
|
||||||
# @param [Integer] height image height
|
|
||||||
# @param [String] bin binary to decode
|
|
||||||
# @param [Symbol] endian endianness of binary
|
|
||||||
# @return [ChunkyPNG::Image] decoded image
|
|
||||||
def self.decode_rfloat(width, height, bin, endian = :big)
|
|
||||||
mem = String.new(capacity: width * height * 3)
|
|
||||||
unpackstr = endian == :little ? 'e' : 'g'
|
|
||||||
(width * height).times do |i|
|
|
||||||
c = f2i(bin.byteslice(i * 4, 4).unpack1(unpackstr))
|
|
||||||
BinUtils.append_int8!(mem, c, c, c)
|
|
||||||
end
|
|
||||||
ChunkyPNG::Image.from_rgb_stream(width, height, mem).flip
|
|
||||||
end
|
|
||||||
|
|
||||||
# Decode image from RG float binary
|
|
||||||
# @param [Integer] width image width
|
|
||||||
# @param [Integer] height image height
|
|
||||||
# @param [String] bin binary to decode
|
|
||||||
# @param [Symbol] endian endianness of binary
|
|
||||||
# @return [ChunkyPNG::Image] decoded image
|
|
||||||
def self.decode_rgfloat(width, height, bin, endian = :big)
|
|
||||||
mem = String.new(capacity: width * height * 3)
|
|
||||||
unpackstr = endian == :little ? 'e2' : 'g2'
|
|
||||||
(width * height).times do |i|
|
|
||||||
r, g = bin.byteslice(i * 8, 8).unpack(unpackstr)
|
|
||||||
BinUtils.append_int8!(mem, f2i(r), f2i(g), 0)
|
|
||||||
end
|
|
||||||
ChunkyPNG::Image.from_rgb_stream(width, height, mem).flip
|
|
||||||
end
|
|
||||||
|
|
||||||
# Decode image from RGBA float binary
|
|
||||||
# @param [Integer] width image width
|
|
||||||
# @param [Integer] height image height
|
|
||||||
# @param [String] bin binary to decode
|
|
||||||
# @param [Symbol] endian endianness of binary
|
|
||||||
# @return [ChunkyPNG::Image] decoded image
|
|
||||||
def self.decode_rgbafloat(width, height, bin, endian = :big)
|
|
||||||
mem = String.new(capacity: width * height * 4)
|
|
||||||
unpackstr = endian == :little ? 'e4' : 'g4'
|
|
||||||
(width * height).times do |i|
|
|
||||||
r, g, b, a = bin.byteslice(i * 16, 16).unpack(unpackstr)
|
|
||||||
BinUtils.append_int8!(mem, f2i(r), f2i(g), f2i(b), f2i(a))
|
|
||||||
end
|
|
||||||
ChunkyPNG::Image.from_rgba_stream(width, height, mem).flip
|
|
||||||
end
|
|
||||||
|
|
||||||
# Decode image from DXT1 compressed binary
|
|
||||||
# @param [Integer] width image width
|
|
||||||
# @param [Integer] height image height
|
|
||||||
# @param [String] bin binary to decode
|
|
||||||
# @return [ChunkyPNG::Image] decoded image
|
|
||||||
def self.decode_dxt1(width, height, bin)
|
|
||||||
ChunkyPNG::Image.from_rgba_stream(width, height, DecodeHelper.decode_dxt1(bin, width, height))
|
|
||||||
end
|
|
||||||
|
|
||||||
# Decode image from DXT5 compressed binary
|
|
||||||
# @param [Integer] width image width
|
|
||||||
# @param [Integer] height image height
|
|
||||||
# @param [String] bin binary to decode
|
|
||||||
# @return [ChunkyPNG::Image] decoded image
|
|
||||||
def self.decode_dxt5(width, height, bin)
|
|
||||||
ChunkyPNG::Image.from_rgba_stream(width, height, DecodeHelper.decode_dxt5(bin, width, height))
|
|
||||||
end
|
|
||||||
|
|
||||||
# Decode image from ETC1 compressed binary
|
|
||||||
# @param [Integer] width image width
|
|
||||||
# @param [Integer] height image height
|
|
||||||
# @param [String] bin binary to decode
|
|
||||||
# @return [ChunkyPNG::Image] decoded image
|
|
||||||
def self.decode_etc1(width, height, bin)
|
|
||||||
ChunkyPNG::Image.from_rgba_stream(width, height, DecodeHelper.decode_etc1(bin, width, height))
|
|
||||||
end
|
|
||||||
|
|
||||||
# Decode image from ETC2 compressed binary
|
|
||||||
# @param [Integer] width image width
|
|
||||||
# @param [Integer] height image height
|
|
||||||
# @param [String] bin binary to decode
|
|
||||||
# @return [ChunkyPNG::Image] decoded image
|
|
||||||
def self.decode_etc2rgb(width, height, bin)
|
|
||||||
ChunkyPNG::Image.from_rgba_stream(width, height, DecodeHelper.decode_etc2(bin, width, height))
|
|
||||||
end
|
|
||||||
|
|
||||||
# Decode image from ETC2 Alpha1 compressed binary
|
|
||||||
# @param [Integer] width image width
|
|
||||||
# @param [Integer] height image height
|
|
||||||
# @param [String] bin binary to decode
|
|
||||||
# @return [ChunkyPNG::Image] decoded image
|
|
||||||
def self.decode_etc2rgba1(width, height, bin)
|
|
||||||
ChunkyPNG::Image.from_rgba_stream(width, height, DecodeHelper.decode_etc2a1(bin, width, height))
|
|
||||||
end
|
|
||||||
|
|
||||||
# Decode image from ETC2 Alpha8 compressed binary
|
|
||||||
# @param [Integer] width image width
|
|
||||||
# @param [Integer] height image height
|
|
||||||
# @param [String] bin binary to decode
|
|
||||||
# @return [ChunkyPNG::Image] decoded image
|
|
||||||
def self.decode_etc2rgba8(width, height, bin)
|
|
||||||
ChunkyPNG::Image.from_rgba_stream(width, height, DecodeHelper.decode_etc2a8(bin, width, height))
|
|
||||||
end
|
|
||||||
|
|
||||||
# Decode image from ASTC compressed binary
|
|
||||||
# @param [Integer] width image width
|
|
||||||
# @param [Integer] height image height
|
|
||||||
# @param [Integer] blocksize block size
|
|
||||||
# @param [String] bin binary to decode
|
|
||||||
# @return [ChunkyPNG::Image] decoded image
|
|
||||||
def self.decode_astc(width, height, blocksize, bin)
|
|
||||||
ChunkyPNG::Image.from_rgba_stream(width, height, DecodeHelper.decode_astc(bin, width, height, blocksize, blocksize))
|
|
||||||
end
|
|
||||||
|
|
||||||
# Create ASTC file data from ObjectValue
|
|
||||||
# @param [Mikunyan::ObjectValue,Hash] object target object
|
|
||||||
# @return [String,nil] created file
|
|
||||||
def self.create_astc_file(object)
|
|
||||||
astc_list = {
|
|
||||||
48 => 4, 49 => 5, 50 => 6, 51 => 8, 52 => 10, 53 => 12,
|
|
||||||
54 => 4, 55 => 5, 56 => 6, 57 => 8, 58 => 10, 59 => 12
|
|
||||||
}
|
|
||||||
width = object['m_Width']
|
|
||||||
height = object['m_Height']
|
|
||||||
fmt = object['m_TextureFormat']
|
|
||||||
bin = object['image data']
|
|
||||||
width = width.value if width.class == ObjectValue
|
|
||||||
height = height.value if height.class == ObjectValue
|
|
||||||
fmt = fmt.value if fmt.class == ObjectValue
|
|
||||||
bin = bin.value if bin.class == ObjectValue
|
|
||||||
if width && height && fmt && astc_list[fmt]
|
|
||||||
header = "\x13\xAB\xA1\x5C".force_encoding('ascii-8bit')
|
|
||||||
header << [astc_list[fmt], astc_list[fmt], 1].pack('C*')
|
|
||||||
header << [width].pack('V').byteslice(0, 3)
|
|
||||||
header << [height].pack('V').byteslice(0, 3)
|
|
||||||
header << "\x01\x00\x00"
|
|
||||||
header + bin
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
# convert 16bit float
|
|
||||||
def self.n2f(n)
|
|
||||||
case n
|
|
||||||
when 0x0000
|
|
||||||
0.0
|
|
||||||
when 0x8000
|
|
||||||
-0.0
|
|
||||||
when 0x7c00
|
|
||||||
Float::INFINITY
|
|
||||||
when 0xfc00
|
|
||||||
-Float::INFINITY
|
|
||||||
else
|
|
||||||
s = n & 0x8000 != 0
|
|
||||||
e = n & 0x7c00
|
|
||||||
f = n & 0x03ff
|
|
||||||
case e
|
|
||||||
when 0x7c00
|
|
||||||
Float::NAN
|
|
||||||
when 0
|
|
||||||
(s ? -f : f) * 2.0**-24
|
|
||||||
else
|
|
||||||
(s ? -1 : 1) * (f / 1024.0 + 1) * (2.0**((e >> 10) - 15))
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
# [0.0,1.0] -> [0,255]
|
# Decode image from RGBA4444 binary
|
||||||
def self.f2i(d)
|
# @param [Integer] width image width
|
||||||
(d * 255).round.clamp(0, 255)
|
# @param [Integer] height image height
|
||||||
|
# @param [String] bin binary to decode
|
||||||
|
# @param [Symbol] endian endianness of binary
|
||||||
|
# @return [ChunkyPNG::Image] decoded image
|
||||||
|
def self.decode_rgba4444(width, height, bin, endian = :big)
|
||||||
|
mem = String.new(capacity: width * height * 4)
|
||||||
|
(width * height).times do |i|
|
||||||
|
c = endian == :little ? BinUtils.get_int16_le(bin, i * 2) : BinUtils.get_int16_be(bin, i * 2)
|
||||||
|
c = ((c & 0xf000) << 12) | ((c & 0x0f00) << 8) | ((c & 0x00f0) << 4) | (c & 0x000f)
|
||||||
|
BinUtils.append_int32_be!(mem, c << 4 | c)
|
||||||
|
end
|
||||||
|
ChunkyPNG::Image.from_rgba_stream(width, height, mem).flip
|
||||||
|
end
|
||||||
|
|
||||||
|
# Decode image from ARGB4444 binary
|
||||||
|
# @param [Integer] width image width
|
||||||
|
# @param [Integer] height image height
|
||||||
|
# @param [String] bin binary to decode
|
||||||
|
# @param [Symbol] endian endianness of binary
|
||||||
|
# @return [ChunkyPNG::Image] decoded image
|
||||||
|
def self.decode_argb4444(width, height, bin, endian = :big)
|
||||||
|
mem = String.new(capacity: width * height * 4)
|
||||||
|
(width * height).times do |i|
|
||||||
|
c = endian == :little ? BinUtils.get_int16_le(bin, i * 2) : BinUtils.get_int16_be(bin, i * 2)
|
||||||
|
c = ((c & 0x0f00) << 16) | ((c & 0x00f0) << 12) | ((c & 0x000f) << 8) | ((c & 0xf000) >> 12)
|
||||||
|
BinUtils.append_int32_be!(mem, c << 4 | c)
|
||||||
|
end
|
||||||
|
ChunkyPNG::Image.from_rgba_stream(width, height, mem).flip
|
||||||
|
end
|
||||||
|
|
||||||
|
# Decode image from RGB565 binary
|
||||||
|
# @param [Integer] width image width
|
||||||
|
# @param [Integer] height image height
|
||||||
|
# @param [String] bin binary to decode
|
||||||
|
# @param [Symbol] endian endianness of binary
|
||||||
|
# @return [ChunkyPNG::Image] decoded image
|
||||||
|
def self.decode_rgb565(width, height, bin, endian = :big)
|
||||||
|
ChunkyPNG::Image.from_rgba_stream(width, height, DecodeHelper.decode_rgb565(bin, width * height, endian == :big)).flip
|
||||||
|
end
|
||||||
|
|
||||||
|
# Decode image from A8 binary
|
||||||
|
# @param [Integer] width image width
|
||||||
|
# @param [Integer] height image height
|
||||||
|
# @param [String] bin binary to decode
|
||||||
|
# @return [ChunkyPNG::Image] decoded image
|
||||||
|
def self.decode_a8(width, height, bin)
|
||||||
|
mem = String.new(capacity: width * height * 3)
|
||||||
|
(width * height).times do |i|
|
||||||
|
c = BinUtils.get_int8(bin, i)
|
||||||
|
BinUtils.append_int8!(mem, c, c, c)
|
||||||
|
end
|
||||||
|
ChunkyPNG::Image.from_rgb_stream(width, height, mem).flip
|
||||||
|
end
|
||||||
|
|
||||||
|
# Decode image from R8 binary
|
||||||
|
# @param [Integer] width image width
|
||||||
|
# @param [Integer] height image height
|
||||||
|
# @param [String] bin binary to decode
|
||||||
|
# @return [ChunkyPNG::Image] decoded image
|
||||||
|
def self.decode_r8(width, height, bin)
|
||||||
|
decode_a8(width, height, bin)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Decode image from RG16 binary
|
||||||
|
# @param [Integer] width image width
|
||||||
|
# @param [Integer] height image height
|
||||||
|
# @param [String] bin binary to decode
|
||||||
|
# @return [ChunkyPNG::Image] decoded image
|
||||||
|
def self.decode_rg16(width, height, bin)
|
||||||
|
mem = String.new(capacity: width * height * 3)
|
||||||
|
(width * height).times do |i|
|
||||||
|
BinUtils.append_int16_int8_be!(mem, BinUtils.get_int16_be(bin, i * 2), 0)
|
||||||
|
end
|
||||||
|
ChunkyPNG::Image.from_rgb_stream(width, height, mem).flip
|
||||||
|
end
|
||||||
|
|
||||||
|
# Decode image from RGB24 binary
|
||||||
|
# @param [Integer] width image width
|
||||||
|
# @param [Integer] height image height
|
||||||
|
# @param [String] bin binary to decode
|
||||||
|
# @return [ChunkyPNG::Image] decoded image
|
||||||
|
def self.decode_rgb24(width, height, bin)
|
||||||
|
ChunkyPNG::Image.from_rgb_stream(width, height, bin).flip
|
||||||
|
end
|
||||||
|
|
||||||
|
# Decode image from RGBA32 binary
|
||||||
|
# @param [Integer] width image width
|
||||||
|
# @param [Integer] height image height
|
||||||
|
# @param [String] bin binary to decode
|
||||||
|
# @return [ChunkyPNG::Image] decoded image
|
||||||
|
def self.decode_rgba32(width, height, bin)
|
||||||
|
ChunkyPNG::Image.from_rgba_stream(width, height, bin).flip
|
||||||
|
end
|
||||||
|
|
||||||
|
# Decode image from ARGB32 binary
|
||||||
|
# @param [Integer] width image width
|
||||||
|
# @param [Integer] height image height
|
||||||
|
# @param [String] bin binary to decode
|
||||||
|
# @return [ChunkyPNG::Image] decoded image
|
||||||
|
def self.decode_argb32(width, height, bin)
|
||||||
|
mem = String.new(capacity: width * height * 4)
|
||||||
|
(width * height).times do |i|
|
||||||
|
c = BinUtils.get_int32_be(bin, i * 4)
|
||||||
|
BinUtils.append_int32_be!(mem, ((c & 0x00ffffff) << 8) | ((c & 0xff000000) >> 24))
|
||||||
|
end
|
||||||
|
ChunkyPNG::Image.from_rgba_stream(width, height, mem).flip
|
||||||
|
end
|
||||||
|
|
||||||
|
# Decode image from BGRA32 binary
|
||||||
|
# @param [Integer] width image width
|
||||||
|
# @param [Integer] height image height
|
||||||
|
# @param [String] bin binary to decode
|
||||||
|
# @return [ChunkyPNG::Image] decoded image
|
||||||
|
def self.decode_bgra32(width, height, bin)
|
||||||
|
mem = String.new(capacity: width * height * 4)
|
||||||
|
(width * height).times do |i|
|
||||||
|
c = BinUtils.get_int32_le(bin, i * 4)
|
||||||
|
BinUtils.append_int32_be!(mem, ((c & 0x00ffffff) << 8) | ((c & 0xff000000) >> 24))
|
||||||
|
end
|
||||||
|
ChunkyPNG::Image.from_rgba_stream(width, height, mem).flip
|
||||||
|
end
|
||||||
|
|
||||||
|
# Decode image from R16 binary
|
||||||
|
# @param [Integer] width image width
|
||||||
|
# @param [Integer] height image height
|
||||||
|
# @param [String] bin binary to decode
|
||||||
|
# @param [Symbol] endian endianness of binary
|
||||||
|
# @return [ChunkyPNG::Image] decoded image
|
||||||
|
def self.decode_r16(width, height, bin, endian = :big)
|
||||||
|
mem = String.new(capacity: width * height * 3)
|
||||||
|
(width * height).times do |i|
|
||||||
|
c = endian == :little ? BinUtils.get_int16_le(bin, i * 2) : BinUtils.get_int16_be(bin, i * 2)
|
||||||
|
c = f2i(r / 65535.0)
|
||||||
|
BinUtils.append_int8!(mem, c, c, c)
|
||||||
|
end
|
||||||
|
ChunkyPNG::Image.from_rgb_stream(width, height, mem).flip
|
||||||
|
end
|
||||||
|
|
||||||
|
# Decode image from RGB9e5 binary
|
||||||
|
# @param [Integer] width image width
|
||||||
|
# @param [Integer] height image height
|
||||||
|
# @param [String] bin binary to decode
|
||||||
|
# @param [Symbol] endian endianness of binary
|
||||||
|
# @return [ChunkyPNG::Image] decoded image
|
||||||
|
def self.decode_rgb9e5float(width, height, bin, endian = :big)
|
||||||
|
mem = String.new(capacity: width * height * 3)
|
||||||
|
(width * height).times do |i|
|
||||||
|
n = endian == :little ? BinUtils.get_int32_le(bin, i * 4) : BinUtils.get_int32_be(bin, i * 4)
|
||||||
|
e = (n & 0xf8000000) >> 27
|
||||||
|
r = (n & 0x7fc0000) >> 9
|
||||||
|
g = (n & 0x3fe00) >> 9
|
||||||
|
b = n & 0x1ff
|
||||||
|
r = (r / 512r + 1) * (2**(e - 15))
|
||||||
|
g = (g / 512r + 1) * (2**(e - 15))
|
||||||
|
b = (b / 512r + 1) * (2**(e - 15))
|
||||||
|
BinUtils.append_int8!(mem, f2i(r), f2i(g), f2i(b))
|
||||||
|
end
|
||||||
|
ChunkyPNG::Image.from_rgb_stream(width, height, mem).flip
|
||||||
|
end
|
||||||
|
|
||||||
|
# Decode image from R Half-float binary
|
||||||
|
# @param [Integer] width image width
|
||||||
|
# @param [Integer] height image height
|
||||||
|
# @param [String] bin binary to decode
|
||||||
|
# @param [Symbol] endian endianness of binary
|
||||||
|
# @return [ChunkyPNG::Image] decoded image
|
||||||
|
def self.decode_rhalf(width, height, bin, endian = :big)
|
||||||
|
mem = String.new(capacity: width * height * 3)
|
||||||
|
(width * height).times do |i|
|
||||||
|
c = f2i(n2f(endian == :little ? BinUtils.get_int16_le(bin, i * 2) : BinUtils.get_int16_be(bin, i * 2)))
|
||||||
|
BinUtils.append_int8!(mem, c, c, c)
|
||||||
|
end
|
||||||
|
ChunkyPNG::Image.from_rgb_stream(width, height, mem).flip
|
||||||
|
end
|
||||||
|
|
||||||
|
# Decode image from RG Half-float binary
|
||||||
|
# @param [Integer] width image width
|
||||||
|
# @param [Integer] height image height
|
||||||
|
# @param [String] bin binary to decode
|
||||||
|
# @param [Symbol] endian endianness of binary
|
||||||
|
# @return [ChunkyPNG::Image] decoded image
|
||||||
|
def self.decode_rghalf(width, height, bin, endian = :big)
|
||||||
|
mem = String.new(capacity: width * height * 3)
|
||||||
|
(width * height).times do |i|
|
||||||
|
r = f2i(n2f(endian == :little ? BinUtils.get_int16_le(bin, i * 4) : BinUtils.get_int16_be(bin, i * 4)))
|
||||||
|
g = f2i(n2f(endian == :little ? BinUtils.get_int16_le(bin, i * 4 + 2) : BinUtils.get_int16_be(bin, i * 4 + 2)))
|
||||||
|
BinUtils.append_int8!(mem, r, g, 0)
|
||||||
|
end
|
||||||
|
ChunkyPNG::Image.from_rgb_stream(width, height, mem).flip
|
||||||
|
end
|
||||||
|
|
||||||
|
# Decode image from RGBA Half-float binary
|
||||||
|
# @param [Integer] width image width
|
||||||
|
# @param [Integer] height image height
|
||||||
|
# @param [String] bin binary to decode
|
||||||
|
# @param [Symbol] endian endianness of binary
|
||||||
|
# @return [ChunkyPNG::Image] decoded image
|
||||||
|
def self.decode_rgbahalf(width, height, bin, endian = :big)
|
||||||
|
mem = String.new(capacity: width * height * 4)
|
||||||
|
(width * height).times do |i|
|
||||||
|
r = f2i(n2f(endian == :little ? BinUtils.get_int16_le(bin, i * 8) : BinUtils.get_int16_be(bin, i * 8)))
|
||||||
|
g = f2i(n2f(endian == :little ? BinUtils.get_int16_le(bin, i * 8 + 2) : BinUtils.get_int16_be(bin, i * 8 + 2)))
|
||||||
|
b = f2i(n2f(endian == :little ? BinUtils.get_int16_le(bin, i * 8 + 4) : BinUtils.get_int16_be(bin, i * 8 + 4)))
|
||||||
|
a = f2i(n2f(endian == :little ? BinUtils.get_int16_le(bin, i * 8 + 6) : BinUtils.get_int16_be(bin, i * 8 + 6)))
|
||||||
|
BinUtils.append_int8!(mem, r, g, b, a)
|
||||||
|
end
|
||||||
|
ChunkyPNG::Image.from_rgba_stream(width, height, mem).flip
|
||||||
|
end
|
||||||
|
|
||||||
|
# Decode image from R float binary
|
||||||
|
# @param [Integer] width image width
|
||||||
|
# @param [Integer] height image height
|
||||||
|
# @param [String] bin binary to decode
|
||||||
|
# @param [Symbol] endian endianness of binary
|
||||||
|
# @return [ChunkyPNG::Image] decoded image
|
||||||
|
def self.decode_rfloat(width, height, bin, endian = :big)
|
||||||
|
mem = String.new(capacity: width * height * 3)
|
||||||
|
unpackstr = endian == :little ? 'e' : 'g'
|
||||||
|
(width * height).times do |i|
|
||||||
|
c = f2i(bin.byteslice(i * 4, 4).unpack1(unpackstr))
|
||||||
|
BinUtils.append_int8!(mem, c, c, c)
|
||||||
|
end
|
||||||
|
ChunkyPNG::Image.from_rgb_stream(width, height, mem).flip
|
||||||
|
end
|
||||||
|
|
||||||
|
# Decode image from RG float binary
|
||||||
|
# @param [Integer] width image width
|
||||||
|
# @param [Integer] height image height
|
||||||
|
# @param [String] bin binary to decode
|
||||||
|
# @param [Symbol] endian endianness of binary
|
||||||
|
# @return [ChunkyPNG::Image] decoded image
|
||||||
|
def self.decode_rgfloat(width, height, bin, endian = :big)
|
||||||
|
mem = String.new(capacity: width * height * 3)
|
||||||
|
unpackstr = endian == :little ? 'e2' : 'g2'
|
||||||
|
(width * height).times do |i|
|
||||||
|
r, g = bin.byteslice(i * 8, 8).unpack(unpackstr)
|
||||||
|
BinUtils.append_int8!(mem, f2i(r), f2i(g), 0)
|
||||||
|
end
|
||||||
|
ChunkyPNG::Image.from_rgb_stream(width, height, mem).flip
|
||||||
|
end
|
||||||
|
|
||||||
|
# Decode image from RGBA float binary
|
||||||
|
# @param [Integer] width image width
|
||||||
|
# @param [Integer] height image height
|
||||||
|
# @param [String] bin binary to decode
|
||||||
|
# @param [Symbol] endian endianness of binary
|
||||||
|
# @return [ChunkyPNG::Image] decoded image
|
||||||
|
def self.decode_rgbafloat(width, height, bin, endian = :big)
|
||||||
|
mem = String.new(capacity: width * height * 4)
|
||||||
|
unpackstr = endian == :little ? 'e4' : 'g4'
|
||||||
|
(width * height).times do |i|
|
||||||
|
r, g, b, a = bin.byteslice(i * 16, 16).unpack(unpackstr)
|
||||||
|
BinUtils.append_int8!(mem, f2i(r), f2i(g), f2i(b), f2i(a))
|
||||||
|
end
|
||||||
|
ChunkyPNG::Image.from_rgba_stream(width, height, mem).flip
|
||||||
|
end
|
||||||
|
|
||||||
|
# Decode image from DXT1 compressed binary
|
||||||
|
# @param [Integer] width image width
|
||||||
|
# @param [Integer] height image height
|
||||||
|
# @param [String] bin binary to decode
|
||||||
|
# @return [ChunkyPNG::Image] decoded image
|
||||||
|
def self.decode_dxt1(width, height, bin)
|
||||||
|
ChunkyPNG::Image.from_rgba_stream(width, height, DecodeHelper.decode_dxt1(bin, width, height))
|
||||||
|
end
|
||||||
|
|
||||||
|
# Decode image from DXT5 compressed binary
|
||||||
|
# @param [Integer] width image width
|
||||||
|
# @param [Integer] height image height
|
||||||
|
# @param [String] bin binary to decode
|
||||||
|
# @return [ChunkyPNG::Image] decoded image
|
||||||
|
def self.decode_dxt5(width, height, bin)
|
||||||
|
ChunkyPNG::Image.from_rgba_stream(width, height, DecodeHelper.decode_dxt5(bin, width, height))
|
||||||
|
end
|
||||||
|
|
||||||
|
# Decode image from ETC1 compressed binary
|
||||||
|
# @param [Integer] width image width
|
||||||
|
# @param [Integer] height image height
|
||||||
|
# @param [String] bin binary to decode
|
||||||
|
# @return [ChunkyPNG::Image] decoded image
|
||||||
|
def self.decode_etc1(width, height, bin)
|
||||||
|
ChunkyPNG::Image.from_rgba_stream(width, height, DecodeHelper.decode_etc1(bin, width, height))
|
||||||
|
end
|
||||||
|
|
||||||
|
# Decode image from ETC2 compressed binary
|
||||||
|
# @param [Integer] width image width
|
||||||
|
# @param [Integer] height image height
|
||||||
|
# @param [String] bin binary to decode
|
||||||
|
# @return [ChunkyPNG::Image] decoded image
|
||||||
|
def self.decode_etc2rgb(width, height, bin)
|
||||||
|
ChunkyPNG::Image.from_rgba_stream(width, height, DecodeHelper.decode_etc2(bin, width, height))
|
||||||
|
end
|
||||||
|
|
||||||
|
# Decode image from ETC2 Alpha1 compressed binary
|
||||||
|
# @param [Integer] width image width
|
||||||
|
# @param [Integer] height image height
|
||||||
|
# @param [String] bin binary to decode
|
||||||
|
# @return [ChunkyPNG::Image] decoded image
|
||||||
|
def self.decode_etc2rgba1(width, height, bin)
|
||||||
|
ChunkyPNG::Image.from_rgba_stream(width, height, DecodeHelper.decode_etc2a1(bin, width, height))
|
||||||
|
end
|
||||||
|
|
||||||
|
# Decode image from ETC2 Alpha8 compressed binary
|
||||||
|
# @param [Integer] width image width
|
||||||
|
# @param [Integer] height image height
|
||||||
|
# @param [String] bin binary to decode
|
||||||
|
# @return [ChunkyPNG::Image] decoded image
|
||||||
|
def self.decode_etc2rgba8(width, height, bin)
|
||||||
|
ChunkyPNG::Image.from_rgba_stream(width, height, DecodeHelper.decode_etc2a8(bin, width, height))
|
||||||
|
end
|
||||||
|
|
||||||
|
# Decode image from ASTC compressed binary
|
||||||
|
# @param [Integer] width image width
|
||||||
|
# @param [Integer] height image height
|
||||||
|
# @param [Integer] blocksize block size
|
||||||
|
# @param [String] bin binary to decode
|
||||||
|
# @return [ChunkyPNG::Image] decoded image
|
||||||
|
def self.decode_astc(width, height, blocksize, bin)
|
||||||
|
ChunkyPNG::Image.from_rgba_stream(width, height, DecodeHelper.decode_astc(bin, width, height, blocksize, blocksize))
|
||||||
|
end
|
||||||
|
|
||||||
|
# Create ASTC file data from ObjectValue
|
||||||
|
# @param [Mikunyan::ObjectValue,Hash] object target object
|
||||||
|
# @return [String,nil] created file
|
||||||
|
def self.create_astc_file(object)
|
||||||
|
astc_list = {
|
||||||
|
48 => 4, 49 => 5, 50 => 6, 51 => 8, 52 => 10, 53 => 12,
|
||||||
|
54 => 4, 55 => 5, 56 => 6, 57 => 8, 58 => 10, 59 => 12
|
||||||
|
}
|
||||||
|
width = object['m_Width']
|
||||||
|
height = object['m_Height']
|
||||||
|
fmt = object['m_TextureFormat']
|
||||||
|
bin = object['image data']
|
||||||
|
width = width.value if width.class == ObjectValue
|
||||||
|
height = height.value if height.class == ObjectValue
|
||||||
|
fmt = fmt.value if fmt.class == ObjectValue
|
||||||
|
bin = bin.value if bin.class == ObjectValue
|
||||||
|
if width && height && fmt && astc_list[fmt]
|
||||||
|
header = "\x13\xAB\xA1\x5C".force_encoding('ascii-8bit')
|
||||||
|
header << [astc_list[fmt], astc_list[fmt], 1].pack('C*')
|
||||||
|
header << [width].pack('V').byteslice(0, 3)
|
||||||
|
header << [height].pack('V').byteslice(0, 3)
|
||||||
|
header << "\x01\x00\x00"
|
||||||
|
header + bin
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# convert 16bit float
|
||||||
|
def self.n2f(n)
|
||||||
|
case n
|
||||||
|
when 0x0000
|
||||||
|
0.0
|
||||||
|
when 0x8000
|
||||||
|
-0.0
|
||||||
|
when 0x7c00
|
||||||
|
Float::INFINITY
|
||||||
|
when 0xfc00
|
||||||
|
-Float::INFINITY
|
||||||
|
else
|
||||||
|
s = n & 0x8000 != 0
|
||||||
|
e = n & 0x7c00
|
||||||
|
f = n & 0x03ff
|
||||||
|
case e
|
||||||
|
when 0x7c00
|
||||||
|
Float::NAN
|
||||||
|
when 0
|
||||||
|
(s ? -f : f) * 2.0**-24
|
||||||
|
else
|
||||||
|
(s ? -1 : 1) * (f / 1024.0 + 1) * (2.0**((e >> 10) - 15))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# [0.0,1.0] -> [0,255]
|
||||||
|
def self.f2i(d)
|
||||||
|
(d * 255).round.clamp(0, 255)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class ImageDecoder
|
||||||
|
def self.decode_object(object)
|
||||||
|
warn 'Warning: Mikunyan::ImageDecoder.decode_object is deprecated and will be removed at a future release. ' \
|
||||||
|
'Use Mikunyan::Decoder::ImageDecoder.decode_object or' \
|
||||||
|
'Mikunyan::CustomTypes::Texture2D::generate_png instead.'
|
||||||
|
Mikunyan::Decoder::ImageDecoder.decode_object(object)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -4,11 +4,12 @@ module Mikunyan
|
|||||||
# Class for representing decoded object
|
# Class for representing decoded object
|
||||||
# @attr [String] name object name
|
# @attr [String] name object name
|
||||||
# @attr [String] type object type name
|
# @attr [String] type object type name
|
||||||
|
# @attr [Hash<String,Mikunyan::ObjectValue>] attr
|
||||||
# @attr [Object] value object
|
# @attr [Object] value object
|
||||||
# @attr [Symbol] endian endianness
|
# @attr [Symbol] endian endianness
|
||||||
# @attr [Boolean] is_struct
|
# @attr [Boolean] is_struct
|
||||||
class ObjectValue
|
class ObjectValue
|
||||||
attr_accessor :name, :type, :value, :endian, :is_struct
|
attr_accessor :name, :type, :attr, :value, :endian, :is_struct
|
||||||
|
|
||||||
# Constructor
|
# Constructor
|
||||||
# @param [String] name object name
|
# @param [String] name object name
|
||||||
@@ -27,13 +28,13 @@ module Mikunyan
|
|||||||
# Return whether object is array or not
|
# Return whether object is array or not
|
||||||
# @return [Boolean]
|
# @return [Boolean]
|
||||||
def array?
|
def array?
|
||||||
value && value.class == Array
|
value&.is_a?(Array)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Return whether object is value or not
|
# Return whether object is value or not
|
||||||
# @return [Boolean]
|
# @return [Boolean]
|
||||||
def value?
|
def value?
|
||||||
value && value.class != Array
|
value && !value.is_a?(Array)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Return whether object is struct or not
|
# Return whether object is struct or not
|
||||||
@@ -55,20 +56,16 @@ module Mikunyan
|
|||||||
@attr.key?(key)
|
@attr.key?(key)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Return value
|
|
||||||
# @return [Object] value
|
|
||||||
def []
|
|
||||||
@value
|
|
||||||
end
|
|
||||||
|
|
||||||
# Return value of selected index or key
|
# Return value of selected index or key
|
||||||
# @param [Integer,String] i index or key
|
# @param [Integer,String] key index or key
|
||||||
# @return [Object] value
|
# @return [Object] value
|
||||||
def [](i)
|
def [](key = nil)
|
||||||
if array? && i.class == Integer
|
if key.nil?
|
||||||
@value[i]
|
@value
|
||||||
|
elsif array? && key.is_a?(Integer)
|
||||||
|
@value[key]
|
||||||
else
|
else
|
||||||
@attr[i]
|
@attr[key]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -83,13 +80,31 @@ module Mikunyan
|
|||||||
# Return value of called key
|
# Return value of called key
|
||||||
# @param [String] name key
|
# @param [String] name key
|
||||||
# @return [Object] value
|
# @return [Object] value
|
||||||
def method_missing(name, *_args)
|
def method_missing(name, *args)
|
||||||
@attr[name.to_s]
|
n = name.to_s
|
||||||
|
@attr.key?(n) ? @attr[n] : super
|
||||||
end
|
end
|
||||||
|
|
||||||
# Implementation of respond_to_missing?
|
# Implementation of respond_to_missing?
|
||||||
def respond_to_missing?(symbol, _include_private)
|
def respond_to_missing?(symbol, _include_private)
|
||||||
@attr.key?(symbol.to_s)
|
@attr.key?(symbol.to_s)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Simplifies self, or serializes self with ruby primitive types
|
||||||
|
def simplify
|
||||||
|
if @type == 'pair'
|
||||||
|
[@attr['first'].simplify, @attr['second'].simplify]
|
||||||
|
elsif @type == 'map' && @value.is_a?(Array)
|
||||||
|
@value.map{|e| [e['first'].simplify, e['second'].simplify]}.to_h
|
||||||
|
elsif is_struct
|
||||||
|
@attr.map{|key, val| [key, val.simplify]}.to_h
|
||||||
|
elsif @value.is_a?(Array)
|
||||||
|
@value.map{|e| e.is_a?(ObjectValue) ? e.simplify : e}
|
||||||
|
elsif @value.is_a?(ObjectValue)
|
||||||
|
@value.simplify
|
||||||
|
else
|
||||||
|
@value
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
+121
-54
@@ -1,5 +1,8 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'json'
|
||||||
|
require 'mikunyan/binary_reader'
|
||||||
|
|
||||||
module Mikunyan
|
module Mikunyan
|
||||||
# Class for representing TypeTree
|
# Class for representing TypeTree
|
||||||
# @attr [Array<Mikunyan::TypeTree::Node>] nodes list of all nodes
|
# @attr [Array<Mikunyan::TypeTree::Node>] nodes list of all nodes
|
||||||
@@ -8,77 +11,141 @@ module Mikunyan
|
|||||||
|
|
||||||
# Struct for representing Node in TypeTree
|
# Struct for representing Node in TypeTree
|
||||||
# @attr [String] version version string
|
# @attr [String] version version string
|
||||||
# @attr [Integer] depth depth of node (>= 0)
|
# @attr [Integer] level level of node (>= 0)
|
||||||
# @attr [Boolean] array? array node or not
|
# @attr [Boolean] array? array node or not
|
||||||
# @attr [String] type type name
|
# @attr [String] type type name
|
||||||
# @attr [String] name node (attribute) name
|
# @attr [String] name node (attribute) name
|
||||||
# @attr [Integer] index index in node list
|
# @attr [Integer] index index in node list
|
||||||
# @attr [Integer] flags flags of node
|
# @attr [Integer] flags flags of node
|
||||||
Node = Struct.new(:version, :depth, :array?, :type, :name, :size, :index, :flags)
|
# @attr [Integer,nil] v18meta
|
||||||
|
# @attr [Mikunyan::TypeTree::Node,nil] parent ̑
|
||||||
# Create TypeTree from binary string (new version)
|
# @attr [Array<Mikunyan::TypeTree::Node>] children
|
||||||
# @param [Mikunyan::BinaryReader] br
|
Node = Struct.new(:version, :level, :array?, :type, :name, :size, :index, :flags, :v18meta, :parent, :children, keyword_init: true) do
|
||||||
# @return [Mikunyan::TypeTree] created TypeTree
|
def need_align?
|
||||||
def self.load(br)
|
flags & 0x4000 != 0
|
||||||
nodes = []
|
|
||||||
node_count = br.i32u
|
|
||||||
buffer_size = br.i32u
|
|
||||||
node_count.times do
|
|
||||||
node = Node.new(br.i16u, br.i8u, br.i8u != 0, br.i32, br.i32, br.i32, br.i32u, br.i32u)
|
|
||||||
nodes << node
|
|
||||||
end
|
end
|
||||||
buffer = br.read(buffer_size)
|
|
||||||
nodes.each do |n|
|
|
||||||
n.type = if n.type >= 0
|
|
||||||
buffer.unpack1("@#{n.type}Z*")
|
|
||||||
else
|
|
||||||
Mikunyan::STRING_TABLE[n.type + 2**31]
|
|
||||||
end
|
|
||||||
n.name = if n.name >= 0
|
|
||||||
buffer.unpack1("@#{n.name}Z*")
|
|
||||||
else
|
|
||||||
Mikunyan::STRING_TABLE[n.name + 2**31]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
r = TypeTree.new
|
|
||||||
r.nodes = nodes
|
|
||||||
r
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Create TypeTree from binary string (legacy version)
|
# Returns the root node of the typetree
|
||||||
|
# @return [Mikunyan::TypeTree::Node,nil]
|
||||||
|
def tree
|
||||||
|
nodes&.[](0)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Generates JSON-compatible serialized representation of typetree information
|
||||||
|
def serialize
|
||||||
|
{
|
||||||
|
'nodes' =>
|
||||||
|
nodes.map do |e|
|
||||||
|
{
|
||||||
|
'version' => e.version,
|
||||||
|
'level' => e.level,
|
||||||
|
'is_array' => e.array?,
|
||||||
|
'type' => e.type,
|
||||||
|
'name' => e.name,
|
||||||
|
'size' => e.size,
|
||||||
|
'flags' => e.flags,
|
||||||
|
'v18meta' => e.v18meta
|
||||||
|
}
|
||||||
|
end
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
# Creates TypeTree from binary string
|
||||||
# @param [Mikunyan::BinaryReader] br
|
# @param [Mikunyan::BinaryReader] br
|
||||||
|
# @param [Integer] version asset format version
|
||||||
# @return [Mikunyan::TypeTree] created TypeTree
|
# @return [Mikunyan::TypeTree] created TypeTree
|
||||||
def self.load_legacy(br)
|
def self.load(br, version)
|
||||||
nodes = []
|
if version == 10 || version >= 12
|
||||||
stack = [0]
|
node_count = br.i32u
|
||||||
until stack.empty?
|
buffer_size = br.i32u
|
||||||
depth = stack.pop
|
nodes = Array.new(node_count) do
|
||||||
type = br.cstr
|
Node.new(
|
||||||
name = br.cstr
|
version: br.i16u,
|
||||||
size = br.i32
|
level: br.i8u,
|
||||||
index = br.i32u
|
array?: br.bool,
|
||||||
is_array = (br.i32 != 0)
|
type: br.i32u,
|
||||||
version = br.i32u
|
name: br.i32u,
|
||||||
flags = br.i32u
|
size: br.i32s,
|
||||||
child_count = br.i32u
|
index: br.i32u,
|
||||||
child_count.times{stack << depth + 1}
|
flags: br.i32u,
|
||||||
nodes << Node.new(version, depth, is_array, type, name, size, index, flags)
|
v18meta: version >= 18 ? br.i64u : nil,
|
||||||
|
children: []
|
||||||
|
)
|
||||||
|
end
|
||||||
|
buffer = br.read(buffer_size)
|
||||||
|
stack = []
|
||||||
|
nodes.each do |n|
|
||||||
|
n.type = Mikunyan::Constants.get_string_or_default(n.type, buffer)
|
||||||
|
n.name = Mikunyan::Constants.get_string_or_default(n.name, buffer)
|
||||||
|
if n.level > 0
|
||||||
|
n.parent = stack[n.level - 1]
|
||||||
|
n.parent.children << n
|
||||||
|
end
|
||||||
|
stack[n.level] = n
|
||||||
|
end
|
||||||
|
else
|
||||||
|
nodes = []
|
||||||
|
stack = []
|
||||||
|
until stack.empty? && !nodes.empty?
|
||||||
|
parent = stack.pop
|
||||||
|
node = Node.new(
|
||||||
|
type: br.cstr,
|
||||||
|
name: br.cstr,
|
||||||
|
size: br.i32s,
|
||||||
|
index: br.i32u,
|
||||||
|
array?: br.i32 != 0,
|
||||||
|
version: br.i32u,
|
||||||
|
flags: br.i32u,
|
||||||
|
level: parent ? parent.level + 1 : 0,
|
||||||
|
parent: parent,
|
||||||
|
children: []
|
||||||
|
)
|
||||||
|
nodes << node
|
||||||
|
parent.children << node if parent
|
||||||
|
stack += Array.new(br.i32u, node)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
r = TypeTree.new
|
ret = TypeTree.new
|
||||||
r.nodes = nodes
|
ret.nodes = nodes
|
||||||
r
|
ret
|
||||||
end
|
end
|
||||||
|
|
||||||
# Create default TypeTree from hash string (if exists)
|
# Create default TypeTree from hash string (if exists)
|
||||||
|
# @param [Integer] class_id
|
||||||
# @param [String] hash
|
# @param [String] hash
|
||||||
# @return [Mikunyan::TypeTree,nil] created TypeTree
|
# @return [Mikunyan::TypeTree,nil] created TypeTree
|
||||||
def self.load_default(hash)
|
def self.load_default(class_id, hash)
|
||||||
hash_str = hash.unpack1('H*')
|
file = File.expand_path("../typetrees/#{class_id}/#{hash.unpack1('H*')}.json", __FILE__)
|
||||||
file = File.expand_path("../typetrees/#{hash_str}.dat", __FILE__)
|
|
||||||
return nil unless File.file?(file)
|
return nil unless File.file?(file)
|
||||||
r = TypeTree.new
|
TypeTree.deserialize(JSON.parse(File.read(file)))
|
||||||
r.nodes = Marshal.load(File.binread(file))
|
end
|
||||||
r
|
|
||||||
|
# Creates TypeTree from serialized object
|
||||||
|
# @param [Hash] obj
|
||||||
|
def self.deserialize(obj)
|
||||||
|
stack = []
|
||||||
|
ret = TypeTree.new
|
||||||
|
ret.nodes = obj['nodes'].map.with_index do |e, index|
|
||||||
|
level = e['level'] || e['depth']
|
||||||
|
parent = level > 0 ? stack[level - 1] : nil
|
||||||
|
n = Node.new(
|
||||||
|
version: e['version'],
|
||||||
|
level: level,
|
||||||
|
array?: e['is_array'],
|
||||||
|
type: e['type'],
|
||||||
|
name: e['name'],
|
||||||
|
size: e['size'],
|
||||||
|
index: index,
|
||||||
|
flags: e['flags'],
|
||||||
|
v18meta: e['v18meta'],
|
||||||
|
parent: parent,
|
||||||
|
children: []
|
||||||
|
)
|
||||||
|
parent.children << n if parent
|
||||||
|
stack[level] = n
|
||||||
|
end
|
||||||
|
ret
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'mikunyan/base_object'
|
||||||
|
|
||||||
|
module Mikunyan
|
||||||
|
module CustomTypes
|
||||||
|
class TextAsset < Mikunyan::BaseObject
|
||||||
|
Mikunyan::CustomTypes.set_custom_type(self, 'TextAsset')
|
||||||
|
|
||||||
|
def text
|
||||||
|
@attr['m_Script']&.value
|
||||||
|
end
|
||||||
|
|
||||||
|
def bytes
|
||||||
|
@attr['m_Script']&.value.dup.force_encoding('ASCII-8BIT')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'mikunyan/base_object'
|
||||||
|
require 'mikunyan/decoders/image_decoder'
|
||||||
|
|
||||||
|
module Mikunyan
|
||||||
|
module CustomTypes
|
||||||
|
class Texture2D < Mikunyan::BaseObject
|
||||||
|
Mikunyan::CustomTypes.set_custom_type(self, 'Texture2D')
|
||||||
|
|
||||||
|
def generate_png
|
||||||
|
Mikunyan::Decoder::ImageDecoder.decode_object(self)
|
||||||
|
end
|
||||||
|
|
||||||
|
def width
|
||||||
|
@attr['m_Width']&.value
|
||||||
|
end
|
||||||
|
|
||||||
|
def height
|
||||||
|
@attr['m_Height']&.value
|
||||||
|
end
|
||||||
|
|
||||||
|
def texture_format
|
||||||
|
@attr['m_TextureFormat']&.value
|
||||||
|
end
|
||||||
|
|
||||||
|
def mipmap_count
|
||||||
|
@attr['m_MipCount']&.value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1 @@
|
|||||||
|
{"nodes":[{"version":5,"level":0,"is_array":false,"type":"GameObject","name":"Base","size":-1,"flags":32768,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"vector","name":"m_Component","size":-1,"flags":65,"v18meta":null},{"version":1,"level":2,"is_array":true,"type":"Array","name":"Array","size":-1,"flags":65,"v18meta":null},{"version":1,"level":3,"is_array":false,"type":"int","name":"size","size":4,"flags":65,"v18meta":null},{"version":1,"level":3,"is_array":false,"type":"ComponentPair","name":"data","size":12,"flags":65,"v18meta":null},{"version":1,"level":4,"is_array":false,"type":"PPtr<Component>","name":"component","size":12,"flags":65,"v18meta":null},{"version":1,"level":5,"is_array":false,"type":"int","name":"m_FileID","size":4,"flags":65,"v18meta":null},{"version":1,"level":5,"is_array":false,"type":"SInt64","name":"m_PathID","size":8,"flags":65,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"unsigned int","name":"m_Layer","size":4,"flags":0,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"string","name":"m_Name","size":-1,"flags":32768,"v18meta":null},{"version":1,"level":2,"is_array":true,"type":"Array","name":"Array","size":-1,"flags":16385,"v18meta":null},{"version":1,"level":3,"is_array":false,"type":"int","name":"size","size":4,"flags":1,"v18meta":null},{"version":1,"level":3,"is_array":false,"type":"char","name":"data","size":1,"flags":1,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"UInt16","name":"m_Tag","size":2,"flags":0,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"bool","name":"m_IsActive","size":1,"flags":0,"v18meta":null}]}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{"nodes":[{"version":6,"level":0,"is_array":false,"type":"GameObject","name":"Base","size":-1,"flags":32768,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"vector","name":"m_Component","size":-1,"flags":32833,"v18meta":null},{"version":1,"level":2,"is_array":true,"type":"Array","name":"Array","size":-1,"flags":16449,"v18meta":null},{"version":1,"level":3,"is_array":false,"type":"int","name":"size","size":4,"flags":65,"v18meta":null},{"version":1,"level":3,"is_array":false,"type":"ComponentPair","name":"data","size":12,"flags":65,"v18meta":null},{"version":1,"level":4,"is_array":false,"type":"PPtr<Component>","name":"component","size":12,"flags":65,"v18meta":null},{"version":1,"level":5,"is_array":false,"type":"int","name":"m_FileID","size":4,"flags":65,"v18meta":null},{"version":1,"level":5,"is_array":false,"type":"SInt64","name":"m_PathID","size":8,"flags":65,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"unsigned int","name":"m_Layer","size":4,"flags":0,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"string","name":"m_Name","size":-1,"flags":32768,"v18meta":null},{"version":1,"level":2,"is_array":true,"type":"Array","name":"Array","size":-1,"flags":16385,"v18meta":null},{"version":1,"level":3,"is_array":false,"type":"int","name":"size","size":4,"flags":1,"v18meta":null},{"version":1,"level":3,"is_array":false,"type":"char","name":"data","size":1,"flags":1,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"UInt16","name":"m_Tag","size":2,"flags":0,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"bool","name":"m_IsActive","size":1,"flags":0,"v18meta":null}]}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{"nodes":[{"version":5,"level":0,"is_array":false,"type":"GameObject","name":"Base","size":-1,"flags":32768,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"vector","name":"m_Component","size":-1,"flags":32833,"v18meta":null},{"version":1,"level":2,"is_array":true,"type":"Array","name":"Array","size":-1,"flags":16449,"v18meta":null},{"version":1,"level":3,"is_array":false,"type":"int","name":"size","size":4,"flags":65,"v18meta":null},{"version":1,"level":3,"is_array":false,"type":"ComponentPair","name":"data","size":12,"flags":65,"v18meta":null},{"version":1,"level":4,"is_array":false,"type":"PPtr<Component>","name":"component","size":12,"flags":65,"v18meta":null},{"version":1,"level":5,"is_array":false,"type":"int","name":"m_FileID","size":4,"flags":65,"v18meta":null},{"version":1,"level":5,"is_array":false,"type":"SInt64","name":"m_PathID","size":8,"flags":65,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"unsigned int","name":"m_Layer","size":4,"flags":0,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"string","name":"m_Name","size":-1,"flags":32768,"v18meta":null},{"version":1,"level":2,"is_array":true,"type":"Array","name":"Array","size":-1,"flags":16385,"v18meta":null},{"version":1,"level":3,"is_array":false,"type":"int","name":"size","size":4,"flags":1,"v18meta":null},{"version":1,"level":3,"is_array":false,"type":"char","name":"data","size":1,"flags":1,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"UInt16","name":"m_Tag","size":2,"flags":0,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"bool","name":"m_IsActive","size":1,"flags":0,"v18meta":null}]}
|
||||||
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
@@ -0,0 +1 @@
|
|||||||
|
{"nodes":[{"version":1,"level":0,"is_array":false,"type":"TextAsset","name":"Base","size":-1,"flags":32768,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"string","name":"m_Name","size":-1,"flags":32769,"v18meta":null},{"version":1,"level":2,"is_array":true,"type":"Array","name":"Array","size":-1,"flags":16385,"v18meta":null},{"version":1,"level":3,"is_array":false,"type":"int","name":"size","size":4,"flags":1,"v18meta":null},{"version":1,"level":3,"is_array":false,"type":"char","name":"data","size":1,"flags":1,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"string","name":"m_Script","size":-1,"flags":67141633,"v18meta":null},{"version":1,"level":2,"is_array":true,"type":"Array","name":"Array","size":-1,"flags":67125249,"v18meta":null},{"version":1,"level":3,"is_array":false,"type":"int","name":"size","size":4,"flags":67108865,"v18meta":null},{"version":1,"level":3,"is_array":false,"type":"char","name":"data","size":1,"flags":67108865,"v18meta":null}]}
|
||||||
Binary file not shown.
@@ -0,0 +1 @@
|
|||||||
|
{"nodes":[{"version":3,"level":0,"is_array":false,"type":"Animation","name":"Base","size":-1,"flags":32768,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"PPtr<GameObject>","name":"m_GameObject","size":12,"flags":65,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"int","name":"m_FileID","size":4,"flags":65,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"SInt64","name":"m_PathID","size":8,"flags":65,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"UInt8","name":"m_Enabled","size":1,"flags":16641,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"PPtr<AnimationClip>","name":"m_Animation","size":12,"flags":0,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"int","name":"m_FileID","size":4,"flags":8388609,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"SInt64","name":"m_PathID","size":8,"flags":8388609,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"vector","name":"m_Animations","size":-1,"flags":32768,"v18meta":null},{"version":1,"level":2,"is_array":true,"type":"Array","name":"Array","size":-1,"flags":16384,"v18meta":null},{"version":1,"level":3,"is_array":false,"type":"int","name":"size","size":4,"flags":0,"v18meta":null},{"version":1,"level":3,"is_array":false,"type":"PPtr<AnimationClip>","name":"data","size":12,"flags":0,"v18meta":null},{"version":1,"level":4,"is_array":false,"type":"int","name":"m_FileID","size":4,"flags":8388609,"v18meta":null},{"version":1,"level":4,"is_array":false,"type":"SInt64","name":"m_PathID","size":8,"flags":8388609,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"int","name":"m_WrapMode","size":4,"flags":0,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"bool","name":"m_PlayAutomatically","size":1,"flags":0,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"bool","name":"m_AnimatePhysics","size":1,"flags":16384,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"int","name":"m_CullingType","size":4,"flags":0,"v18meta":null}]}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{"nodes":[{"version":3,"level":0,"is_array":false,"type":"Animation","name":"Base","size":-1,"flags":32768,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"PPtr<GameObject>","name":"m_GameObject","size":12,"flags":65,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"int","name":"m_FileID","size":4,"flags":65,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"SInt64","name":"m_PathID","size":8,"flags":65,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"UInt8","name":"m_Enabled","size":1,"flags":16641,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"PPtr<AnimationClip>","name":"m_Animation","size":12,"flags":0,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"int","name":"m_FileID","size":4,"flags":1,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"SInt64","name":"m_PathID","size":8,"flags":1,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"vector","name":"m_Animations","size":-1,"flags":0,"v18meta":null},{"version":1,"level":2,"is_array":true,"type":"Array","name":"Array","size":-1,"flags":0,"v18meta":null},{"version":1,"level":3,"is_array":false,"type":"int","name":"size","size":4,"flags":0,"v18meta":null},{"version":1,"level":3,"is_array":false,"type":"PPtr<AnimationClip>","name":"data","size":12,"flags":0,"v18meta":null},{"version":1,"level":4,"is_array":false,"type":"int","name":"m_FileID","size":4,"flags":1,"v18meta":null},{"version":1,"level":4,"is_array":false,"type":"SInt64","name":"m_PathID","size":8,"flags":1,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"int","name":"m_WrapMode","size":4,"flags":0,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"bool","name":"m_PlayAutomatically","size":1,"flags":0,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"bool","name":"m_AnimatePhysics","size":1,"flags":16384,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"int","name":"m_CullingType","size":4,"flags":0,"v18meta":null}]}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{"nodes":[{"version":4,"level":0,"is_array":false,"type":"MonoScript","name":"Base","size":-1,"flags":32768,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"string","name":"m_Name","size":-1,"flags":32769,"v18meta":null},{"version":1,"level":2,"is_array":true,"type":"Array","name":"Array","size":-1,"flags":16385,"v18meta":null},{"version":1,"level":3,"is_array":false,"type":"int","name":"size","size":4,"flags":1,"v18meta":null},{"version":1,"level":3,"is_array":false,"type":"char","name":"data","size":1,"flags":1,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"int","name":"m_ExecutionOrder","size":4,"flags":16,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"Hash128","name":"m_PropertiesHash","size":16,"flags":16,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"UInt8","name":"bytes[0]","size":1,"flags":16,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"UInt8","name":"bytes[1]","size":1,"flags":16,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"UInt8","name":"bytes[2]","size":1,"flags":16,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"UInt8","name":"bytes[3]","size":1,"flags":16,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"UInt8","name":"bytes[4]","size":1,"flags":16,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"UInt8","name":"bytes[5]","size":1,"flags":16,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"UInt8","name":"bytes[6]","size":1,"flags":16,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"UInt8","name":"bytes[7]","size":1,"flags":16,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"UInt8","name":"bytes[8]","size":1,"flags":16,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"UInt8","name":"bytes[9]","size":1,"flags":16,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"UInt8","name":"bytes[10]","size":1,"flags":16,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"UInt8","name":"bytes[11]","size":1,"flags":16,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"UInt8","name":"bytes[12]","size":1,"flags":16,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"UInt8","name":"bytes[13]","size":1,"flags":16,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"UInt8","name":"bytes[14]","size":1,"flags":16,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"UInt8","name":"bytes[15]","size":1,"flags":16,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"string","name":"m_ClassName","size":-1,"flags":32784,"v18meta":null},{"version":1,"level":2,"is_array":true,"type":"Array","name":"Array","size":-1,"flags":16401,"v18meta":null},{"version":1,"level":3,"is_array":false,"type":"int","name":"size","size":4,"flags":17,"v18meta":null},{"version":1,"level":3,"is_array":false,"type":"char","name":"data","size":1,"flags":17,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"string","name":"m_Namespace","size":-1,"flags":32784,"v18meta":null},{"version":1,"level":2,"is_array":true,"type":"Array","name":"Array","size":-1,"flags":16401,"v18meta":null},{"version":1,"level":3,"is_array":false,"type":"int","name":"size","size":4,"flags":17,"v18meta":null},{"version":1,"level":3,"is_array":false,"type":"char","name":"data","size":1,"flags":17,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"string","name":"m_AssemblyName","size":-1,"flags":32784,"v18meta":null},{"version":1,"level":2,"is_array":true,"type":"Array","name":"Array","size":-1,"flags":16401,"v18meta":null},{"version":1,"level":3,"is_array":false,"type":"int","name":"size","size":4,"flags":17,"v18meta":null},{"version":1,"level":3,"is_array":false,"type":"char","name":"data","size":1,"flags":17,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"bool","name":"m_IsEditorScript","size":1,"flags":1,"v18meta":null}]}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{"nodes":[{"version":5,"level":0,"is_array":false,"type":"MonoScript","name":"Base","size":-1,"flags":32768,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"string","name":"m_Name","size":-1,"flags":557057,"v18meta":null},{"version":1,"level":2,"is_array":true,"type":"Array","name":"Array","size":-1,"flags":540673,"v18meta":null},{"version":1,"level":3,"is_array":false,"type":"int","name":"size","size":4,"flags":524289,"v18meta":null},{"version":1,"level":3,"is_array":false,"type":"char","name":"data","size":1,"flags":524289,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"int","name":"m_ExecutionOrder","size":4,"flags":16,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"Hash128","name":"m_PropertiesHash","size":16,"flags":16,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"UInt8","name":"bytes[0]","size":1,"flags":16,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"UInt8","name":"bytes[1]","size":1,"flags":16,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"UInt8","name":"bytes[2]","size":1,"flags":16,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"UInt8","name":"bytes[3]","size":1,"flags":16,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"UInt8","name":"bytes[4]","size":1,"flags":16,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"UInt8","name":"bytes[5]","size":1,"flags":16,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"UInt8","name":"bytes[6]","size":1,"flags":16,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"UInt8","name":"bytes[7]","size":1,"flags":16,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"UInt8","name":"bytes[8]","size":1,"flags":16,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"UInt8","name":"bytes[9]","size":1,"flags":16,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"UInt8","name":"bytes[10]","size":1,"flags":16,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"UInt8","name":"bytes[11]","size":1,"flags":16,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"UInt8","name":"bytes[12]","size":1,"flags":16,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"UInt8","name":"bytes[13]","size":1,"flags":16,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"UInt8","name":"bytes[14]","size":1,"flags":16,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"UInt8","name":"bytes[15]","size":1,"flags":16,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"string","name":"m_ClassName","size":-1,"flags":32784,"v18meta":null},{"version":1,"level":2,"is_array":true,"type":"Array","name":"Array","size":-1,"flags":16401,"v18meta":null},{"version":1,"level":3,"is_array":false,"type":"int","name":"size","size":4,"flags":17,"v18meta":null},{"version":1,"level":3,"is_array":false,"type":"char","name":"data","size":1,"flags":17,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"string","name":"m_Namespace","size":-1,"flags":32784,"v18meta":null},{"version":1,"level":2,"is_array":true,"type":"Array","name":"Array","size":-1,"flags":16401,"v18meta":null},{"version":1,"level":3,"is_array":false,"type":"int","name":"size","size":4,"flags":17,"v18meta":null},{"version":1,"level":3,"is_array":false,"type":"char","name":"data","size":1,"flags":17,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"string","name":"m_AssemblyName","size":-1,"flags":32784,"v18meta":null},{"version":1,"level":2,"is_array":true,"type":"Array","name":"Array","size":-1,"flags":16401,"v18meta":null},{"version":1,"level":3,"is_array":false,"type":"int","name":"size","size":4,"flags":17,"v18meta":null},{"version":1,"level":3,"is_array":false,"type":"char","name":"data","size":1,"flags":17,"v18meta":null}]}
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1 @@
|
|||||||
|
{"nodes":[{"version":1,"level":0,"is_array":false,"type":"Flare","name":"Base","size":-1,"flags":32768,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"string","name":"m_Name","size":-1,"flags":32769,"v18meta":null},{"version":1,"level":2,"is_array":true,"type":"Array","name":"Array","size":-1,"flags":16385,"v18meta":null},{"version":1,"level":3,"is_array":false,"type":"int","name":"size","size":4,"flags":1,"v18meta":null},{"version":1,"level":3,"is_array":false,"type":"char","name":"data","size":1,"flags":1,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"PPtr<Texture>","name":"m_FlareTexture","size":12,"flags":0,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"int","name":"m_FileID","size":4,"flags":8388609,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"SInt64","name":"m_PathID","size":8,"flags":8388609,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"int","name":"m_TextureLayout","size":4,"flags":0,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"vector","name":"m_Elements","size":-1,"flags":32768,"v18meta":null},{"version":1,"level":2,"is_array":true,"type":"Array","name":"Array","size":-1,"flags":16384,"v18meta":null},{"version":1,"level":3,"is_array":false,"type":"int","name":"size","size":4,"flags":0,"v18meta":null},{"version":1,"level":3,"is_array":false,"type":"FlareElement","name":"data","size":32,"flags":0,"v18meta":null},{"version":1,"level":4,"is_array":false,"type":"unsigned int","name":"m_ImageIndex","size":4,"flags":0,"v18meta":null},{"version":1,"level":4,"is_array":false,"type":"float","name":"m_Position","size":4,"flags":0,"v18meta":null},{"version":1,"level":4,"is_array":false,"type":"float","name":"m_Size","size":4,"flags":0,"v18meta":null},{"version":1,"level":4,"is_array":false,"type":"ColorRGBA","name":"m_Color","size":16,"flags":2097152,"v18meta":null},{"version":1,"level":5,"is_array":false,"type":"float","name":"r","size":4,"flags":2097153,"v18meta":null},{"version":1,"level":5,"is_array":false,"type":"float","name":"g","size":4,"flags":2097153,"v18meta":null},{"version":1,"level":5,"is_array":false,"type":"float","name":"b","size":4,"flags":2097153,"v18meta":null},{"version":1,"level":5,"is_array":false,"type":"float","name":"a","size":4,"flags":2097153,"v18meta":null},{"version":1,"level":4,"is_array":false,"type":"bool","name":"m_UseLightColor","size":1,"flags":0,"v18meta":null},{"version":1,"level":4,"is_array":false,"type":"bool","name":"m_Rotate","size":1,"flags":0,"v18meta":null},{"version":1,"level":4,"is_array":false,"type":"bool","name":"m_Zoom","size":1,"flags":0,"v18meta":null},{"version":1,"level":4,"is_array":false,"type":"bool","name":"m_Fade","size":1,"flags":0,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"bool","name":"m_UseFog","size":1,"flags":0,"v18meta":null}]}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{"nodes":[{"version":1,"level":0,"is_array":false,"type":"LensFlare","name":"Base","size":54,"flags":32768,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"PPtr<GameObject>","name":"m_GameObject","size":12,"flags":65,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"int","name":"m_FileID","size":4,"flags":65,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"SInt64","name":"m_PathID","size":8,"flags":65,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"UInt8","name":"m_Enabled","size":1,"flags":16641,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"PPtr<Flare>","name":"m_Flare","size":12,"flags":0,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"int","name":"m_FileID","size":4,"flags":8388609,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"SInt64","name":"m_PathID","size":8,"flags":8388609,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"ColorRGBA","name":"m_Color","size":16,"flags":2097152,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"float","name":"r","size":4,"flags":2097153,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"float","name":"g","size":4,"flags":2097153,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"float","name":"b","size":4,"flags":2097153,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"float","name":"a","size":4,"flags":2097153,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"float","name":"m_Brightness","size":4,"flags":0,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"float","name":"m_FadeSpeed","size":4,"flags":0,"v18meta":null},{"version":2,"level":1,"is_array":false,"type":"BitField","name":"m_IgnoreLayers","size":4,"flags":0,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"unsigned int","name":"m_Bits","size":4,"flags":4194305,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"bool","name":"m_Directional","size":1,"flags":0,"v18meta":null}]}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{"nodes":[{"version":1,"level":0,"is_array":false,"type":"Behaviour","name":"Base","size":13,"flags":32768,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"PPtr<GameObject>","name":"m_GameObject","size":12,"flags":65,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"int","name":"m_FileID","size":4,"flags":65,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"SInt64","name":"m_PathID","size":8,"flags":65,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"UInt8","name":"m_Enabled","size":1,"flags":16641,"v18meta":null}]}
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1 @@
|
|||||||
|
{"nodes":[{"version":2,"level":0,"is_array":false,"type":"SphereCollider","name":"Base","size":42,"flags":32768,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"PPtr<GameObject>","name":"m_GameObject","size":12,"flags":65,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"int","name":"m_FileID","size":4,"flags":65,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"SInt64","name":"m_PathID","size":8,"flags":65,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"PPtr<PhysicMaterial>","name":"m_Material","size":12,"flags":0,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"int","name":"m_FileID","size":4,"flags":8388609,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"SInt64","name":"m_PathID","size":8,"flags":8388609,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"bool","name":"m_IsTrigger","size":1,"flags":0,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"bool","name":"m_Enabled","size":1,"flags":16641,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"float","name":"m_Radius","size":4,"flags":0,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"Vector3f","name":"m_Center","size":12,"flags":2097152,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"float","name":"x","size":4,"flags":2097152,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"float","name":"y","size":4,"flags":2097152,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"float","name":"z","size":4,"flags":2097152,"v18meta":null}]}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{"nodes":[{"version":1,"level":0,"is_array":false,"type":"CapsuleCollider","name":"Base","size":50,"flags":32768,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"PPtr<GameObject>","name":"m_GameObject","size":12,"flags":65,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"int","name":"m_FileID","size":4,"flags":65,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"SInt64","name":"m_PathID","size":8,"flags":65,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"PPtr<PhysicMaterial>","name":"m_Material","size":12,"flags":0,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"int","name":"m_FileID","size":4,"flags":8388609,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"SInt64","name":"m_PathID","size":8,"flags":8388609,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"bool","name":"m_IsTrigger","size":1,"flags":0,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"bool","name":"m_Enabled","size":1,"flags":16641,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"float","name":"m_Radius","size":4,"flags":0,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"float","name":"m_Height","size":4,"flags":0,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"int","name":"m_Direction","size":4,"flags":8388608,"v18meta":null},{"version":1,"level":1,"is_array":false,"type":"Vector3f","name":"m_Center","size":12,"flags":2097152,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"float","name":"x","size":4,"flags":2097152,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"float","name":"y","size":4,"flags":2097152,"v18meta":null},{"version":1,"level":2,"is_array":false,"type":"float","name":"z","size":4,"flags":2097152,"v18meta":null}]}
|
||||||
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user