more and more update

This commit is contained in:
Ishotihadus
2019-12-09 00:44:21 +09:00
parent 629e82353a
commit e1ac05e540
1066 changed files with 1797 additions and 1384 deletions
+2
View File
@@ -15,3 +15,5 @@
*.bundle *.bundle
.DS_Store .DS_Store
.idea/
*.iml
+72 -71
View File
@@ -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
View File
@@ -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
-6
View File
@@ -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
View File
@@ -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
+86 -63
View File
@@ -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
+34
View File
@@ -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'
+63 -85
View File
@@ -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
View File
@@ -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
+2
View File
@@ -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
+483 -462
View File
@@ -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
+31 -16
View File
@@ -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
View File
@@ -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
+19
View File
@@ -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
+32
View File
@@ -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
@@ -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}]}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -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}]}
@@ -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}]}
@@ -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
@@ -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}]}
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