Compare commits
136 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c9394cd957 | |||
| 46c0e8ffe1 | |||
| d14c232015 | |||
| 4002bdecb8 | |||
| 17259e00c7 | |||
| 44b02b92d8 | |||
| 251854cc41 | |||
| 6f7b77245d | |||
| 6d99f5ebf6 | |||
| f1f2430f97 | |||
| b52696c965 | |||
| 5fba52dc83 | |||
| dfb74baf79 | |||
| 978e90a403 | |||
| c17d7d6331 | |||
| 9fef18d6ea | |||
| ee0cd4ab52 | |||
| f904bc138b | |||
| 7ed5345b1b | |||
| d7f652d572 | |||
| 32ce032655 | |||
| e1cf36aa3c | |||
| f644396a15 | |||
| 3e77c34bd5 | |||
| 052c60f629 | |||
| a1f2e3e7fe | |||
| 32ee8b326f | |||
| 06ce479eb6 | |||
| 03f74bac64 | |||
| 344b675745 | |||
| 86590d95a5 | |||
| bbea1341b2 | |||
| ca60dd9834 | |||
| 7aa35b5b8c | |||
| bd2decdb8f | |||
| 9b2c85bcae | |||
| efbab7c43a | |||
| 729a8a8263 | |||
| 0ec29f62ca | |||
| 796317f9d9 | |||
| 7596dcc7cd | |||
| 422851cdab | |||
| ec0a2a47f1 | |||
| 8ce5b947f6 | |||
| 419ca63f9d | |||
| 6fdb0c7b0e | |||
| 4e97b4b898 | |||
| 1766dcbdeb | |||
| ef38471ff1 | |||
| 217a7993e9 | |||
| 0a41615763 | |||
| 9d34f668d5 | |||
| 9269a36725 | |||
| 813e8b10a6 | |||
| 84c75fadf5 | |||
| c76e41b1ab | |||
| fefeea5f35 | |||
| 4a81c461e8 | |||
| b10d03d50d | |||
| da98a0c5b8 | |||
| 76d17bacf5 | |||
| 6678ce082b | |||
| 07074b3deb | |||
| df5d9f90d4 | |||
| 4f2d30552a | |||
| d259c7a5cd | |||
| c71ceb7ea6 | |||
| 85cf134a49 | |||
| 687b1d3a0d | |||
| a30a0d0bc5 | |||
| e1dc54d6d7 | |||
| c4270e186d | |||
| 182a42ace2 | |||
| 06fbe69a97 | |||
| a0bf4f9acd | |||
| 12568ba044 | |||
| de95b02285 | |||
| 286edfe72c | |||
| d717b223b7 | |||
| 9e195832ef | |||
| c8d08b2793 | |||
| 2bcd9662be | |||
| ea461ee3d2 | |||
| fda821b441 | |||
| 5c193c761a | |||
| 14f47c6d30 | |||
| e53eacef78 | |||
| ada26db659 | |||
| 48ca96807f | |||
| 2018028853 | |||
| 6f138dcc05 | |||
| 69bcd2be67 | |||
| 45ad53b19a | |||
| 6230240ee3 | |||
| 73ec9f4bee | |||
| f3a0bf505e | |||
| 290708876d | |||
| 5b96a29cca | |||
| 948e2c4d92 | |||
| 76da1c33ae | |||
| 72b84ee24d | |||
| 7b33d41172 | |||
| c7043c1a83 | |||
| d0baf26c61 | |||
| 60ac10b043 | |||
| 80dc24b487 | |||
| 9d32a9dd6a | |||
| d96cc3c762 | |||
| 509df42730 | |||
| 4efa5b0507 | |||
| cffe96b409 | |||
| 16dddc01e3 | |||
| b5d2c2cadb | |||
| 1d2c0ab6cb | |||
| c6b7e04c47 | |||
| 5704813b28 | |||
| 465c989e75 | |||
| d335aaef9e | |||
| 495b48c783 | |||
| 05b55722fb | |||
| de54257eef | |||
| e62b6c3d77 | |||
| dc05e5b5eb | |||
| f377381e26 | |||
| 20f9fe493f | |||
| 0b462754a5 | |||
| b1ea8dd346 | |||
| 4a46f897bd | |||
| 6a5ec80de7 | |||
| 4f2046d412 | |||
| 1cf59e8d67 | |||
| e9e8390bbc | |||
| 738b084440 | |||
| 32cce894ac | |||
| a6264b39d1 | |||
| eb4981808b |
+151
-21
@@ -1,7 +1,10 @@
|
||||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
##
|
||||
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||
|
||||
# User-specific files
|
||||
*.rsuser
|
||||
*.suo
|
||||
*.user
|
||||
*.userosscache
|
||||
@@ -15,13 +18,22 @@
|
||||
[Dd]ebugPublic/
|
||||
[Rr]elease/
|
||||
[Rr]eleases/
|
||||
build/
|
||||
x64/
|
||||
x86/
|
||||
[Aa][Rr][Mm]/
|
||||
[Aa][Rr][Mm]64/
|
||||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
[Ll]og/
|
||||
|
||||
# Visual Studio 2015 cache/options directory
|
||||
# Visual Studio 2015/2017 cache/options directory
|
||||
.vs/
|
||||
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||
#wwwroot/
|
||||
|
||||
# Visual Studio 2017 auto generated files
|
||||
Generated\ Files/
|
||||
|
||||
# MSTest test Results
|
||||
[Tt]est[Rr]esult*/
|
||||
@@ -36,18 +48,28 @@ TestResult.xml
|
||||
[Rr]eleasePS/
|
||||
dlldata.c
|
||||
|
||||
# DNX
|
||||
# Benchmark Results
|
||||
BenchmarkDotNet.Artifacts/
|
||||
|
||||
# .NET Core
|
||||
project.lock.json
|
||||
project.fragment.lock.json
|
||||
artifacts/
|
||||
|
||||
# StyleCop
|
||||
StyleCopReport.xml
|
||||
|
||||
# Files built by Visual Studio
|
||||
*_i.c
|
||||
*_p.c
|
||||
*_i.h
|
||||
*_h.h
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.iobj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.ipdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
@@ -57,6 +79,7 @@ artifacts/
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.tmp_proj
|
||||
*_wpftmp.csproj
|
||||
*.log
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
@@ -72,14 +95,21 @@ _Chutzpah*
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opendb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
*.VC.db
|
||||
*.VC.VC.opendb
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
*.sap
|
||||
|
||||
# Visual Studio Trace Files
|
||||
*.e2e
|
||||
|
||||
# TFS 2012 Local Workspace
|
||||
$tf/
|
||||
@@ -101,9 +131,18 @@ _TeamCity*
|
||||
# DotCover is a Code Coverage Tool
|
||||
*.dotCover
|
||||
|
||||
# AxoCover is a Code Coverage Tool
|
||||
.axoCover/*
|
||||
!.axoCover/settings.json
|
||||
|
||||
# Visual Studio code coverage results
|
||||
*.coverage
|
||||
*.coveragexml
|
||||
|
||||
# NCrunch
|
||||
_NCrunch_*
|
||||
.*crunch*.local.xml
|
||||
nCrunchTemp_*
|
||||
|
||||
# MightyMoose
|
||||
*.mm.*
|
||||
@@ -131,47 +170,68 @@ publish/
|
||||
# Publish Web Output
|
||||
*.[Pp]ublish.xml
|
||||
*.azurePubxml
|
||||
## TODO: Comment the next line if you want to checkin your
|
||||
## web deploy settings but do note that will include unencrypted
|
||||
## passwords
|
||||
#*.pubxml
|
||||
|
||||
# Note: Comment the next line if you want to checkin your web deploy settings,
|
||||
# but database connection strings (with potential passwords) will be unencrypted
|
||||
*.pubxml
|
||||
*.publishproj
|
||||
|
||||
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||
# in these scripts will be unencrypted
|
||||
PublishScripts/
|
||||
|
||||
# NuGet Packages
|
||||
*.nupkg
|
||||
# The packages folder can be ignored because of Package Restore
|
||||
**/packages/*
|
||||
**/[Pp]ackages/*
|
||||
# except build/, which is used as an MSBuild target.
|
||||
!**/packages/build/
|
||||
!**/[Pp]ackages/build/
|
||||
# Uncomment if necessary however generally it will be regenerated when needed
|
||||
#!**/packages/repositories.config
|
||||
#!**/[Pp]ackages/repositories.config
|
||||
# NuGet v3's project.json files produces more ignorable files
|
||||
*.nuget.props
|
||||
*.nuget.targets
|
||||
|
||||
# Windows Azure Build Output
|
||||
# Microsoft Azure Build Output
|
||||
csx/
|
||||
*.build.csdef
|
||||
|
||||
# Windows Store app package directory
|
||||
# Microsoft Azure Emulator
|
||||
ecf/
|
||||
rcf/
|
||||
|
||||
# Windows Store app package directories and files
|
||||
AppPackages/
|
||||
BundleArtifacts/
|
||||
Package.StoreAssociation.xml
|
||||
_pkginfo.txt
|
||||
*.appx
|
||||
|
||||
# Visual Studio cache files
|
||||
# files ending in .cache can be ignored
|
||||
*.[Cc]ache
|
||||
# but keep track of directories ending in .cache
|
||||
!*.[Cc]ache/
|
||||
!?*.[Cc]ache/
|
||||
|
||||
# Others
|
||||
ClientBin/
|
||||
[Ss]tyle[Cc]op.*
|
||||
~$*
|
||||
*~
|
||||
*.dbmdl
|
||||
*.dbproj.schemaview
|
||||
*.jfm
|
||||
*.pfx
|
||||
*.publishsettings
|
||||
node_modules/
|
||||
orleans.codegen.cs
|
||||
|
||||
# Including strong name files can present a security risk
|
||||
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
||||
#*.snk
|
||||
|
||||
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||
#bower_components/
|
||||
|
||||
# RIA/Silverlight projects
|
||||
Generated_Code/
|
||||
|
||||
@@ -182,21 +242,30 @@ _UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
UpgradeLog*.htm
|
||||
ServiceFabricBackup/
|
||||
*.rptproj.bak
|
||||
|
||||
# SQL Server files
|
||||
*.mdf
|
||||
*.ldf
|
||||
*.ndf
|
||||
|
||||
# Business Intelligence projects
|
||||
*.rdl.data
|
||||
*.bim.layout
|
||||
*.bim_*.settings
|
||||
*.rptproj.rsuser
|
||||
*- Backup*.rdl
|
||||
|
||||
# Microsoft Fakes
|
||||
FakesAssemblies/
|
||||
|
||||
# GhostDoc plugin setting file
|
||||
*.GhostDoc.xml
|
||||
|
||||
# Node.js Tools for Visual Studio
|
||||
.ntvs_analysis.dat
|
||||
node_modules/
|
||||
|
||||
# Visual Studio 6 build log
|
||||
*.plg
|
||||
@@ -204,7 +273,68 @@ FakesAssemblies/
|
||||
# Visual Studio 6 workspace options file
|
||||
*.opt
|
||||
|
||||
# LightSwitch generated files
|
||||
GeneratedArtifacts/
|
||||
_Pvt_Extensions/
|
||||
ModelManifest.xml
|
||||
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||
*.vbw
|
||||
|
||||
# Visual Studio LightSwitch build output
|
||||
**/*.HTMLClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/ModelManifest.xml
|
||||
**/*.Server/GeneratedArtifacts
|
||||
**/*.Server/ModelManifest.xml
|
||||
_Pvt_Extensions
|
||||
|
||||
# Paket dependency manager
|
||||
.paket/paket.exe
|
||||
paket-files/
|
||||
|
||||
# FAKE - F# Make
|
||||
.fake/
|
||||
|
||||
# JetBrains Rider
|
||||
.idea/
|
||||
*.sln.iml
|
||||
|
||||
# CodeRush personal settings
|
||||
.cr/personal
|
||||
|
||||
# Python Tools for Visual Studio (PTVS)
|
||||
__pycache__/
|
||||
*.pyc
|
||||
|
||||
# Cake - Uncomment if you are using it
|
||||
# tools/**
|
||||
# !tools/packages.config
|
||||
|
||||
# Tabs Studio
|
||||
*.tss
|
||||
|
||||
# Telerik's JustMock configuration file
|
||||
*.jmconfig
|
||||
|
||||
# BizTalk build output
|
||||
*.btp.cs
|
||||
*.btm.cs
|
||||
*.odx.cs
|
||||
*.xsd.cs
|
||||
|
||||
# OpenCover UI analysis results
|
||||
OpenCover/
|
||||
|
||||
# Azure Stream Analytics local run output
|
||||
ASALocalRun/
|
||||
|
||||
# MSBuild Binary and Structured Log
|
||||
*.binlog
|
||||
|
||||
# NVidia Nsight GPU debugger configuration file
|
||||
*.nvuser
|
||||
|
||||
# MFractors (Xamarin productivity tool) working folder
|
||||
.mfractor/
|
||||
|
||||
# Local History for Visual Studio
|
||||
.localhistory/
|
||||
|
||||
# BeatPulse healthcheck temp database
|
||||
healthchecksdb
|
||||
@@ -0,0 +1,51 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{40C796B5-88CE-4ADC-ACD6-2F4862B7F136}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>AssetStudio.PInvoke</RootNamespace>
|
||||
<AssemblyName>AssetStudio.PInvoke</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<Deterministic>true</Deterministic>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="DllLoader.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Utf8StringHandle.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
||||
@@ -0,0 +1,124 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace AssetStudio.PInvoke
|
||||
{
|
||||
public static class DllLoader
|
||||
{
|
||||
|
||||
public static void PreloadDll(string dllName)
|
||||
{
|
||||
var dllDir = GetDirectedDllDirectory();
|
||||
|
||||
// Not using OperatingSystem.Platform.
|
||||
// See: https://www.mono-project.com/docs/faq/technical/#how-to-detect-the-execution-platform
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
{
|
||||
Win32.LoadDll(dllDir, dllName);
|
||||
}
|
||||
else
|
||||
{
|
||||
Posix.LoadDll(dllDir, dllName);
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetDirectedDllDirectory()
|
||||
{
|
||||
var localPath = Process.GetCurrentProcess().MainModule.FileName;
|
||||
var localDir = Path.GetDirectoryName(localPath);
|
||||
|
||||
var subDir = Environment.Is64BitProcess ? "x64" : "x86";
|
||||
|
||||
var directedDllDir = Path.Combine(localDir, subDir);
|
||||
|
||||
return directedDllDir;
|
||||
}
|
||||
|
||||
private static class Win32
|
||||
{
|
||||
|
||||
internal static void LoadDll(string dllDir, string dllName)
|
||||
{
|
||||
var dllFileName = $"{dllName}.dll";
|
||||
var directedDllPath = Path.Combine(dllDir, dllFileName);
|
||||
|
||||
// Specify SEARCH_DLL_LOAD_DIR to load dependent libraries located in the same platform-specific directory.
|
||||
var hLibrary = LoadLibraryEx(directedDllPath, IntPtr.Zero, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR);
|
||||
|
||||
if (hLibrary == IntPtr.Zero)
|
||||
{
|
||||
var errorCode = Marshal.GetLastWin32Error();
|
||||
var exception = new Win32Exception(errorCode);
|
||||
|
||||
throw new DllNotFoundException(exception.Message, exception);
|
||||
}
|
||||
}
|
||||
|
||||
// HMODULE LoadLibraryExA(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags);
|
||||
// HMODULE LoadLibraryExW(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags);
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
private static extern IntPtr LoadLibraryEx(string lpLibFileName, IntPtr hFile, uint dwFlags);
|
||||
|
||||
private const uint LOAD_LIBRARY_SEARCH_DEFAULT_DIRS = 0x1000;
|
||||
private const uint LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR = 0x100;
|
||||
|
||||
}
|
||||
|
||||
private static class Posix
|
||||
{
|
||||
|
||||
internal static void LoadDll(string dllDir, string dllName)
|
||||
{
|
||||
string dllExtension;
|
||||
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||
{
|
||||
dllExtension = ".so";
|
||||
}
|
||||
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
|
||||
{
|
||||
dllExtension = ".dylib";
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
var dllFileName = $"lib{dllName}{dllExtension}";
|
||||
var directedDllPath = Path.Combine(dllDir, dllFileName);
|
||||
|
||||
const int ldFlags = RTLD_NOW | RTLD_GLOBAL;
|
||||
var hLibrary = DlOpen(directedDllPath, ldFlags);
|
||||
|
||||
if (hLibrary == IntPtr.Zero)
|
||||
{
|
||||
var pErrStr = DlError();
|
||||
// `PtrToStringAnsi` always uses the specific constructor of `String` (see dotnet/core#2325),
|
||||
// which in turn interprets the byte sequence with system default codepage. On OSX and Linux
|
||||
// the codepage is UTF-8 so the error message should be handled correctly.
|
||||
var errorMessage = Marshal.PtrToStringAnsi(pErrStr);
|
||||
|
||||
throw new DllNotFoundException(errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
// OSX and most Linux OS use LP64 so `int` is still 32-bit even on 64-bit platforms.
|
||||
// void *dlopen(const char *filename, int flag);
|
||||
[DllImport("libdl", EntryPoint = "dlopen")]
|
||||
private static extern IntPtr DlOpen([MarshalAs(UnmanagedType.LPStr)] string fileName, int flags);
|
||||
|
||||
// char *dlerror(void);
|
||||
[DllImport("libdl", EntryPoint = "dlerror")]
|
||||
private static extern IntPtr DlError();
|
||||
|
||||
private const int RTLD_LAZY = 0x1;
|
||||
private const int RTLD_NOW = 0x2;
|
||||
private const int RTLD_GLOBAL = 0x100;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// 有关程序集的一般信息由以下
|
||||
// 控制。更改这些特性值可修改
|
||||
// 与程序集关联的信息。
|
||||
[assembly: AssemblyTitle("AssetStudio.PInvoke")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("AssetStudio.PInvoke")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2020")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// 将 ComVisible 设置为 false 会使此程序集中的类型
|
||||
//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
|
||||
//请将此类型的 ComVisible 特性设置为 true。
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
|
||||
[assembly: Guid("40c796b5-88ce-4adc-acd6-2f4862b7f136")]
|
||||
|
||||
// 程序集的版本信息由下列四个值组成:
|
||||
//
|
||||
// 主版本
|
||||
// 次版本
|
||||
// 生成号
|
||||
// 修订号
|
||||
//
|
||||
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
|
||||
//通过使用 "*",如下所示:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
@@ -0,0 +1,100 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using Microsoft.Win32.SafeHandles;
|
||||
|
||||
namespace AssetStudio.PInvoke
|
||||
{
|
||||
// Generally the technique from Steamworks.NET
|
||||
public class Utf8StringHandle : SafeHandleZeroOrMinusOneIsInvalid
|
||||
{
|
||||
|
||||
static Utf8StringHandle()
|
||||
{
|
||||
Utf8 = new UTF8Encoding(false);
|
||||
}
|
||||
|
||||
public Utf8StringHandle(string str)
|
||||
: base(true)
|
||||
{
|
||||
IntPtr buffer;
|
||||
|
||||
if (str == null)
|
||||
{
|
||||
buffer = IntPtr.Zero;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (str.Length == 0)
|
||||
{
|
||||
buffer = Marshal.AllocHGlobal(1);
|
||||
|
||||
unsafe
|
||||
{
|
||||
*(byte*)buffer = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var strlen = Utf8.GetByteCount(str);
|
||||
var strBuffer = new byte[strlen + 1];
|
||||
|
||||
Utf8.GetBytes(str, 0, str.Length, strBuffer, 0);
|
||||
|
||||
buffer = Marshal.AllocHGlobal(strBuffer.Length);
|
||||
|
||||
Marshal.Copy(strBuffer, 0, buffer, strBuffer.Length);
|
||||
}
|
||||
}
|
||||
|
||||
SetHandle(buffer);
|
||||
}
|
||||
|
||||
public static string ReadUtf8StringFromPointer(IntPtr lpstr)
|
||||
{
|
||||
if (lpstr == IntPtr.Zero || lpstr == new IntPtr(-1))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var byteCount = 0;
|
||||
|
||||
unsafe
|
||||
{
|
||||
var p = (byte*)lpstr.ToPointer();
|
||||
|
||||
while (*p != 0)
|
||||
{
|
||||
byteCount += 1;
|
||||
p += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (byteCount == 0)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
var strBuffer = new byte[byteCount];
|
||||
|
||||
Marshal.Copy(lpstr, strBuffer, 0, byteCount);
|
||||
|
||||
var str = Utf8.GetString(strBuffer);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
protected override bool ReleaseHandle()
|
||||
{
|
||||
if (!IsInvalid)
|
||||
{
|
||||
Marshal.FreeHGlobal(handle);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static readonly UTF8Encoding Utf8;
|
||||
|
||||
}
|
||||
}
|
||||
+119
-39
@@ -1,61 +1,141 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.27130.2024
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.29920.165
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AssetStudioGUI", "AssetStudioGUI\AssetStudioGUI.csproj", "{24551E2D-E9B6-4CD6-8F2A-D9F4A13E7853}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AssetStudio", "AssetStudio\AssetStudio.csproj", "{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AssetStudioFBX", "AssetStudioFBX\AssetStudioFBX.vcxproj", "{4F8EF5EF-732B-49CF-9EB3-B23E19AE6267}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AssetStudioUtility", "AssetStudioUtility\AssetStudioUtility.csproj", "{80AEC261-21EE-4E4F-A93B-7A744DC84888}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AssetStudioUtility", "AssetStudioUtility\AssetStudioUtility.csproj", "{9131C403-7FE8-444D-9AF5-5FE5DF76FF24}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AssetStudioGUI", "AssetStudioGUI\AssetStudioGUI.csproj", "{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AssetStudio", "AssetStudio\AssetStudio.csproj", "{AF56B63C-1764-41B7-9E60-8D485422AC3B}"
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AssetStudioFBXNative", "AssetStudioFBXNative\AssetStudioFBXNative.vcxproj", "{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AssetStudioFBXWrapper", "AssetStudioFBXWrapper\AssetStudioFBXWrapper.csproj", "{BD76E63F-1517-47FA-8233-33E853A3ACEE}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027} = {11EA25A3-ED68-40EE-A9D0-7FDE3B583027}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Texture2DDecoderNative", "Texture2DDecoderNative\Texture2DDecoderNative.vcxproj", "{29356642-C46E-4144-83D8-22DC09D0D7FD}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Texture2DDecoderWrapper", "Texture2DDecoderWrapper\Texture2DDecoderWrapper.csproj", "{2AFCE830-B463-49B3-A026-877E5EAFC0A4}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{29356642-C46E-4144-83D8-22DC09D0D7FD} = {29356642-C46E-4144-83D8-22DC09D0D7FD}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AssetStudio.PInvoke", "AssetStudio.PInvoke\AssetStudio.PInvoke.csproj", "{40C796B5-88CE-4ADC-ACD6-2F4862B7F136}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{24551E2D-E9B6-4CD6-8F2A-D9F4A13E7853}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{24551E2D-E9B6-4CD6-8F2A-D9F4A13E7853}.Debug|x64.Build.0 = Debug|x64
|
||||
{24551E2D-E9B6-4CD6-8F2A-D9F4A13E7853}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{24551E2D-E9B6-4CD6-8F2A-D9F4A13E7853}.Debug|x86.Build.0 = Debug|x86
|
||||
{24551E2D-E9B6-4CD6-8F2A-D9F4A13E7853}.Release|x64.ActiveCfg = Release|x64
|
||||
{24551E2D-E9B6-4CD6-8F2A-D9F4A13E7853}.Release|x64.Build.0 = Release|x64
|
||||
{24551E2D-E9B6-4CD6-8F2A-D9F4A13E7853}.Release|x86.ActiveCfg = Release|x86
|
||||
{24551E2D-E9B6-4CD6-8F2A-D9F4A13E7853}.Release|x86.Build.0 = Release|x86
|
||||
{4F8EF5EF-732B-49CF-9EB3-B23E19AE6267}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{4F8EF5EF-732B-49CF-9EB3-B23E19AE6267}.Debug|x64.Build.0 = Debug|x64
|
||||
{4F8EF5EF-732B-49CF-9EB3-B23E19AE6267}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{4F8EF5EF-732B-49CF-9EB3-B23E19AE6267}.Debug|x86.Build.0 = Debug|Win32
|
||||
{4F8EF5EF-732B-49CF-9EB3-B23E19AE6267}.Release|x64.ActiveCfg = Release|x64
|
||||
{4F8EF5EF-732B-49CF-9EB3-B23E19AE6267}.Release|x64.Build.0 = Release|x64
|
||||
{4F8EF5EF-732B-49CF-9EB3-B23E19AE6267}.Release|x86.ActiveCfg = Release|Win32
|
||||
{4F8EF5EF-732B-49CF-9EB3-B23E19AE6267}.Release|x86.Build.0 = Release|Win32
|
||||
{9131C403-7FE8-444D-9AF5-5FE5DF76FF24}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{9131C403-7FE8-444D-9AF5-5FE5DF76FF24}.Debug|x64.Build.0 = Debug|x64
|
||||
{9131C403-7FE8-444D-9AF5-5FE5DF76FF24}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{9131C403-7FE8-444D-9AF5-5FE5DF76FF24}.Debug|x86.Build.0 = Debug|x86
|
||||
{9131C403-7FE8-444D-9AF5-5FE5DF76FF24}.Release|x64.ActiveCfg = Release|x64
|
||||
{9131C403-7FE8-444D-9AF5-5FE5DF76FF24}.Release|x64.Build.0 = Release|x64
|
||||
{9131C403-7FE8-444D-9AF5-5FE5DF76FF24}.Release|x86.ActiveCfg = Release|x86
|
||||
{9131C403-7FE8-444D-9AF5-5FE5DF76FF24}.Release|x86.Build.0 = Release|x86
|
||||
{AF56B63C-1764-41B7-9E60-8D485422AC3B}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{AF56B63C-1764-41B7-9E60-8D485422AC3B}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{AF56B63C-1764-41B7-9E60-8D485422AC3B}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{AF56B63C-1764-41B7-9E60-8D485422AC3B}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{AF56B63C-1764-41B7-9E60-8D485422AC3B}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{AF56B63C-1764-41B7-9E60-8D485422AC3B}.Release|x64.Build.0 = Release|Any CPU
|
||||
{AF56B63C-1764-41B7-9E60-8D485422AC3B}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{AF56B63C-1764-41B7-9E60-8D485422AC3B}.Release|x86.Build.0 = Release|Any CPU
|
||||
{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}.Release|x64.Build.0 = Release|Any CPU
|
||||
{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}.Release|x86.Build.0 = Release|Any CPU
|
||||
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Release|x64.Build.0 = Release|Any CPU
|
||||
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Release|x86.Build.0 = Release|Any CPU
|
||||
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Release|x64.Build.0 = Release|Any CPU
|
||||
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Release|x86.Build.0 = Release|Any CPU
|
||||
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Debug|Any CPU.Build.0 = Debug|Win32
|
||||
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Debug|x64.Build.0 = Debug|x64
|
||||
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Debug|x86.Build.0 = Debug|Win32
|
||||
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Release|Any CPU.Build.0 = Release|Win32
|
||||
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Release|x64.ActiveCfg = Release|x64
|
||||
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Release|x64.Build.0 = Release|x64
|
||||
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Release|x86.ActiveCfg = Release|Win32
|
||||
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Release|x86.Build.0 = Release|Win32
|
||||
{BD76E63F-1517-47FA-8233-33E853A3ACEE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{BD76E63F-1517-47FA-8233-33E853A3ACEE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BD76E63F-1517-47FA-8233-33E853A3ACEE}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{BD76E63F-1517-47FA-8233-33E853A3ACEE}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{BD76E63F-1517-47FA-8233-33E853A3ACEE}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{BD76E63F-1517-47FA-8233-33E853A3ACEE}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{BD76E63F-1517-47FA-8233-33E853A3ACEE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BD76E63F-1517-47FA-8233-33E853A3ACEE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{BD76E63F-1517-47FA-8233-33E853A3ACEE}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{BD76E63F-1517-47FA-8233-33E853A3ACEE}.Release|x64.Build.0 = Release|Any CPU
|
||||
{BD76E63F-1517-47FA-8233-33E853A3ACEE}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{BD76E63F-1517-47FA-8233-33E853A3ACEE}.Release|x86.Build.0 = Release|Any CPU
|
||||
{29356642-C46E-4144-83D8-22DC09D0D7FD}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{29356642-C46E-4144-83D8-22DC09D0D7FD}.Debug|Any CPU.Build.0 = Debug|Win32
|
||||
{29356642-C46E-4144-83D8-22DC09D0D7FD}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{29356642-C46E-4144-83D8-22DC09D0D7FD}.Debug|x64.Build.0 = Debug|x64
|
||||
{29356642-C46E-4144-83D8-22DC09D0D7FD}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{29356642-C46E-4144-83D8-22DC09D0D7FD}.Debug|x86.Build.0 = Debug|Win32
|
||||
{29356642-C46E-4144-83D8-22DC09D0D7FD}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{29356642-C46E-4144-83D8-22DC09D0D7FD}.Release|Any CPU.Build.0 = Release|Win32
|
||||
{29356642-C46E-4144-83D8-22DC09D0D7FD}.Release|x64.ActiveCfg = Release|x64
|
||||
{29356642-C46E-4144-83D8-22DC09D0D7FD}.Release|x64.Build.0 = Release|x64
|
||||
{29356642-C46E-4144-83D8-22DC09D0D7FD}.Release|x86.ActiveCfg = Release|Win32
|
||||
{29356642-C46E-4144-83D8-22DC09D0D7FD}.Release|x86.Build.0 = Release|Win32
|
||||
{2AFCE830-B463-49B3-A026-877E5EAFC0A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2AFCE830-B463-49B3-A026-877E5EAFC0A4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2AFCE830-B463-49B3-A026-877E5EAFC0A4}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{2AFCE830-B463-49B3-A026-877E5EAFC0A4}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{2AFCE830-B463-49B3-A026-877E5EAFC0A4}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{2AFCE830-B463-49B3-A026-877E5EAFC0A4}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{2AFCE830-B463-49B3-A026-877E5EAFC0A4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2AFCE830-B463-49B3-A026-877E5EAFC0A4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{2AFCE830-B463-49B3-A026-877E5EAFC0A4}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{2AFCE830-B463-49B3-A026-877E5EAFC0A4}.Release|x64.Build.0 = Release|Any CPU
|
||||
{2AFCE830-B463-49B3-A026-877E5EAFC0A4}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{2AFCE830-B463-49B3-A026-877E5EAFC0A4}.Release|x86.Build.0 = Release|Any CPU
|
||||
{40C796B5-88CE-4ADC-ACD6-2F4862B7F136}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{40C796B5-88CE-4ADC-ACD6-2F4862B7F136}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{40C796B5-88CE-4ADC-ACD6-2F4862B7F136}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{40C796B5-88CE-4ADC-ACD6-2F4862B7F136}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{40C796B5-88CE-4ADC-ACD6-2F4862B7F136}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{40C796B5-88CE-4ADC-ACD6-2F4862B7F136}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{40C796B5-88CE-4ADC-ACD6-2F4862B7F136}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{40C796B5-88CE-4ADC-ACD6-2F4862B7F136}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{40C796B5-88CE-4ADC-ACD6-2F4862B7F136}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{40C796B5-88CE-4ADC-ACD6-2F4862B7F136}.Release|x64.Build.0 = Release|Any CPU
|
||||
{40C796B5-88CE-4ADC-ACD6-2F4862B7F136}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{40C796B5-88CE-4ADC-ACD6-2F4862B7F136}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {F5C476A6-2B3B-416F-8BD5-6FE454FF3972}
|
||||
SolutionGuid = {F8734F96-97B6-40CA-B791-6D5467F2F713}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{AF56B63C-1764-41B7-9E60-8D485422AC3B}</ProjectGuid>
|
||||
<ProjectGuid>{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>AssetStudio</RootNamespace>
|
||||
<AssemblyName>AssetStudio</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<Deterministic>true</Deterministic>
|
||||
</PropertyGroup>
|
||||
@@ -33,12 +33,6 @@
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="7zip\Common\CommandLineParser.cs" />
|
||||
@@ -56,22 +50,7 @@
|
||||
<Compile Include="7zip\Compress\RangeCoder\RangeCoderBit.cs" />
|
||||
<Compile Include="7zip\Compress\RangeCoder\RangeCoderBitTree.cs" />
|
||||
<Compile Include="7zip\ICoder.cs" />
|
||||
<Compile Include="Classes\RuntimeAnimatorController.cs" />
|
||||
<Compile Include="Math\Color.cs" />
|
||||
<Compile Include="Math\Half.cs" />
|
||||
<Compile Include="Math\HalfHelper.cs" />
|
||||
<Compile Include="Math\Matrix4x4.cs" />
|
||||
<Compile Include="Math\Quaternion.cs" />
|
||||
<Compile Include="Math\Vector2.cs" />
|
||||
<Compile Include="Math\Vector3.cs" />
|
||||
<Compile Include="Math\Vector4.cs" />
|
||||
<Compile Include="UType.cs" />
|
||||
<Compile Include="ResourceReader.cs" />
|
||||
<Compile Include="IImported.cs" />
|
||||
<Compile Include="SerializedFile.cs" />
|
||||
<Compile Include="AssetsManager.cs" />
|
||||
<Compile Include="Extensions\BinaryReaderExtensions.cs" />
|
||||
<Compile Include="Extensions\BinaryWriterExtensions.cs" />
|
||||
<Compile Include="Brotli\BitReader.cs" />
|
||||
<Compile Include="Brotli\BrotliInputStream.cs" />
|
||||
<Compile Include="Brotli\BrotliRuntimeException.cs" />
|
||||
@@ -114,8 +93,11 @@
|
||||
<Compile Include="Classes\NamedObject.cs" />
|
||||
<Compile Include="Classes\Object.cs" />
|
||||
<Compile Include="Classes\PlayerSettings.cs" />
|
||||
<Compile Include="Classes\PPtr.cs" />
|
||||
<Compile Include="Classes\RectTransform.cs" />
|
||||
<Compile Include="Classes\Renderer.cs" />
|
||||
<Compile Include="Classes\ResourceManager.cs" />
|
||||
<Compile Include="Classes\RuntimeAnimatorController.cs" />
|
||||
<Compile Include="Classes\Shader.cs" />
|
||||
<Compile Include="Classes\SkinnedMeshRenderer.cs" />
|
||||
<Compile Include="Classes\Sprite.cs" />
|
||||
@@ -128,26 +110,38 @@
|
||||
<Compile Include="ClassIDType.cs" />
|
||||
<Compile Include="CommonString.cs" />
|
||||
<Compile Include="EndianBinaryReader.cs" />
|
||||
<Compile Include="Extensions\BinaryReaderExtensions.cs" />
|
||||
<Compile Include="Extensions\BinaryWriterExtensions.cs" />
|
||||
<Compile Include="Extensions\StreamExtensions.cs" />
|
||||
<Compile Include="FileIdentifier.cs" />
|
||||
<Compile Include="IImported.cs" />
|
||||
<Compile Include="ILogger.cs" />
|
||||
<Compile Include="ImportHelper.cs" />
|
||||
<Compile Include="IProgress.cs" />
|
||||
<Compile Include="LocalSerializedObjectIdentifier.cs" />
|
||||
<Compile Include="Logger.cs" />
|
||||
<Compile Include="Lz4DecoderStream.cs" />
|
||||
<Compile Include="Math\Color.cs" />
|
||||
<Compile Include="Math\Half.cs" />
|
||||
<Compile Include="Math\HalfHelper.cs" />
|
||||
<Compile Include="Math\Matrix4x4.cs" />
|
||||
<Compile Include="Math\Quaternion.cs" />
|
||||
<Compile Include="Math\Vector2.cs" />
|
||||
<Compile Include="Math\Vector3.cs" />
|
||||
<Compile Include="Math\Vector4.cs" />
|
||||
<Compile Include="ObjectInfo.cs" />
|
||||
<Compile Include="ObjectReader.cs" />
|
||||
<Compile Include="Classes\PPtr.cs" />
|
||||
<Compile Include="Progress.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="ResourceReader.cs" />
|
||||
<Compile Include="SerializedFile.cs" />
|
||||
<Compile Include="SerializedFileHeader.cs" />
|
||||
<Compile Include="SerializedType.cs" />
|
||||
<Compile Include="SevenZipHelper.cs" />
|
||||
<Compile Include="Extensions\StreamExtensions.cs" />
|
||||
<Compile Include="StreamFile.cs" />
|
||||
<Compile Include="TypeTreeHelper.cs" />
|
||||
<Compile Include="TypeTreeNode.cs" />
|
||||
<Compile Include="WebFile.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
||||
+160
-120
@@ -1,6 +1,8 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using static AssetStudio.ImportHelper;
|
||||
|
||||
namespace AssetStudio
|
||||
@@ -8,12 +10,12 @@ namespace AssetStudio
|
||||
public class AssetsManager
|
||||
{
|
||||
public List<SerializedFile> assetsFileList = new List<SerializedFile>();
|
||||
internal Dictionary<string, int> assetsFileIndexCache = new Dictionary<string, int>();
|
||||
internal Dictionary<string, EndianBinaryReader> resourceFileReaders = new Dictionary<string, EndianBinaryReader>();
|
||||
internal Dictionary<string, int> assetsFileIndexCache = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
|
||||
internal Dictionary<string, BinaryReader> resourceFileReaders = new Dictionary<string, BinaryReader>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
private List<string> importFiles = new List<string>();
|
||||
private HashSet<string> importFilesHash = new HashSet<string>();
|
||||
private HashSet<string> assetsFileListHash = new HashSet<string>();
|
||||
private HashSet<string> importFilesHash = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
private HashSet<string> assetsFileListHash = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
public void LoadFiles(params string[] files)
|
||||
{
|
||||
@@ -36,7 +38,7 @@ namespace AssetStudio
|
||||
foreach (var file in files)
|
||||
{
|
||||
importFiles.Add(file);
|
||||
importFilesHash.Add(Path.GetFileName(file).ToUpper());
|
||||
importFilesHash.Add(Path.GetFileName(file));
|
||||
}
|
||||
|
||||
Progress.Reset();
|
||||
@@ -52,7 +54,7 @@ namespace AssetStudio
|
||||
assetsFileListHash.Clear();
|
||||
|
||||
ReadAssets();
|
||||
ProcessGameObject();
|
||||
ProcessAssets();
|
||||
}
|
||||
|
||||
private void LoadFile(string fullName)
|
||||
@@ -74,21 +76,21 @@ namespace AssetStudio
|
||||
private void LoadAssetsFile(string fullName, EndianBinaryReader reader)
|
||||
{
|
||||
var fileName = Path.GetFileName(fullName);
|
||||
if (!assetsFileListHash.Contains(fileName.ToUpper()))
|
||||
if (!assetsFileListHash.Contains(fileName))
|
||||
{
|
||||
Logger.Info($"Loading {fileName}");
|
||||
try
|
||||
{
|
||||
var assetsFile = new SerializedFile(this, fullName, reader);
|
||||
assetsFileList.Add(assetsFile);
|
||||
assetsFileListHash.Add(assetsFile.upperFileName);
|
||||
assetsFileListHash.Add(assetsFile.fileName);
|
||||
|
||||
foreach (var sharedFile in assetsFile.m_Externals)
|
||||
{
|
||||
var sharedFilePath = Path.GetDirectoryName(fullName) + "\\" + sharedFile.fileName;
|
||||
var sharedFilePath = Path.Combine(Path.GetDirectoryName(fullName), sharedFile.fileName);
|
||||
var sharedFileName = sharedFile.fileName;
|
||||
|
||||
if (!importFilesHash.Contains(sharedFileName.ToUpper()))
|
||||
if (!importFilesHash.Contains(sharedFileName))
|
||||
{
|
||||
if (!File.Exists(sharedFilePath))
|
||||
{
|
||||
@@ -102,15 +104,15 @@ namespace AssetStudio
|
||||
if (File.Exists(sharedFilePath))
|
||||
{
|
||||
importFiles.Add(sharedFilePath);
|
||||
importFilesHash.Add(sharedFileName.ToUpper());
|
||||
importFilesHash.Add(sharedFileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Error($"Error while reading assets file {fileName}", e);
|
||||
reader.Dispose();
|
||||
//Logger.Error($"Unable to load assets file {fileName}");
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -121,8 +123,8 @@ namespace AssetStudio
|
||||
|
||||
private void LoadAssetsFromMemory(string fullName, EndianBinaryReader reader, string originalPath, string unityVersion = null)
|
||||
{
|
||||
var upperFileName = Path.GetFileName(fullName).ToUpper();
|
||||
if (!assetsFileListHash.Contains(upperFileName))
|
||||
var fileName = Path.GetFileName(fullName);
|
||||
if (!assetsFileListHash.Contains(fileName))
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -133,15 +135,12 @@ namespace AssetStudio
|
||||
assetsFile.SetVersion(unityVersion);
|
||||
}
|
||||
assetsFileList.Add(assetsFile);
|
||||
assetsFileListHash.Add(assetsFile.upperFileName);
|
||||
assetsFileListHash.Add(assetsFile.fileName);
|
||||
}
|
||||
catch
|
||||
catch (Exception e)
|
||||
{
|
||||
//Logger.Error($"Unable to load assets file {fileName} from {Path.GetFileName(originalPath)}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
resourceFileReaders.Add(upperFileName, reader);
|
||||
Logger.Error($"Error while reading assets file {fileName} from {Path.GetFileName(originalPath)}", e);
|
||||
resourceFileReaders.Add(fileName, reader);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -155,18 +154,26 @@ namespace AssetStudio
|
||||
var bundleFile = new BundleFile(reader, fullName);
|
||||
foreach (var file in bundleFile.fileList)
|
||||
{
|
||||
var dummyPath = Path.GetDirectoryName(fullName) + "\\" + file.fileName;
|
||||
LoadAssetsFromMemory(dummyPath, new EndianBinaryReader(file.stream), parentPath ?? fullName, bundleFile.versionEngine);
|
||||
var subReader = new EndianBinaryReader(file.stream);
|
||||
if (SerializedFile.IsSerializedFile(subReader))
|
||||
{
|
||||
var dummyPath = Path.GetDirectoryName(fullName) + Path.DirectorySeparatorChar + file.fileName;
|
||||
LoadAssetsFromMemory(dummyPath, subReader, parentPath ?? fullName, bundleFile.m_Header.unityRevision);
|
||||
}
|
||||
else
|
||||
{
|
||||
resourceFileReaders[file.fileName] = subReader; //TODO
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
catch (Exception e)
|
||||
{
|
||||
/*var str = $"Unable to load bundle file {fileName}";
|
||||
var str = $"Error while reading bundle file {fileName}";
|
||||
if (parentPath != null)
|
||||
{
|
||||
str += $" from {Path.GetFileName(parentPath)}";
|
||||
}
|
||||
Logger.Error(str);*/
|
||||
Logger.Error(str, e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -183,7 +190,7 @@ namespace AssetStudio
|
||||
var webFile = new WebFile(reader);
|
||||
foreach (var file in webFile.fileList)
|
||||
{
|
||||
var dummyPath = Path.GetDirectoryName(fullName) + "\\" + file.fileName;
|
||||
var dummyPath = Path.Combine(Path.GetDirectoryName(fullName), file.fileName);
|
||||
switch (CheckFileType(file.stream, out var fileReader))
|
||||
{
|
||||
case FileType.AssetsFile:
|
||||
@@ -195,12 +202,15 @@ namespace AssetStudio
|
||||
case FileType.WebFile:
|
||||
LoadWebFile(dummyPath, fileReader);
|
||||
break;
|
||||
case FileType.ResourceFile:
|
||||
resourceFileReaders[file.fileName] = fileReader; //TODO
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
catch (Exception e)
|
||||
{
|
||||
//Logger.Error($"Unable to load web file {fileName}");
|
||||
Logger.Error($"Error while reading web file {fileName}", e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -235,96 +245,113 @@ namespace AssetStudio
|
||||
Progress.Reset();
|
||||
foreach (var assetsFile in assetsFileList)
|
||||
{
|
||||
assetsFile.Objects = new Dictionary<long, Object>(assetsFile.m_Objects.Count);
|
||||
foreach (var objectInfo in assetsFile.m_Objects)
|
||||
{
|
||||
var objectReader = new ObjectReader(assetsFile.reader, assetsFile, objectInfo);
|
||||
switch (objectReader.type)
|
||||
try
|
||||
{
|
||||
case ClassIDType.Animation:
|
||||
assetsFile.Objects.Add(objectInfo.m_PathID, new Animation(objectReader));
|
||||
break;
|
||||
case ClassIDType.AnimationClip:
|
||||
assetsFile.Objects.Add(objectInfo.m_PathID, new AnimationClip(objectReader));
|
||||
break;
|
||||
case ClassIDType.Animator:
|
||||
assetsFile.Objects.Add(objectInfo.m_PathID, new Animator(objectReader));
|
||||
break;
|
||||
case ClassIDType.AnimatorController:
|
||||
assetsFile.Objects.Add(objectInfo.m_PathID, new AnimatorController(objectReader));
|
||||
break;
|
||||
case ClassIDType.AnimatorOverrideController:
|
||||
assetsFile.Objects.Add(objectInfo.m_PathID, new AnimatorOverrideController(objectReader));
|
||||
break;
|
||||
case ClassIDType.AssetBundle:
|
||||
assetsFile.Objects.Add(objectInfo.m_PathID, new AssetBundle(objectReader));
|
||||
break;
|
||||
case ClassIDType.AudioClip:
|
||||
assetsFile.Objects.Add(objectInfo.m_PathID, new AudioClip(objectReader));
|
||||
break;
|
||||
case ClassIDType.Avatar:
|
||||
assetsFile.Objects.Add(objectInfo.m_PathID, new Avatar(objectReader));
|
||||
break;
|
||||
case ClassIDType.Font:
|
||||
assetsFile.Objects.Add(objectInfo.m_PathID, new Font(objectReader));
|
||||
break;
|
||||
case ClassIDType.GameObject:
|
||||
assetsFile.Objects.Add(objectInfo.m_PathID, new GameObject(objectReader));
|
||||
break;
|
||||
case ClassIDType.Material:
|
||||
assetsFile.Objects.Add(objectInfo.m_PathID, new Material(objectReader));
|
||||
break;
|
||||
case ClassIDType.Mesh:
|
||||
assetsFile.Objects.Add(objectInfo.m_PathID, new Mesh(objectReader));
|
||||
break;
|
||||
case ClassIDType.MeshFilter:
|
||||
assetsFile.Objects.Add(objectInfo.m_PathID, new MeshFilter(objectReader));
|
||||
break;
|
||||
case ClassIDType.MeshRenderer:
|
||||
assetsFile.Objects.Add(objectInfo.m_PathID, new MeshRenderer(objectReader));
|
||||
break;
|
||||
case ClassIDType.MonoBehaviour:
|
||||
assetsFile.Objects.Add(objectInfo.m_PathID, new MonoBehaviour(objectReader));
|
||||
break;
|
||||
case ClassIDType.MonoScript:
|
||||
assetsFile.Objects.Add(objectInfo.m_PathID, new MonoScript(objectReader));
|
||||
break;
|
||||
case ClassIDType.MovieTexture:
|
||||
assetsFile.Objects.Add(objectInfo.m_PathID, new MovieTexture(objectReader));
|
||||
break;
|
||||
case ClassIDType.PlayerSettings:
|
||||
assetsFile.Objects.Add(objectInfo.m_PathID, new PlayerSettings(objectReader));
|
||||
break;
|
||||
case ClassIDType.RectTransform:
|
||||
assetsFile.Objects.Add(objectInfo.m_PathID, new RectTransform(objectReader));
|
||||
break;
|
||||
case ClassIDType.Shader:
|
||||
assetsFile.Objects.Add(objectInfo.m_PathID, new Shader(objectReader));
|
||||
break;
|
||||
case ClassIDType.SkinnedMeshRenderer:
|
||||
assetsFile.Objects.Add(objectInfo.m_PathID, new SkinnedMeshRenderer(objectReader));
|
||||
break;
|
||||
case ClassIDType.Sprite:
|
||||
assetsFile.Objects.Add(objectInfo.m_PathID, new Sprite(objectReader));
|
||||
break;
|
||||
case ClassIDType.SpriteAtlas:
|
||||
assetsFile.Objects.Add(objectInfo.m_PathID, new SpriteAtlas(objectReader));
|
||||
break;
|
||||
case ClassIDType.TextAsset:
|
||||
assetsFile.Objects.Add(objectInfo.m_PathID, new TextAsset(objectReader));
|
||||
break;
|
||||
case ClassIDType.Texture2D:
|
||||
assetsFile.Objects.Add(objectInfo.m_PathID, new Texture2D(objectReader));
|
||||
break;
|
||||
case ClassIDType.Transform:
|
||||
assetsFile.Objects.Add(objectInfo.m_PathID, new Transform(objectReader));
|
||||
break;
|
||||
case ClassIDType.VideoClip:
|
||||
assetsFile.Objects.Add(objectInfo.m_PathID, new VideoClip(objectReader));
|
||||
break;
|
||||
default:
|
||||
assetsFile.Objects.Add(objectInfo.m_PathID, new Object(objectReader));
|
||||
break;
|
||||
Object obj;
|
||||
switch (objectReader.type)
|
||||
{
|
||||
case ClassIDType.Animation:
|
||||
obj = new Animation(objectReader);
|
||||
break;
|
||||
case ClassIDType.AnimationClip:
|
||||
obj = new AnimationClip(objectReader);
|
||||
break;
|
||||
case ClassIDType.Animator:
|
||||
obj = new Animator(objectReader);
|
||||
break;
|
||||
case ClassIDType.AnimatorController:
|
||||
obj = new AnimatorController(objectReader);
|
||||
break;
|
||||
case ClassIDType.AnimatorOverrideController:
|
||||
obj = new AnimatorOverrideController(objectReader);
|
||||
break;
|
||||
case ClassIDType.AssetBundle:
|
||||
obj = new AssetBundle(objectReader);
|
||||
break;
|
||||
case ClassIDType.AudioClip:
|
||||
obj = new AudioClip(objectReader);
|
||||
break;
|
||||
case ClassIDType.Avatar:
|
||||
obj = new Avatar(objectReader);
|
||||
break;
|
||||
case ClassIDType.Font:
|
||||
obj = new Font(objectReader);
|
||||
break;
|
||||
case ClassIDType.GameObject:
|
||||
obj = new GameObject(objectReader);
|
||||
break;
|
||||
case ClassIDType.Material:
|
||||
obj = new Material(objectReader);
|
||||
break;
|
||||
case ClassIDType.Mesh:
|
||||
obj = new Mesh(objectReader);
|
||||
break;
|
||||
case ClassIDType.MeshFilter:
|
||||
obj = new MeshFilter(objectReader);
|
||||
break;
|
||||
case ClassIDType.MeshRenderer:
|
||||
obj = new MeshRenderer(objectReader);
|
||||
break;
|
||||
case ClassIDType.MonoBehaviour:
|
||||
obj = new MonoBehaviour(objectReader);
|
||||
break;
|
||||
case ClassIDType.MonoScript:
|
||||
obj = new MonoScript(objectReader);
|
||||
break;
|
||||
case ClassIDType.MovieTexture:
|
||||
obj = new MovieTexture(objectReader);
|
||||
break;
|
||||
case ClassIDType.PlayerSettings:
|
||||
obj = new PlayerSettings(objectReader);
|
||||
break;
|
||||
case ClassIDType.RectTransform:
|
||||
obj = new RectTransform(objectReader);
|
||||
break;
|
||||
case ClassIDType.Shader:
|
||||
obj = new Shader(objectReader);
|
||||
break;
|
||||
case ClassIDType.SkinnedMeshRenderer:
|
||||
obj = new SkinnedMeshRenderer(objectReader);
|
||||
break;
|
||||
case ClassIDType.Sprite:
|
||||
obj = new Sprite(objectReader);
|
||||
break;
|
||||
case ClassIDType.SpriteAtlas:
|
||||
obj = new SpriteAtlas(objectReader);
|
||||
break;
|
||||
case ClassIDType.TextAsset:
|
||||
obj = new TextAsset(objectReader);
|
||||
break;
|
||||
case ClassIDType.Texture2D:
|
||||
obj = new Texture2D(objectReader);
|
||||
break;
|
||||
case ClassIDType.Transform:
|
||||
obj = new Transform(objectReader);
|
||||
break;
|
||||
case ClassIDType.VideoClip:
|
||||
obj = new VideoClip(objectReader);
|
||||
break;
|
||||
case ClassIDType.ResourceManager:
|
||||
obj = new ResourceManager(objectReader);
|
||||
break;
|
||||
default:
|
||||
obj = new Object(objectReader);
|
||||
break;
|
||||
}
|
||||
assetsFile.AddObject(obj);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine("Unable to load object")
|
||||
.AppendLine($"Assets {assetsFile.fileName}")
|
||||
.AppendLine($"Type {objectReader.type}")
|
||||
.AppendLine($"PathID {objectInfo.m_PathID}")
|
||||
.Append(e);
|
||||
Logger.Error(sb.ToString());
|
||||
}
|
||||
|
||||
Progress.Report(++i, progressCount);
|
||||
@@ -332,13 +359,13 @@ namespace AssetStudio
|
||||
}
|
||||
}
|
||||
|
||||
private void ProcessGameObject()
|
||||
private void ProcessAssets()
|
||||
{
|
||||
Logger.Info("Process GameObject...");
|
||||
Logger.Info("Process Assets...");
|
||||
|
||||
foreach (var assetsFile in assetsFileList)
|
||||
{
|
||||
foreach (var obj in assetsFile.Objects.Values)
|
||||
foreach (var obj in assetsFile.Objects)
|
||||
{
|
||||
if (obj is GameObject m_GameObject)
|
||||
{
|
||||
@@ -370,6 +397,19 @@ namespace AssetStudio
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (obj is SpriteAtlas m_SpriteAtlas)
|
||||
{
|
||||
foreach (var m_PackedSprite in m_SpriteAtlas.m_PackedSprites)
|
||||
{
|
||||
if (m_PackedSprite.TryGet(out var m_Sprite))
|
||||
{
|
||||
if (m_Sprite.m_SpriteAtlas.IsNull)
|
||||
{
|
||||
m_Sprite.m_SpriteAtlas.Set(m_SpriteAtlas);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace AssetStudio
|
||||
{
|
||||
public enum BuildTarget
|
||||
{
|
||||
UnknownPlatform = 3716,
|
||||
NoTarget = -2,
|
||||
DashboardWidget = 1,
|
||||
StandaloneOSX = 2,
|
||||
StandaloneOSXPPC = 3,
|
||||
@@ -42,6 +42,12 @@ namespace AssetStudio
|
||||
WiiU,
|
||||
tvOS,
|
||||
Switch,
|
||||
NoTarget = -2
|
||||
Lumin,
|
||||
Stadia,
|
||||
CloudRendering,
|
||||
GameCoreXboxSeries,
|
||||
GameCoreXboxOne,
|
||||
PS5,
|
||||
UnknownPlatform = 9999
|
||||
}
|
||||
}
|
||||
|
||||
+262
-194
@@ -1,246 +1,314 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Lz4;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public class StreamFile
|
||||
{
|
||||
public string fileName;
|
||||
public Stream stream;
|
||||
}
|
||||
|
||||
public class BlockInfo
|
||||
{
|
||||
public uint compressedSize;
|
||||
public uint uncompressedSize;
|
||||
public short flag;
|
||||
}
|
||||
|
||||
public class BundleFile
|
||||
{
|
||||
private string path;
|
||||
public string versionPlayer;
|
||||
public string versionEngine;
|
||||
public List<StreamFile> fileList = new List<StreamFile>();
|
||||
|
||||
public BundleFile(EndianBinaryReader bundleReader, string path)
|
||||
public class Header
|
||||
{
|
||||
this.path = path;
|
||||
var signature = bundleReader.ReadStringToNull();
|
||||
switch (signature)
|
||||
public string signature;
|
||||
public uint version;
|
||||
public string unityVersion;
|
||||
public string unityRevision;
|
||||
public long size;
|
||||
public uint compressedBlocksInfoSize;
|
||||
public uint uncompressedBlocksInfoSize;
|
||||
public uint flags;
|
||||
}
|
||||
|
||||
public class StorageBlock
|
||||
{
|
||||
public uint compressedSize;
|
||||
public uint uncompressedSize;
|
||||
public ushort flags;
|
||||
}
|
||||
|
||||
public class Node
|
||||
{
|
||||
public long offset;
|
||||
public long size;
|
||||
public uint flags;
|
||||
public string path;
|
||||
}
|
||||
|
||||
public Header m_Header;
|
||||
private StorageBlock[] m_BlocksInfo;
|
||||
private Node[] m_DirectoryInfo;
|
||||
|
||||
public StreamFile[] fileList;
|
||||
|
||||
public BundleFile(EndianBinaryReader reader, string path)
|
||||
{
|
||||
m_Header = new Header();
|
||||
m_Header.signature = reader.ReadStringToNull();
|
||||
m_Header.version = reader.ReadUInt32();
|
||||
m_Header.unityVersion = reader.ReadStringToNull();
|
||||
m_Header.unityRevision = reader.ReadStringToNull();
|
||||
switch (m_Header.signature)
|
||||
{
|
||||
case "UnityArchive":
|
||||
break; //TODO
|
||||
case "UnityWeb":
|
||||
case "UnityRaw":
|
||||
case "\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA":
|
||||
if (m_Header.version == 6)
|
||||
{
|
||||
var format = bundleReader.ReadInt32();
|
||||
versionPlayer = bundleReader.ReadStringToNull();
|
||||
versionEngine = bundleReader.ReadStringToNull();
|
||||
if (format < 6)
|
||||
{
|
||||
int bundleSize = bundleReader.ReadInt32();
|
||||
}
|
||||
else if (format == 6)
|
||||
{
|
||||
ReadFormat6(bundleReader, true);
|
||||
return;
|
||||
}
|
||||
short dummy2 = bundleReader.ReadInt16();
|
||||
int offset = bundleReader.ReadInt16();
|
||||
int dummy3 = bundleReader.ReadInt32();
|
||||
int lzmaChunks = bundleReader.ReadInt32();
|
||||
|
||||
int lzmaSize = 0;
|
||||
long streamSize = 0;
|
||||
|
||||
for (int i = 0; i < lzmaChunks; i++)
|
||||
{
|
||||
lzmaSize = bundleReader.ReadInt32();
|
||||
streamSize = bundleReader.ReadInt32();
|
||||
}
|
||||
|
||||
bundleReader.Position = offset;
|
||||
switch (signature)
|
||||
{
|
||||
case "\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA": //.bytes
|
||||
case "UnityWeb":
|
||||
{
|
||||
var lzmaBuffer = bundleReader.ReadBytes(lzmaSize);
|
||||
using (var lzmaStream = new EndianBinaryReader(SevenZipHelper.StreamDecompress(new MemoryStream(lzmaBuffer))))
|
||||
{
|
||||
GetAssetsFiles(lzmaStream, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "UnityRaw":
|
||||
{
|
||||
GetAssetsFiles(bundleReader, offset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
goto case "UnityFS";
|
||||
}
|
||||
ReadHeaderAndBlocksInfo(reader);
|
||||
using (var blocksStream = CreateBlocksStream(path))
|
||||
{
|
||||
ReadBlocksAndDirectory(reader, blocksStream);
|
||||
ReadFiles(blocksStream, path);
|
||||
}
|
||||
break;
|
||||
case "UnityFS":
|
||||
ReadHeader(reader);
|
||||
ReadBlocksInfoAndDirectory(reader);
|
||||
using (var blocksStream = CreateBlocksStream(path))
|
||||
{
|
||||
var format = bundleReader.ReadInt32();
|
||||
versionPlayer = bundleReader.ReadStringToNull();
|
||||
versionEngine = bundleReader.ReadStringToNull();
|
||||
if (format == 6)
|
||||
{
|
||||
ReadFormat6(bundleReader);
|
||||
}
|
||||
break;
|
||||
ReadBlocks(reader, blocksStream);
|
||||
ReadFiles(blocksStream, path);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void GetAssetsFiles(EndianBinaryReader reader, int offset)
|
||||
private void ReadHeaderAndBlocksInfo(EndianBinaryReader reader)
|
||||
{
|
||||
int fileCount = reader.ReadInt32();
|
||||
for (int i = 0; i < fileCount; i++)
|
||||
var isCompressed = m_Header.signature == "UnityWeb";
|
||||
if (m_Header.version >= 4)
|
||||
{
|
||||
var file = new StreamFile();
|
||||
file.fileName = Path.GetFileName(reader.ReadStringToNull());
|
||||
int fileOffset = reader.ReadInt32();
|
||||
fileOffset += offset;
|
||||
int fileSize = reader.ReadInt32();
|
||||
long nextFile = reader.Position;
|
||||
reader.Position = fileOffset;
|
||||
var buffer = reader.ReadBytes(fileSize);
|
||||
file.stream = new MemoryStream(buffer);
|
||||
fileList.Add(file);
|
||||
reader.Position = nextFile;
|
||||
var hash = reader.ReadBytes(16);
|
||||
var crc = reader.ReadUInt32();
|
||||
}
|
||||
var minimumStreamedBytes = reader.ReadUInt32();
|
||||
m_Header.size = reader.ReadUInt32();
|
||||
var numberOfLevelsToDownloadBeforeStreaming = reader.ReadUInt32();
|
||||
var levelCount = reader.ReadInt32();
|
||||
m_BlocksInfo = new StorageBlock[1];
|
||||
for (int i = 0; i < levelCount; i++)
|
||||
{
|
||||
var storageBlock = new StorageBlock()
|
||||
{
|
||||
compressedSize = reader.ReadUInt32(),
|
||||
uncompressedSize = reader.ReadUInt32(),
|
||||
flags = (ushort)(isCompressed ? 1 : 0)
|
||||
};
|
||||
if (i == levelCount - 1)
|
||||
{
|
||||
m_BlocksInfo[0] = storageBlock;
|
||||
}
|
||||
}
|
||||
if (m_Header.version >= 2)
|
||||
{
|
||||
var completeFileSize = reader.ReadUInt32();
|
||||
}
|
||||
if (m_Header.version >= 3)
|
||||
{
|
||||
var fileInfoHeaderSize = reader.ReadUInt32();
|
||||
}
|
||||
reader.Position = m_Header.size;
|
||||
}
|
||||
|
||||
private void ReadFormat6(EndianBinaryReader bundleReader, bool padding = false)
|
||||
private Stream CreateBlocksStream(string path)
|
||||
{
|
||||
var bundleSize = bundleReader.ReadInt64();
|
||||
int compressedSize = bundleReader.ReadInt32();
|
||||
int uncompressedSize = bundleReader.ReadInt32();
|
||||
int flag = bundleReader.ReadInt32();
|
||||
if (padding)
|
||||
bundleReader.ReadByte();
|
||||
byte[] blocksInfoBytes;
|
||||
if ((flag & 0x80) != 0)//at end of file
|
||||
Stream blocksStream;
|
||||
var uncompressedSizeSum = m_BlocksInfo.Sum(x => x.uncompressedSize);
|
||||
if (uncompressedSizeSum >= int.MaxValue)
|
||||
{
|
||||
var position = bundleReader.Position;
|
||||
bundleReader.Position = bundleReader.BaseStream.Length - compressedSize;
|
||||
blocksInfoBytes = bundleReader.ReadBytes(compressedSize);
|
||||
bundleReader.Position = position;
|
||||
/*var memoryMappedFile = MemoryMappedFile.CreateNew(Path.GetFileName(path), uncompressedSizeSum);
|
||||
assetsDataStream = memoryMappedFile.CreateViewStream();*/
|
||||
blocksStream = new FileStream(path + ".temp", FileMode.Create, FileAccess.ReadWrite, FileShare.None, 4096, FileOptions.DeleteOnClose);
|
||||
}
|
||||
else
|
||||
{
|
||||
blocksInfoBytes = bundleReader.ReadBytes(compressedSize);
|
||||
blocksStream = new MemoryStream((int)uncompressedSizeSum);
|
||||
}
|
||||
MemoryStream blocksInfoStream;
|
||||
switch (flag & 0x3F)
|
||||
return blocksStream;
|
||||
}
|
||||
|
||||
private void ReadBlocksAndDirectory(EndianBinaryReader reader, Stream blocksStream)
|
||||
{
|
||||
foreach (var blockInfo in m_BlocksInfo)
|
||||
{
|
||||
default://None
|
||||
var uncompressedBytes = reader.ReadBytes((int)blockInfo.compressedSize);
|
||||
if (blockInfo.flags == 1)
|
||||
{
|
||||
using (var memoryStream = new MemoryStream(uncompressedBytes))
|
||||
{
|
||||
blocksInfoStream = new MemoryStream(blocksInfoBytes);
|
||||
break;
|
||||
}
|
||||
case 1://LZMA
|
||||
{
|
||||
blocksInfoStream = SevenZipHelper.StreamDecompress(new MemoryStream(blocksInfoBytes));
|
||||
break;
|
||||
}
|
||||
case 2://LZ4
|
||||
case 3://LZ4HC
|
||||
{
|
||||
byte[] uncompressedBytes = new byte[uncompressedSize];
|
||||
using (var decoder = new Lz4DecoderStream(new MemoryStream(blocksInfoBytes)))
|
||||
using (var decompressStream = SevenZipHelper.StreamDecompress(memoryStream))
|
||||
{
|
||||
decoder.Read(uncompressedBytes, 0, uncompressedSize);
|
||||
uncompressedBytes = decompressStream.ToArray();
|
||||
}
|
||||
blocksInfoStream = new MemoryStream(uncompressedBytes);
|
||||
break;
|
||||
}
|
||||
//case 4:LZHAM?
|
||||
}
|
||||
using (var blocksInfoReader = new EndianBinaryReader(blocksInfoStream))
|
||||
{
|
||||
blocksInfoReader.Position = 0x10;
|
||||
int blockcount = blocksInfoReader.ReadInt32();
|
||||
var blockInfos = new BlockInfo[blockcount];
|
||||
for (int i = 0; i < blockcount; i++)
|
||||
{
|
||||
blockInfos[i] = new BlockInfo
|
||||
{
|
||||
uncompressedSize = blocksInfoReader.ReadUInt32(),
|
||||
compressedSize = blocksInfoReader.ReadUInt32(),
|
||||
flag = blocksInfoReader.ReadInt16()
|
||||
};
|
||||
}
|
||||
Stream dataStream;
|
||||
var uncompressedSizeSum = blockInfos.Sum(x => x.uncompressedSize);
|
||||
if (uncompressedSizeSum > int.MaxValue)
|
||||
blocksStream.Write(uncompressedBytes, 0, uncompressedBytes.Length);
|
||||
}
|
||||
blocksStream.Position = 0;
|
||||
var blocksReader = new EndianBinaryReader(blocksStream);
|
||||
var nodesCount = blocksReader.ReadInt32();
|
||||
m_DirectoryInfo = new Node[nodesCount];
|
||||
for (int i = 0; i < nodesCount; i++)
|
||||
{
|
||||
m_DirectoryInfo[i] = new Node
|
||||
{
|
||||
/*var memoryMappedFile = MemoryMappedFile.CreateNew(Path.GetFileName(path), uncompressedSizeSum);
|
||||
assetsDataStream = memoryMappedFile.CreateViewStream();*/
|
||||
dataStream = new FileStream(path + ".temp", FileMode.Create, FileAccess.ReadWrite, FileShare.None, 4096, FileOptions.DeleteOnClose);
|
||||
path = blocksReader.ReadStringToNull(),
|
||||
offset = blocksReader.ReadUInt32(),
|
||||
size = blocksReader.ReadUInt32()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public void ReadFiles(Stream blocksStream, string path)
|
||||
{
|
||||
fileList = new StreamFile[m_DirectoryInfo.Length];
|
||||
for (int i = 0; i < m_DirectoryInfo.Length; i++)
|
||||
{
|
||||
var node = m_DirectoryInfo[i];
|
||||
var file = new StreamFile();
|
||||
fileList[i] = file;
|
||||
file.path = node.path;
|
||||
file.fileName = Path.GetFileName(node.path);
|
||||
if (node.size >= int.MaxValue)
|
||||
{
|
||||
/*var memoryMappedFile = MemoryMappedFile.CreateNew(file.fileName, entryinfo_size);
|
||||
file.stream = memoryMappedFile.CreateViewStream();*/
|
||||
var extractPath = path + "_unpacked" + Path.DirectorySeparatorChar;
|
||||
Directory.CreateDirectory(extractPath);
|
||||
file.stream = new FileStream(extractPath + file.fileName, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite);
|
||||
}
|
||||
else
|
||||
{
|
||||
dataStream = new MemoryStream();
|
||||
file.stream = new MemoryStream((int)node.size);
|
||||
}
|
||||
foreach (var blockInfo in blockInfos)
|
||||
{
|
||||
switch (blockInfo.flag & 0x3F)
|
||||
blocksStream.Position = node.offset;
|
||||
blocksStream.CopyTo(file.stream, node.size);
|
||||
file.stream.Position = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void ReadHeader(EndianBinaryReader reader)
|
||||
{
|
||||
m_Header.size = reader.ReadInt64();
|
||||
m_Header.compressedBlocksInfoSize = reader.ReadUInt32();
|
||||
m_Header.uncompressedBlocksInfoSize = reader.ReadUInt32();
|
||||
m_Header.flags = reader.ReadUInt32();
|
||||
if (m_Header.signature != "UnityFS")
|
||||
{
|
||||
reader.ReadByte();
|
||||
}
|
||||
}
|
||||
|
||||
private void ReadBlocksInfoAndDirectory(EndianBinaryReader reader)
|
||||
{
|
||||
byte[] blocksInfoBytes;
|
||||
if (m_Header.version >= 7)
|
||||
{
|
||||
reader.AlignStream(16);
|
||||
}
|
||||
if ((m_Header.flags & 0x80) != 0) //kArchiveBlocksInfoAtTheEnd
|
||||
{
|
||||
var position = reader.Position;
|
||||
reader.Position = reader.BaseStream.Length - m_Header.compressedBlocksInfoSize;
|
||||
blocksInfoBytes = reader.ReadBytes((int)m_Header.compressedBlocksInfoSize);
|
||||
reader.Position = position;
|
||||
}
|
||||
else //0x40 kArchiveBlocksAndDirectoryInfoCombined
|
||||
{
|
||||
blocksInfoBytes = reader.ReadBytes((int)m_Header.compressedBlocksInfoSize);
|
||||
}
|
||||
var blocksInfoCompressedStream = new MemoryStream(blocksInfoBytes);
|
||||
MemoryStream blocksInfoUncompresseddStream;
|
||||
switch (m_Header.flags & 0x3F) //kArchiveCompressionTypeMask
|
||||
{
|
||||
default: //None
|
||||
{
|
||||
default://None
|
||||
{
|
||||
bundleReader.BaseStream.CopyTo(dataStream, blockInfo.compressedSize);
|
||||
break;
|
||||
}
|
||||
case 1://LZMA
|
||||
{
|
||||
SevenZipHelper.StreamDecompress(bundleReader.BaseStream, dataStream, blockInfo.compressedSize, blockInfo.uncompressedSize);
|
||||
break;
|
||||
}
|
||||
case 2://LZ4
|
||||
case 3://LZ4HC
|
||||
{
|
||||
var lz4Stream = new Lz4DecoderStream(bundleReader.BaseStream, blockInfo.compressedSize);
|
||||
lz4Stream.CopyTo(dataStream, blockInfo.uncompressedSize);
|
||||
break;
|
||||
}
|
||||
//case 4:LZHAM?
|
||||
blocksInfoUncompresseddStream = blocksInfoCompressedStream;
|
||||
break;
|
||||
}
|
||||
case 1: //LZMA
|
||||
{
|
||||
blocksInfoUncompresseddStream = new MemoryStream((int)(m_Header.uncompressedBlocksInfoSize));
|
||||
SevenZipHelper.StreamDecompress(blocksInfoCompressedStream, blocksInfoUncompresseddStream, m_Header.compressedBlocksInfoSize, m_Header.uncompressedBlocksInfoSize);
|
||||
blocksInfoUncompresseddStream.Position = 0;
|
||||
blocksInfoCompressedStream.Close();
|
||||
break;
|
||||
}
|
||||
case 2: //LZ4
|
||||
case 3: //LZ4HC
|
||||
{
|
||||
var uncompressedBytes = new byte[m_Header.uncompressedBlocksInfoSize];
|
||||
using (var decoder = new Lz4DecoderStream(blocksInfoCompressedStream))
|
||||
{
|
||||
decoder.Read(uncompressedBytes, 0, uncompressedBytes.Length);
|
||||
}
|
||||
blocksInfoUncompresseddStream = new MemoryStream(uncompressedBytes);
|
||||
break;
|
||||
}
|
||||
}
|
||||
using (var blocksInfoReader = new EndianBinaryReader(blocksInfoUncompresseddStream))
|
||||
{
|
||||
var uncompressedDataHash = blocksInfoReader.ReadBytes(16);
|
||||
var blocksInfoCount = blocksInfoReader.ReadInt32();
|
||||
m_BlocksInfo = new StorageBlock[blocksInfoCount];
|
||||
for (int i = 0; i < blocksInfoCount; i++)
|
||||
{
|
||||
m_BlocksInfo[i] = new StorageBlock
|
||||
{
|
||||
uncompressedSize = blocksInfoReader.ReadUInt32(),
|
||||
compressedSize = blocksInfoReader.ReadUInt32(),
|
||||
flags = blocksInfoReader.ReadUInt16()
|
||||
};
|
||||
}
|
||||
dataStream.Position = 0;
|
||||
using (dataStream)
|
||||
|
||||
var nodesCount = blocksInfoReader.ReadInt32();
|
||||
m_DirectoryInfo = new Node[nodesCount];
|
||||
for (int i = 0; i < nodesCount; i++)
|
||||
{
|
||||
var entryinfo_count = blocksInfoReader.ReadInt32();
|
||||
for (int i = 0; i < entryinfo_count; i++)
|
||||
m_DirectoryInfo[i] = new Node
|
||||
{
|
||||
var file = new StreamFile();
|
||||
var entryinfo_offset = blocksInfoReader.ReadInt64();
|
||||
var entryinfo_size = blocksInfoReader.ReadInt64();
|
||||
flag = blocksInfoReader.ReadInt32();
|
||||
file.fileName = Path.GetFileName(blocksInfoReader.ReadStringToNull());
|
||||
if (entryinfo_size > int.MaxValue)
|
||||
{
|
||||
/*var memoryMappedFile = MemoryMappedFile.CreateNew(file.fileName, entryinfo_size);
|
||||
file.stream = memoryMappedFile.CreateViewStream();*/
|
||||
var extractPath = path + "_unpacked\\";
|
||||
Directory.CreateDirectory(extractPath);
|
||||
file.stream = File.Create(extractPath + file.fileName);
|
||||
}
|
||||
else
|
||||
{
|
||||
file.stream = new MemoryStream();
|
||||
}
|
||||
dataStream.Position = entryinfo_offset;
|
||||
dataStream.CopyTo(file.stream, entryinfo_size);
|
||||
file.stream.Position = 0;
|
||||
fileList.Add(file);
|
||||
}
|
||||
offset = blocksInfoReader.ReadInt64(),
|
||||
size = blocksInfoReader.ReadInt64(),
|
||||
flags = blocksInfoReader.ReadUInt32(),
|
||||
path = blocksInfoReader.ReadStringToNull(),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ReadBlocks(EndianBinaryReader reader, Stream blocksStream)
|
||||
{
|
||||
foreach (var blockInfo in m_BlocksInfo)
|
||||
{
|
||||
switch (blockInfo.flags & 0x3F) //kStorageBlockCompressionTypeMask
|
||||
{
|
||||
default: //None
|
||||
{
|
||||
reader.BaseStream.CopyTo(blocksStream, blockInfo.compressedSize);
|
||||
break;
|
||||
}
|
||||
case 1: //LZMA
|
||||
{
|
||||
SevenZipHelper.StreamDecompress(reader.BaseStream, blocksStream, blockInfo.compressedSize, blockInfo.uncompressedSize);
|
||||
break;
|
||||
}
|
||||
case 2: //LZ4
|
||||
case 3: //LZ4HC
|
||||
{
|
||||
var compressedStream = new MemoryStream(reader.ReadBytes((int)blockInfo.compressedSize));
|
||||
using (var lz4Stream = new Lz4DecoderStream(compressedStream))
|
||||
{
|
||||
lz4Stream.CopyTo(blocksStream, blockInfo.uncompressedSize);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
blocksStream.Position = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+103
-10
@@ -1,4 +1,5 @@
|
||||
namespace AssetStudio
|
||||
// official Class ID Reference: https://docs.unity3d.com/Manual/ClassIDReference.html
|
||||
namespace AssetStudio
|
||||
{
|
||||
public enum ClassIDType
|
||||
{
|
||||
@@ -26,7 +27,7 @@
|
||||
ParticleRenderer = 26,
|
||||
Texture = 27,
|
||||
Texture2D = 28,
|
||||
SceneSettings = 29,
|
||||
OcclusionCullingSettings = 29,
|
||||
GraphicsSettings = 30,
|
||||
MeshFilter = 33,
|
||||
OcclusionPortal = 41,
|
||||
@@ -49,7 +50,7 @@
|
||||
PhysicsMaterial2D = 62,
|
||||
MeshCollider = 64,
|
||||
BoxCollider = 65,
|
||||
SpriteCollider2D = 66,
|
||||
CompositeCollider2D = 66,
|
||||
EdgeCollider2D = 68,
|
||||
CapsuleCollider2D = 70,
|
||||
ComputeShader = 72,
|
||||
@@ -92,6 +93,7 @@
|
||||
FlareLayer = 124,
|
||||
HaloLayer = 125,
|
||||
NavMeshAreas = 126,
|
||||
NavMeshProjectSettings = 126,
|
||||
HaloManager = 127,
|
||||
Font = 128,
|
||||
PlayerSettings = 129,
|
||||
@@ -158,7 +160,7 @@
|
||||
BlendTree = 206,
|
||||
Motion = 207,
|
||||
NavMeshObstacle = 208,
|
||||
TerrainInstance = 210,
|
||||
SortingGroup = 210,
|
||||
SpriteRenderer = 212,
|
||||
Sprite = 213,
|
||||
CachedSpriteAtlas = 214,
|
||||
@@ -216,15 +218,19 @@
|
||||
PerformanceReportingManager = 305,
|
||||
UnityConnectSettings = 310,
|
||||
AvatarMask = 319,
|
||||
PlayableDirector = 320,
|
||||
VideoPlayer = 328,
|
||||
VideoClip = 329,
|
||||
ParticleSystemForceField = 330,
|
||||
SpriteMask = 331,
|
||||
WorldAnchor = 362,
|
||||
OcclusionCullingData = 363,
|
||||
//kLargestRuntimeClassID = 364
|
||||
SmallestEditorClassID = 1000,
|
||||
Prefab = 1001,
|
||||
PrefabInstance = 1001,
|
||||
EditorExtensionImpl = 1002,
|
||||
AssetImporter = 1003,
|
||||
AssetDatabase = 1004,
|
||||
AssetDatabaseV1 = 1004,
|
||||
Mesh3DSImporter = 1005,
|
||||
TextureImporter = 1006,
|
||||
ShaderImporter = 1007,
|
||||
@@ -259,13 +265,13 @@
|
||||
AnimatorState = 1102,
|
||||
HumanTemplate = 1105,
|
||||
AnimatorStateMachine = 1107,
|
||||
PreviewAssetType = 1108,
|
||||
PreviewAnimationClip = 1108,
|
||||
AnimatorTransition = 1109,
|
||||
SpeedTreeImporter = 1110,
|
||||
AnimatorTransitionBase = 1111,
|
||||
SubstanceImporter = 1112,
|
||||
LightmapParameters = 1113,
|
||||
LightmapSnapshot = 1120,
|
||||
LightingDataAsset = 1120,
|
||||
GISRaster = 1121,
|
||||
GISRasterImporter = 1122,
|
||||
CadImporter = 1123,
|
||||
@@ -276,11 +282,98 @@
|
||||
ActivationLogComponent = 2000,
|
||||
//kLargestEditorClassID = 2001
|
||||
//kClassIdOutOfHierarchy = 100000
|
||||
SubDerived = 367388927,
|
||||
//int = 100000,
|
||||
//bool = 100001,
|
||||
//float = 100002,
|
||||
MonoObject = 100003,
|
||||
Collision = 100004,
|
||||
Vector3f = 100005,
|
||||
RootMotionData = 100006,
|
||||
Collision2D = 100007,
|
||||
AudioMixerLiveUpdateFloat = 100008,
|
||||
AudioMixerLiveUpdateBool = 100009,
|
||||
Polygon2D = 100010,
|
||||
//void = 100011,
|
||||
TilemapCollider2D = 19719996,
|
||||
AssetImporterLog = 41386430,
|
||||
VFXRenderer = 73398921,
|
||||
SerializableManagedRefTestClass = 76251197,
|
||||
Grid = 156049354,
|
||||
ScenesUsingAssets = 156483287,
|
||||
ArticulationBody = 171741748,
|
||||
Preset = 181963792,
|
||||
EmptyObject = 277625683,
|
||||
IConstraint = 285090594,
|
||||
TestObjectWithSpecialLayoutOne = 293259124,
|
||||
AssemblyDefinitionReferenceImporter = 294290339,
|
||||
SiblingDerived = 334799969,
|
||||
TestObjectWithSerializedMapStringNonAlignedStruct = 342846651,
|
||||
SubDerived = 367388927,
|
||||
AssetImportInProgressProxy = 369655926,
|
||||
PluginBuildInfo = 382020655,
|
||||
EditorProjectAccess = 426301858,
|
||||
PrefabImporter = 468431735,
|
||||
TestObjectWithSerializedArray = 478637458,
|
||||
TestObjectWithSerializedAnimationCurve = 478637459,
|
||||
TilemapRenderer = 483693784,
|
||||
ScriptableCamera = 488575907,
|
||||
SpriteAtlasAsset = 612988286,
|
||||
SpriteAtlasDatabase = 638013454,
|
||||
AudioBuildInfo = 641289076,
|
||||
CachedSpriteAtlasRuntimeData = 644342135,
|
||||
RendererFake = 646504946,
|
||||
AssemblyDefinitionReferenceAsset = 662584278,
|
||||
BuiltAssetBundleInfoSet = 668709126,
|
||||
SpriteAtlas = 687078895,
|
||||
RayTracingShaderImporter = 747330370,
|
||||
RayTracingShader = 825902497,
|
||||
LightingSettings = 850595691,
|
||||
PlatformModuleSetup = 877146078,
|
||||
VersionControlSettings = 890905787,
|
||||
AimConstraint = 895512359,
|
||||
VFXManager = 937362698,
|
||||
VisualEffectSubgraph = 994735392,
|
||||
VisualEffectSubgraphOperator = 994735403,
|
||||
VisualEffectSubgraphBlock = 994735404,
|
||||
LocalizationImporter = 1027052791,
|
||||
Derived = 1091556383,
|
||||
PropertyModificationsTargetTestObject = 1111377672,
|
||||
ReferencesArtifactGenerator = 1114811875,
|
||||
AssemblyDefinitionAsset = 1152215463,
|
||||
SceneVisibilityState = 1154873562,
|
||||
LookAtConstraint = 1183024399,
|
||||
SpriteAtlasImporter = 1210832254,
|
||||
MultiArtifactTestImporter = 1223240404,
|
||||
GameObjectRecorder = 1268269756,
|
||||
LightingDataAssetParent = 1325145578,
|
||||
PresetManager = 1386491679,
|
||||
TestObjectWithSpecialLayoutTwo = 1392443030,
|
||||
StreamingManager = 1403656975,
|
||||
LowerResBlitTexture = 1480428607,
|
||||
RenderPassAttachment = 1571458007
|
||||
StreamingController = 1542919678,
|
||||
RenderPassAttachment = 1571458007,
|
||||
TestObjectVectorPairStringBool = 1628831178,
|
||||
GridLayout = 1742807556,
|
||||
AssemblyDefinitionImporter = 1766753193,
|
||||
ParentConstraint = 1773428102,
|
||||
FakeComponent = 1803986026,
|
||||
PositionConstraint = 1818360608,
|
||||
RotationConstraint = 1818360609,
|
||||
ScaleConstraint = 1818360610,
|
||||
Tilemap = 1839735485,
|
||||
PackageManifest = 1896753125,
|
||||
PackageManifestImporter = 1896753126,
|
||||
TerrainLayer = 1953259897,
|
||||
SpriteShapeRenderer = 1971053207,
|
||||
NativeObjectType = 1977754360,
|
||||
TestObjectWithSerializedMapStringBool = 1981279845,
|
||||
SerializableManagedHost = 1995898324,
|
||||
VisualEffectAsset = 2058629509,
|
||||
VisualEffectImporter = 2058629510,
|
||||
VisualEffectResource = 2058629511,
|
||||
VisualEffectObject = 2059678085,
|
||||
VisualEffect = 2083052967,
|
||||
LocalizationAsset = 2083778819,
|
||||
ScriptedImporter = 2089858483
|
||||
}
|
||||
}
|
||||
|
||||
@@ -292,7 +292,7 @@ namespace AssetStudio
|
||||
public AnimationCurve<float> curve;
|
||||
public string attribute;
|
||||
public string path;
|
||||
public int classID;
|
||||
public ClassIDType classID;
|
||||
public PPtr<MonoScript> script;
|
||||
|
||||
|
||||
@@ -301,7 +301,7 @@ namespace AssetStudio
|
||||
curve = new AnimationCurve<float>(reader, reader.ReadSingle);
|
||||
attribute = reader.ReadAlignedString();
|
||||
path = reader.ReadAlignedString();
|
||||
classID = reader.ReadInt32();
|
||||
classID = (ClassIDType)reader.ReadInt32();
|
||||
script = new PPtr<MonoScript>(reader);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,9 +27,9 @@ namespace AssetStudio
|
||||
public AudioCompressionFormat m_CompressionFormat;
|
||||
|
||||
public string m_Source;
|
||||
public long m_Offset;
|
||||
public ulong m_Offset;
|
||||
public long m_Size;
|
||||
public Lazy<byte[]> m_AudioData;
|
||||
public ResourceReader m_AudioData;
|
||||
|
||||
public AudioClip(ObjectReader reader) : base(reader)
|
||||
{
|
||||
@@ -48,7 +48,7 @@ namespace AssetStudio
|
||||
var tsize = m_Size % 4 != 0 ? m_Size + 4 - m_Size % 4 : m_Size;
|
||||
if (reader.byteSize + reader.byteStart - reader.Position != tsize)
|
||||
{
|
||||
m_Offset = reader.ReadInt32();
|
||||
m_Offset = reader.ReadUInt32();
|
||||
m_Source = assetsFile.fullName + ".resS";
|
||||
}
|
||||
}
|
||||
@@ -72,8 +72,9 @@ namespace AssetStudio
|
||||
m_Legacy3D = reader.ReadBoolean();
|
||||
reader.AlignStream();
|
||||
|
||||
//StreamedResource m_Resource
|
||||
m_Source = reader.ReadAlignedString();
|
||||
m_Offset = reader.ReadInt64();
|
||||
m_Offset = reader.ReadUInt64();
|
||||
m_Size = reader.ReadInt64();
|
||||
m_CompressionFormat = (AudioCompressionFormat)reader.ReadInt32();
|
||||
}
|
||||
@@ -87,7 +88,7 @@ namespace AssetStudio
|
||||
{
|
||||
resourceReader = new ResourceReader(reader, reader.BaseStream.Position, (int)m_Size);
|
||||
}
|
||||
m_AudioData = new Lazy<byte[]>(resourceReader.GetData);
|
||||
m_AudioData = resourceReader;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,11 +19,14 @@ namespace AssetStudio
|
||||
public class UnityPropertySheet
|
||||
{
|
||||
public KeyValuePair<string, UnityTexEnv>[] m_TexEnvs;
|
||||
public KeyValuePair<string, int>[] m_Ints;
|
||||
public KeyValuePair<string, float>[] m_Floats;
|
||||
public KeyValuePair<string, Color>[] m_Colors;
|
||||
|
||||
public UnityPropertySheet(ObjectReader reader)
|
||||
{
|
||||
var version = reader.version;
|
||||
|
||||
int m_TexEnvsSize = reader.ReadInt32();
|
||||
m_TexEnvs = new KeyValuePair<string, UnityTexEnv>[m_TexEnvsSize];
|
||||
for (int i = 0; i < m_TexEnvsSize; i++)
|
||||
@@ -31,6 +34,16 @@ namespace AssetStudio
|
||||
m_TexEnvs[i] = new KeyValuePair<string, UnityTexEnv>(reader.ReadAlignedString(), new UnityTexEnv(reader));
|
||||
}
|
||||
|
||||
if (version[0] >= 2021) //2021.1 and up
|
||||
{
|
||||
int m_IntsSize = reader.ReadInt32();
|
||||
m_Ints = new KeyValuePair<string, int>[m_IntsSize];
|
||||
for (int i = 0; i < m_IntsSize; i++)
|
||||
{
|
||||
m_Ints[i] = new KeyValuePair<string, int>(reader.ReadAlignedString(), reader.ReadInt32());
|
||||
}
|
||||
}
|
||||
|
||||
int m_FloatsSize = reader.ReadInt32();
|
||||
m_Floats = new KeyValuePair<string, float>[m_FloatsSize];
|
||||
for (int i = 0; i < m_FloatsSize; i++)
|
||||
@@ -95,6 +108,8 @@ namespace AssetStudio
|
||||
}
|
||||
|
||||
m_SavedProperties = new UnityPropertySheet(reader);
|
||||
|
||||
//vector m_BuildTextureStacks 2020 and up
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+353
-99
@@ -166,19 +166,19 @@ namespace AssetStudio
|
||||
|
||||
if (version[0] < 4) //4.0 down
|
||||
{
|
||||
GetChannels();
|
||||
GetChannels(version);
|
||||
}
|
||||
}
|
||||
else //5.0 and up
|
||||
{
|
||||
GetStreams();
|
||||
GetStreams(version);
|
||||
}
|
||||
|
||||
m_DataSize = reader.ReadBytes(reader.ReadInt32());
|
||||
m_DataSize = reader.ReadUInt8Array();
|
||||
reader.AlignStream();
|
||||
}
|
||||
|
||||
private void GetStreams()
|
||||
private void GetStreams(int[] version)
|
||||
{
|
||||
var streamCount = m_Channels.Max(x => x.stream) + 1;
|
||||
m_Streams = new StreamInfo[streamCount];
|
||||
@@ -195,7 +195,7 @@ namespace AssetStudio
|
||||
if (m_Channel.dimension > 0)
|
||||
{
|
||||
chnMask |= 1u << chn;
|
||||
stride += m_Channel.dimension * MeshHelper.GetChannelFormatSize(m_Channel.format);
|
||||
stride += m_Channel.dimension * MeshHelper.GetFormatSize(MeshHelper.ToVertexFormat(m_Channel.format, version));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -213,7 +213,7 @@ namespace AssetStudio
|
||||
}
|
||||
}
|
||||
|
||||
private void GetChannels()
|
||||
private void GetChannels(int[] version)
|
||||
{
|
||||
m_Channels = new ChannelInfo[6];
|
||||
for (int i = 0; i < 6; i++)
|
||||
@@ -253,7 +253,7 @@ namespace AssetStudio
|
||||
m_Channel.dimension = 4;
|
||||
break;
|
||||
}
|
||||
offset += (byte)(m_Channel.dimension * MeshHelper.GetChannelFormatSize(m_Channel.format));
|
||||
offset += (byte)(m_Channel.dimension * MeshHelper.GetFormatSize(MeshHelper.ToVertexFormat(m_Channel.format, version)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -396,11 +396,21 @@ namespace AssetStudio
|
||||
}
|
||||
}
|
||||
|
||||
public enum GfxPrimitiveType : int
|
||||
{
|
||||
kPrimitiveTriangles = 0,
|
||||
kPrimitiveTriangleStrip = 1,
|
||||
kPrimitiveQuads = 2,
|
||||
kPrimitiveLines = 3,
|
||||
kPrimitiveLineStrip = 4,
|
||||
kPrimitivePoints = 5,
|
||||
};
|
||||
|
||||
public class SubMesh
|
||||
{
|
||||
public uint firstByte;
|
||||
public uint indexCount;
|
||||
public int topology;
|
||||
public GfxPrimitiveType topology;
|
||||
public uint triangleCount;
|
||||
public uint baseVertex;
|
||||
public uint firstVertex;
|
||||
@@ -413,7 +423,7 @@ namespace AssetStudio
|
||||
|
||||
firstByte = reader.ReadUInt32();
|
||||
indexCount = reader.ReadUInt32();
|
||||
topology = reader.ReadInt32();
|
||||
topology = (GfxPrimitiveType)reader.ReadInt32();
|
||||
|
||||
if (version[0] < 4) //4.0 down
|
||||
{
|
||||
@@ -436,7 +446,7 @@ namespace AssetStudio
|
||||
|
||||
public sealed class Mesh : NamedObject
|
||||
{
|
||||
private bool m_Use16BitIndices = true; //3.5.0 and newer always uses 16bit indices;
|
||||
private bool m_Use16BitIndices = true;
|
||||
public SubMesh[] m_SubMeshes;
|
||||
private uint[] m_IndexBuffer;
|
||||
public BlendShapeData m_Shapes;
|
||||
@@ -451,12 +461,16 @@ namespace AssetStudio
|
||||
public float[] m_UV1;
|
||||
public float[] m_UV2;
|
||||
public float[] m_UV3;
|
||||
public float[] m_UV4;
|
||||
public float[] m_UV5;
|
||||
public float[] m_UV6;
|
||||
public float[] m_UV7;
|
||||
public float[] m_Tangents;
|
||||
private VertexData m_VertexData;
|
||||
private CompressedMesh m_CompressedMesh;
|
||||
private StreamingInfo m_StreamData;
|
||||
|
||||
public List<uint> m_Indices = new List<uint>(); //use a list because I don't always know the facecount for triangle strips
|
||||
public List<uint> m_Indices = new List<uint>();
|
||||
|
||||
public Mesh(ObjectReader reader) : base(reader)
|
||||
{
|
||||
@@ -536,6 +550,7 @@ namespace AssetStudio
|
||||
((version[0] == 2017 && version[1] == 3) && m_MeshCompression == 0))//2017.3.xfx with no compression
|
||||
{
|
||||
var m_IndexFormat = reader.ReadInt32();
|
||||
m_Use16BitIndices = m_IndexFormat == 0;
|
||||
}
|
||||
|
||||
int m_IndexBuffer_size = reader.ReadInt32();
|
||||
@@ -638,9 +653,9 @@ namespace AssetStudio
|
||||
|
||||
if (version[0] >= 5) //5.0 and up
|
||||
{
|
||||
var m_BakedConvexCollisionMesh = reader.ReadBytes(reader.ReadInt32());
|
||||
var m_BakedConvexCollisionMesh = reader.ReadUInt8Array();
|
||||
reader.AlignStream();
|
||||
var m_BakedTriangleCollisionMesh = reader.ReadBytes(reader.ReadInt32());
|
||||
var m_BakedTriangleCollisionMesh = reader.ReadUInt8Array();
|
||||
reader.AlignStream();
|
||||
}
|
||||
|
||||
@@ -680,7 +695,7 @@ namespace AssetStudio
|
||||
DecompressCompressedMesh();
|
||||
}
|
||||
|
||||
BuildFaces();
|
||||
GetTriangles();
|
||||
}
|
||||
|
||||
private void ReadVertexData()
|
||||
@@ -696,12 +711,13 @@ namespace AssetStudio
|
||||
var channelMask = new BitArray(new[] { (int)m_Stream.channelMask });
|
||||
if (channelMask.Get(chn))
|
||||
{
|
||||
if (version[0] < 2018 && chn == 2 && m_Channel.format == 2)
|
||||
if (version[0] < 2018 && chn == 2 && m_Channel.format == 2) //kShaderChannelColor && kChannelFormatColor
|
||||
{
|
||||
m_Channel.dimension = 4;
|
||||
}
|
||||
|
||||
var componentByteSize = (int)MeshHelper.GetChannelFormatSize(m_Channel.format);
|
||||
var vertexFormat = MeshHelper.ToVertexFormat(m_Channel.format, version);
|
||||
var componentByteSize = (int)MeshHelper.GetFormatSize(vertexFormat);
|
||||
var componentBytes = new byte[m_VertexCount * m_Channel.dimension * componentByteSize];
|
||||
for (int v = 0; v < m_VertexCount; v++)
|
||||
{
|
||||
@@ -726,10 +742,10 @@ namespace AssetStudio
|
||||
|
||||
int[] componentsIntArray = null;
|
||||
float[] componentsFloatArray = null;
|
||||
if (m_Channel.format == 10 || m_Channel.format == 11)
|
||||
componentsIntArray = MeshHelper.BytesToIntArray(componentBytes);
|
||||
if (MeshHelper.IsIntFormat(vertexFormat))
|
||||
componentsIntArray = MeshHelper.BytesToIntArray(componentBytes, vertexFormat);
|
||||
else
|
||||
componentsFloatArray = MeshHelper.BytesToFloatArray(componentBytes, componentByteSize);
|
||||
componentsFloatArray = MeshHelper.BytesToFloatArray(componentBytes, vertexFormat);
|
||||
|
||||
if (version[0] >= 2018)
|
||||
{
|
||||
@@ -759,10 +775,18 @@ namespace AssetStudio
|
||||
case 7: //kShaderChannelTexCoord3
|
||||
m_UV3 = componentsFloatArray;
|
||||
break;
|
||||
//kShaderChannelTexCoord4 8
|
||||
//kShaderChannelTexCoord5 9
|
||||
//kShaderChannelTexCoord6 10
|
||||
//kShaderChannelTexCoord7 11
|
||||
case 8: //kShaderChannelTexCoord4
|
||||
m_UV4 = componentsFloatArray;
|
||||
break;
|
||||
case 9: //kShaderChannelTexCoord5
|
||||
m_UV5 = componentsFloatArray;
|
||||
break;
|
||||
case 10: //kShaderChannelTexCoord6
|
||||
m_UV6 = componentsFloatArray;
|
||||
break;
|
||||
case 11: //kShaderChannelTexCoord7
|
||||
m_UV7 = componentsFloatArray;
|
||||
break;
|
||||
//2018.2 and up
|
||||
case 12: //kShaderChannelBlendWeight
|
||||
if (m_Skin == null)
|
||||
@@ -840,23 +864,40 @@ namespace AssetStudio
|
||||
if (m_CompressedMesh.m_Vertices.m_NumItems > 0)
|
||||
{
|
||||
m_VertexCount = (int)m_CompressedMesh.m_Vertices.m_NumItems / 3;
|
||||
m_Vertices = m_CompressedMesh.m_Vertices.UnpackFloats(3, 4);
|
||||
m_Vertices = m_CompressedMesh.m_Vertices.UnpackFloats(3, 3 * 4);
|
||||
}
|
||||
//UV
|
||||
if (m_CompressedMesh.m_UV.m_NumItems > 0)
|
||||
{
|
||||
m_UV0 = m_CompressedMesh.m_UV.UnpackFloats(2, 4, 0, m_VertexCount);
|
||||
if (m_CompressedMesh.m_UV.m_NumItems >= m_VertexCount * 4)
|
||||
var m_UVInfo = m_CompressedMesh.m_UVInfo;
|
||||
if (m_UVInfo != 0)
|
||||
{
|
||||
m_UV1 = m_CompressedMesh.m_UV.UnpackFloats(2, 4, m_VertexCount * 2, m_VertexCount);
|
||||
const int kInfoBitsPerUV = 4;
|
||||
const int kUVDimensionMask = 3;
|
||||
const int kUVChannelExists = 4;
|
||||
const int kMaxTexCoordShaderChannels = 8;
|
||||
|
||||
int uvSrcOffset = 0;
|
||||
for (int uv = 0; uv < kMaxTexCoordShaderChannels; uv++)
|
||||
{
|
||||
var texCoordBits = m_UVInfo >> (uv * kInfoBitsPerUV);
|
||||
texCoordBits &= (1u << kInfoBitsPerUV) - 1u;
|
||||
if ((texCoordBits & kUVChannelExists) != 0)
|
||||
{
|
||||
var uvDim = 1 + (int)(texCoordBits & kUVDimensionMask);
|
||||
var m_UV = m_CompressedMesh.m_UV.UnpackFloats(uvDim, uvDim * 4, uvSrcOffset, m_VertexCount);
|
||||
SetUV(uv, m_UV);
|
||||
uvSrcOffset += uvDim * m_VertexCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (m_CompressedMesh.m_UV.m_NumItems >= m_VertexCount * 6)
|
||||
else
|
||||
{
|
||||
m_UV2 = m_CompressedMesh.m_UV.UnpackFloats(2, 4, m_VertexCount * 4, m_VertexCount);
|
||||
}
|
||||
if (m_CompressedMesh.m_UV.m_NumItems >= m_VertexCount * 8)
|
||||
{
|
||||
m_UV3 = m_CompressedMesh.m_UV.UnpackFloats(2, 4, m_VertexCount * 6, m_VertexCount);
|
||||
m_UV0 = m_CompressedMesh.m_UV.UnpackFloats(2, 2 * 4, 0, m_VertexCount);
|
||||
if (m_CompressedMesh.m_UV.m_NumItems >= m_VertexCount * 4)
|
||||
{
|
||||
m_UV1 = m_CompressedMesh.m_UV.UnpackFloats(2, 2 * 4, m_VertexCount * 2, m_VertexCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
//BindPose
|
||||
@@ -1008,7 +1049,7 @@ namespace AssetStudio
|
||||
}
|
||||
}
|
||||
|
||||
private void BuildFaces()
|
||||
private void GetTriangles()
|
||||
{
|
||||
foreach (var m_SubMesh in m_SubMeshes)
|
||||
{
|
||||
@@ -1017,43 +1058,65 @@ namespace AssetStudio
|
||||
{
|
||||
firstIndex /= 2;
|
||||
}
|
||||
|
||||
if (m_SubMesh.topology == 0)
|
||||
var indexCount = m_SubMesh.indexCount;
|
||||
var topology = m_SubMesh.topology;
|
||||
if (topology == GfxPrimitiveType.kPrimitiveTriangles)
|
||||
{
|
||||
for (int i = 0; i < m_SubMesh.indexCount / 3; i++)
|
||||
for (int i = 0; i < indexCount; i += 3)
|
||||
{
|
||||
m_Indices.Add(m_IndexBuffer[firstIndex + i * 3]);
|
||||
m_Indices.Add(m_IndexBuffer[firstIndex + i * 3 + 1]);
|
||||
m_Indices.Add(m_IndexBuffer[firstIndex + i * 3 + 2]);
|
||||
m_Indices.Add(m_IndexBuffer[firstIndex + i]);
|
||||
m_Indices.Add(m_IndexBuffer[firstIndex + i + 1]);
|
||||
m_Indices.Add(m_IndexBuffer[firstIndex + i + 2]);
|
||||
}
|
||||
}
|
||||
else if (version[0] < 4 || topology == GfxPrimitiveType.kPrimitiveTriangleStrip)
|
||||
{
|
||||
// de-stripify :
|
||||
uint triIndex = 0;
|
||||
for (int i = 0; i < indexCount - 2; i++)
|
||||
{
|
||||
var a = m_IndexBuffer[firstIndex + i];
|
||||
var b = m_IndexBuffer[firstIndex + i + 1];
|
||||
var c = m_IndexBuffer[firstIndex + i + 2];
|
||||
|
||||
// skip degenerates
|
||||
if (a == b || a == c || b == c)
|
||||
continue;
|
||||
|
||||
// do the winding flip-flop of strips :
|
||||
if ((i & 1) == 1)
|
||||
{
|
||||
m_Indices.Add(b);
|
||||
m_Indices.Add(a);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Indices.Add(a);
|
||||
m_Indices.Add(b);
|
||||
}
|
||||
m_Indices.Add(c);
|
||||
triIndex += 3;
|
||||
}
|
||||
//fix indexCount
|
||||
m_SubMesh.indexCount = triIndex;
|
||||
}
|
||||
else if (topology == GfxPrimitiveType.kPrimitiveQuads)
|
||||
{
|
||||
for (int q = 0; q < indexCount; q += 4)
|
||||
{
|
||||
m_Indices.Add(m_IndexBuffer[firstIndex + q]);
|
||||
m_Indices.Add(m_IndexBuffer[firstIndex + q + 1]);
|
||||
m_Indices.Add(m_IndexBuffer[firstIndex + q + 2]);
|
||||
m_Indices.Add(m_IndexBuffer[firstIndex + q]);
|
||||
m_Indices.Add(m_IndexBuffer[firstIndex + q + 2]);
|
||||
m_Indices.Add(m_IndexBuffer[firstIndex + q + 3]);
|
||||
}
|
||||
//fix indexCount
|
||||
m_SubMesh.indexCount = indexCount / 2 * 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint j = 0;
|
||||
for (int i = 0; i < m_SubMesh.indexCount - 2; i++)
|
||||
{
|
||||
uint fa = m_IndexBuffer[firstIndex + i];
|
||||
uint fb = m_IndexBuffer[firstIndex + i + 1];
|
||||
uint fc = m_IndexBuffer[firstIndex + i + 2];
|
||||
|
||||
if ((fa != fb) && (fa != fc) && (fc != fb))
|
||||
{
|
||||
m_Indices.Add(fa);
|
||||
if ((i % 2) == 0)
|
||||
{
|
||||
m_Indices.Add(fb);
|
||||
m_Indices.Add(fc);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Indices.Add(fc);
|
||||
m_Indices.Add(fb);
|
||||
}
|
||||
j++;
|
||||
}
|
||||
}
|
||||
//fix indexCount
|
||||
m_SubMesh.indexCount = j * 3;
|
||||
throw new NotSupportedException("Failed getting triangles. Submesh topology is lines or points.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1066,62 +1129,253 @@ namespace AssetStudio
|
||||
m_Skin[i] = new BoneWeights4();
|
||||
}
|
||||
}
|
||||
|
||||
private void SetUV(int uv, float[] m_UV)
|
||||
{
|
||||
switch (uv)
|
||||
{
|
||||
case 0:
|
||||
m_UV0 = m_UV;
|
||||
break;
|
||||
case 1:
|
||||
m_UV1 = m_UV;
|
||||
break;
|
||||
case 2:
|
||||
m_UV2 = m_UV;
|
||||
break;
|
||||
case 3:
|
||||
m_UV3 = m_UV;
|
||||
break;
|
||||
case 4:
|
||||
m_UV4 = m_UV;
|
||||
break;
|
||||
case 5:
|
||||
m_UV5 = m_UV;
|
||||
break;
|
||||
case 6:
|
||||
m_UV6 = m_UV;
|
||||
break;
|
||||
case 7:
|
||||
m_UV7 = m_UV;
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
|
||||
public float[] GetUV(int uv)
|
||||
{
|
||||
switch (uv)
|
||||
{
|
||||
case 0:
|
||||
return m_UV0;
|
||||
case 1:
|
||||
return m_UV1;
|
||||
case 2:
|
||||
return m_UV2;
|
||||
case 3:
|
||||
return m_UV3;
|
||||
case 4:
|
||||
return m_UV4;
|
||||
case 5:
|
||||
return m_UV5;
|
||||
case 6:
|
||||
return m_UV6;
|
||||
case 7:
|
||||
return m_UV7;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class MeshHelper
|
||||
{
|
||||
public static uint GetChannelFormatSize(int format)
|
||||
public enum VertexChannelFormat
|
||||
{
|
||||
switch (format)
|
||||
kChannelFormatFloat,
|
||||
kChannelFormatFloat16,
|
||||
kChannelFormatColor,
|
||||
kChannelFormatByte,
|
||||
kChannelFormatUInt32
|
||||
}
|
||||
|
||||
public enum VertexFormat2017
|
||||
{
|
||||
kVertexFormatFloat,
|
||||
kVertexFormatFloat16,
|
||||
kVertexFormatColor,
|
||||
kVertexFormatUNorm8,
|
||||
kVertexFormatSNorm8,
|
||||
kVertexFormatUNorm16,
|
||||
kVertexFormatSNorm16,
|
||||
kVertexFormatUInt8,
|
||||
kVertexFormatSInt8,
|
||||
kVertexFormatUInt16,
|
||||
kVertexFormatSInt16,
|
||||
kVertexFormatUInt32,
|
||||
kVertexFormatSInt32
|
||||
}
|
||||
|
||||
public enum VertexFormat
|
||||
{
|
||||
kVertexFormatFloat,
|
||||
kVertexFormatFloat16,
|
||||
kVertexFormatUNorm8,
|
||||
kVertexFormatSNorm8,
|
||||
kVertexFormatUNorm16,
|
||||
kVertexFormatSNorm16,
|
||||
kVertexFormatUInt8,
|
||||
kVertexFormatSInt8,
|
||||
kVertexFormatUInt16,
|
||||
kVertexFormatSInt16,
|
||||
kVertexFormatUInt32,
|
||||
kVertexFormatSInt32
|
||||
}
|
||||
|
||||
public static VertexFormat ToVertexFormat(int format, int[] version)
|
||||
{
|
||||
if (version[0] < 2017)
|
||||
{
|
||||
case 0: //kChannelFormatFloat
|
||||
return 4u;
|
||||
case 1: //kChannelFormatFloat16
|
||||
return 2u;
|
||||
case 2: //kChannelFormatColor
|
||||
return 1u;
|
||||
case 3: //kChannelFormatByte
|
||||
return 1u;
|
||||
case 4: //kChannelFormatUInt32
|
||||
return 4u;
|
||||
case 10: //kChannelFormatInt32
|
||||
return 4u;
|
||||
case 11: //kChannelFormatInt32
|
||||
return 4u;
|
||||
default:
|
||||
return 0;
|
||||
switch ((VertexChannelFormat)format)
|
||||
{
|
||||
case VertexChannelFormat.kChannelFormatFloat:
|
||||
return VertexFormat.kVertexFormatFloat;
|
||||
case VertexChannelFormat.kChannelFormatFloat16:
|
||||
return VertexFormat.kVertexFormatFloat16;
|
||||
case VertexChannelFormat.kChannelFormatColor: //in 4.x is size 4
|
||||
return VertexFormat.kVertexFormatUNorm8;
|
||||
case VertexChannelFormat.kChannelFormatByte:
|
||||
return VertexFormat.kVertexFormatUInt8;
|
||||
case VertexChannelFormat.kChannelFormatUInt32: //in 5.x
|
||||
return VertexFormat.kVertexFormatUInt32;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(format), format, null);
|
||||
}
|
||||
}
|
||||
else if (version[0] < 2019)
|
||||
{
|
||||
switch ((VertexFormat2017)format)
|
||||
{
|
||||
case VertexFormat2017.kVertexFormatFloat:
|
||||
return VertexFormat.kVertexFormatFloat;
|
||||
case VertexFormat2017.kVertexFormatFloat16:
|
||||
return VertexFormat.kVertexFormatFloat16;
|
||||
case VertexFormat2017.kVertexFormatColor:
|
||||
case VertexFormat2017.kVertexFormatUNorm8:
|
||||
return VertexFormat.kVertexFormatUNorm8;
|
||||
case VertexFormat2017.kVertexFormatSNorm8:
|
||||
return VertexFormat.kVertexFormatSNorm8;
|
||||
case VertexFormat2017.kVertexFormatUNorm16:
|
||||
return VertexFormat.kVertexFormatUNorm16;
|
||||
case VertexFormat2017.kVertexFormatSNorm16:
|
||||
return VertexFormat.kVertexFormatSNorm16;
|
||||
case VertexFormat2017.kVertexFormatUInt8:
|
||||
return VertexFormat.kVertexFormatUInt8;
|
||||
case VertexFormat2017.kVertexFormatSInt8:
|
||||
return VertexFormat.kVertexFormatSInt8;
|
||||
case VertexFormat2017.kVertexFormatUInt16:
|
||||
return VertexFormat.kVertexFormatUInt16;
|
||||
case VertexFormat2017.kVertexFormatSInt16:
|
||||
return VertexFormat.kVertexFormatSInt16;
|
||||
case VertexFormat2017.kVertexFormatUInt32:
|
||||
return VertexFormat.kVertexFormatUInt32;
|
||||
case VertexFormat2017.kVertexFormatSInt32:
|
||||
return VertexFormat.kVertexFormatSInt32;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(format), format, null);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return (VertexFormat)format;
|
||||
}
|
||||
}
|
||||
|
||||
public static float[] BytesToFloatArray(byte[] inputBytes, int size)
|
||||
|
||||
public static uint GetFormatSize(VertexFormat format)
|
||||
{
|
||||
var result = new float[inputBytes.Length / size];
|
||||
for (int i = 0; i < inputBytes.Length / size; i++)
|
||||
switch (format)
|
||||
{
|
||||
var value = 0f;
|
||||
switch (size)
|
||||
case VertexFormat.kVertexFormatFloat:
|
||||
case VertexFormat.kVertexFormatUInt32:
|
||||
case VertexFormat.kVertexFormatSInt32:
|
||||
return 4u;
|
||||
case VertexFormat.kVertexFormatFloat16:
|
||||
case VertexFormat.kVertexFormatUNorm16:
|
||||
case VertexFormat.kVertexFormatSNorm16:
|
||||
case VertexFormat.kVertexFormatUInt16:
|
||||
case VertexFormat.kVertexFormatSInt16:
|
||||
return 2u;
|
||||
case VertexFormat.kVertexFormatUNorm8:
|
||||
case VertexFormat.kVertexFormatSNorm8:
|
||||
case VertexFormat.kVertexFormatUInt8:
|
||||
case VertexFormat.kVertexFormatSInt8:
|
||||
return 1u;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(format), format, null);
|
||||
}
|
||||
}
|
||||
|
||||
public static bool IsIntFormat(VertexFormat format)
|
||||
{
|
||||
return format >= VertexFormat.kVertexFormatUInt8;
|
||||
}
|
||||
|
||||
public static float[] BytesToFloatArray(byte[] inputBytes, VertexFormat format)
|
||||
{
|
||||
var size = GetFormatSize(format);
|
||||
var len = inputBytes.Length / size;
|
||||
var result = new float[len];
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case 1:
|
||||
value = inputBytes[i] / 255.0f;
|
||||
case VertexFormat.kVertexFormatFloat:
|
||||
result[i] = BitConverter.ToSingle(inputBytes, i * 4);
|
||||
break;
|
||||
case 2:
|
||||
value = Half.ToHalf(inputBytes, i * 2);
|
||||
case VertexFormat.kVertexFormatFloat16:
|
||||
result[i] = Half.ToHalf(inputBytes, i * 2);
|
||||
break;
|
||||
case 4:
|
||||
value = BitConverter.ToSingle(inputBytes, i * 4);
|
||||
case VertexFormat.kVertexFormatUNorm8:
|
||||
result[i] = inputBytes[i] / 255f;
|
||||
break;
|
||||
case VertexFormat.kVertexFormatSNorm8:
|
||||
result[i] = Math.Max((sbyte)inputBytes[i] / 127f, -1f);
|
||||
break;
|
||||
case VertexFormat.kVertexFormatUNorm16:
|
||||
result[i] = BitConverter.ToUInt16(inputBytes, i * 2) / 65535f;
|
||||
break;
|
||||
case VertexFormat.kVertexFormatSNorm16:
|
||||
result[i] = Math.Max(BitConverter.ToInt16(inputBytes, i * 2) / 32767f, -1f);
|
||||
break;
|
||||
}
|
||||
result[i] = value;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static int[] BytesToIntArray(byte[] inputBytes)
|
||||
public static int[] BytesToIntArray(byte[] inputBytes, VertexFormat format)
|
||||
{
|
||||
var result = new int[inputBytes.Length / 4];
|
||||
for (int i = 0; i < inputBytes.Length / 4; i++)
|
||||
var size = GetFormatSize(format);
|
||||
var len = inputBytes.Length / size;
|
||||
var result = new int[len];
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
result[i] = BitConverter.ToInt32(inputBytes, i * 4);
|
||||
switch (format)
|
||||
{
|
||||
case VertexFormat.kVertexFormatUInt8:
|
||||
case VertexFormat.kVertexFormatSInt8:
|
||||
result[i] = inputBytes[i];
|
||||
break;
|
||||
case VertexFormat.kVertexFormatUInt16:
|
||||
case VertexFormat.kVertexFormatSInt16:
|
||||
result[i] = BitConverter.ToInt16(inputBytes, i * 2);
|
||||
break;
|
||||
case VertexFormat.kVertexFormatUInt32:
|
||||
case VertexFormat.kVertexFormatSInt32:
|
||||
result[i] = BitConverter.ToInt32(inputBytes, i * 4);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace AssetStudio
|
||||
public sealed class MonoScript : NamedObject
|
||||
{
|
||||
public string m_ClassName;
|
||||
public string m_Namespace = string.Empty;
|
||||
public string m_Namespace;
|
||||
public string m_AssemblyName;
|
||||
|
||||
public MonoScript(ObjectReader reader) : base(reader)
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace AssetStudio
|
||||
var m_Loop = reader.ReadBoolean();
|
||||
reader.AlignStream();
|
||||
m_AudioClip = new PPtr<AudioClip>(reader);
|
||||
m_MovieData = reader.ReadBytes(reader.ReadInt32());
|
||||
m_MovieData = reader.ReadUInt8Array();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
@@ -43,7 +43,6 @@ namespace AssetStudio
|
||||
|
||||
public string Dump()
|
||||
{
|
||||
reader.Reset();
|
||||
if (serializedType?.m_Nodes != null)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
@@ -53,6 +52,35 @@ namespace AssetStudio
|
||||
return null;
|
||||
}
|
||||
|
||||
public string Dump(List<TypeTreeNode> m_Nodes)
|
||||
{
|
||||
if (m_Nodes != null)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
TypeTreeHelper.ReadTypeString(sb, m_Nodes, reader);
|
||||
return sb.ToString();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public OrderedDictionary ToType()
|
||||
{
|
||||
if (serializedType?.m_Nodes != null)
|
||||
{
|
||||
return TypeTreeHelper.ReadType(serializedType.m_Nodes, reader);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public OrderedDictionary ToType(List<TypeTreeNode> m_Nodes)
|
||||
{
|
||||
if (m_Nodes != null)
|
||||
{
|
||||
return TypeTreeHelper.ReadType(m_Nodes, reader);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public byte[] GetRawData()
|
||||
{
|
||||
reader.Reset();
|
||||
|
||||
@@ -35,10 +35,10 @@ namespace AssetStudio
|
||||
if (index == -2)
|
||||
{
|
||||
var m_External = assetsFile.m_Externals[m_FileID - 1];
|
||||
var name = m_External.fileName.ToUpper();
|
||||
var name = m_External.fileName;
|
||||
if (!assetsFileIndexCache.TryGetValue(name, out index))
|
||||
{
|
||||
index = assetsFileList.FindIndex(x => x.upperFileName == name);
|
||||
index = assetsFileList.FindIndex(x => x.fileName.Equals(name, StringComparison.OrdinalIgnoreCase));
|
||||
assetsFileIndexCache.Add(name, index);
|
||||
}
|
||||
}
|
||||
@@ -57,7 +57,7 @@ namespace AssetStudio
|
||||
{
|
||||
if (TryGetAssetsFile(out var sourceFile))
|
||||
{
|
||||
if (sourceFile.Objects.TryGetValue(m_PathID, out var obj))
|
||||
if (sourceFile.ObjectsDic.TryGetValue(m_PathID, out var obj))
|
||||
{
|
||||
if (obj is T variable)
|
||||
{
|
||||
@@ -75,7 +75,7 @@ namespace AssetStudio
|
||||
{
|
||||
if (TryGetAssetsFile(out var sourceFile))
|
||||
{
|
||||
if (sourceFile.Objects.TryGetValue(m_PathID, out var obj))
|
||||
if (sourceFile.ObjectsDic.TryGetValue(m_PathID, out var obj))
|
||||
{
|
||||
if (obj is T2 variable)
|
||||
{
|
||||
@@ -91,8 +91,8 @@ namespace AssetStudio
|
||||
|
||||
public void Set(T m_Object)
|
||||
{
|
||||
var name = m_Object.assetsFile.upperFileName;
|
||||
if (string.Equals(assetsFile.upperFileName, name, StringComparison.Ordinal))
|
||||
var name = m_Object.assetsFile.fileName;
|
||||
if (string.Equals(assetsFile.fileName, name, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
m_FileID = 0;
|
||||
}
|
||||
@@ -119,13 +119,13 @@ namespace AssetStudio
|
||||
|
||||
if (!assetsFileIndexCache.TryGetValue(name, out index))
|
||||
{
|
||||
index = assetsFileList.FindIndex(x => x.upperFileName == name);
|
||||
index = assetsFileList.FindIndex(x => x.fileName.Equals(name, StringComparison.OrdinalIgnoreCase));
|
||||
assetsFileIndexCache.Add(name, index);
|
||||
}
|
||||
|
||||
m_PathID = m_Object.m_PathID;
|
||||
}
|
||||
|
||||
public bool IsNull() => m_PathID == 0 || m_FileID < 0;
|
||||
public bool IsNull => m_PathID == 0 || m_FileID < 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,13 +39,25 @@ namespace AssetStudio
|
||||
var m_Enabled = reader.ReadBoolean();
|
||||
var m_CastShadows = reader.ReadByte();
|
||||
var m_ReceiveShadows = reader.ReadByte();
|
||||
if (version[0] > 2017 || (version[0] == 2017 && version[0] >= 2)) //2017.2 and up
|
||||
if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 2)) //2017.2 and up
|
||||
{
|
||||
var m_DynamicOccludee = reader.ReadByte();
|
||||
}
|
||||
if (version[0] >= 2021) //2021.1 and up
|
||||
{
|
||||
var m_StaticShadowCaster = reader.ReadByte();
|
||||
}
|
||||
var m_MotionVectors = reader.ReadByte();
|
||||
var m_LightProbeUsage = reader.ReadByte();
|
||||
var m_ReflectionProbeUsage = reader.ReadByte();
|
||||
if (version[0] > 2019 || (version[0] == 2019 && version[1] >= 3)) //2019.3 and up
|
||||
{
|
||||
var m_RayTracingMode = reader.ReadByte();
|
||||
}
|
||||
if (version[0] >= 2020) //2020.1 and up
|
||||
{
|
||||
var m_RayTraceProcedural = reader.ReadByte();
|
||||
}
|
||||
reader.AlignStream();
|
||||
}
|
||||
else
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public class ResourceManager : Object
|
||||
{
|
||||
public KeyValuePair<string, PPtr<Object>>[] m_Container;
|
||||
|
||||
public ResourceManager(ObjectReader reader) : base(reader)
|
||||
{
|
||||
var m_ContainerSize = reader.ReadInt32();
|
||||
m_Container = new KeyValuePair<string, PPtr<Object>>[m_ContainerSize];
|
||||
for (int i = 0; i < m_ContainerSize; i++)
|
||||
{
|
||||
m_Container[i] = new KeyValuePair<string, PPtr<Object>>(reader.ReadAlignedString(), new PPtr<Object>(reader));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+108
-10
@@ -5,6 +5,16 @@ using System.Linq;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public class Hash128
|
||||
{
|
||||
public byte[] bytes;
|
||||
|
||||
public Hash128(BinaryReader reader)
|
||||
{
|
||||
bytes = reader.ReadBytes(16);
|
||||
}
|
||||
}
|
||||
|
||||
public class StructParameter
|
||||
{
|
||||
public MatrixParameter[] m_MatrixParams;
|
||||
@@ -201,6 +211,7 @@ namespace AssetStudio
|
||||
public SerializedShaderFloatValue zTest;
|
||||
public SerializedShaderFloatValue zWrite;
|
||||
public SerializedShaderFloatValue culling;
|
||||
public SerializedShaderFloatValue conservative;
|
||||
public SerializedShaderFloatValue offsetFactor;
|
||||
public SerializedShaderFloatValue offsetUnits;
|
||||
public SerializedShaderFloatValue alphaToMask;
|
||||
@@ -239,6 +250,10 @@ namespace AssetStudio
|
||||
zTest = new SerializedShaderFloatValue(reader);
|
||||
zWrite = new SerializedShaderFloatValue(reader);
|
||||
culling = new SerializedShaderFloatValue(reader);
|
||||
if (version[0] >= 2020) //2020.1 and up
|
||||
{
|
||||
conservative = new SerializedShaderFloatValue(reader);
|
||||
}
|
||||
offsetFactor = new SerializedShaderFloatValue(reader);
|
||||
offsetUnits = new SerializedShaderFloatValue(reader);
|
||||
alphaToMask = new SerializedShaderFloatValue(reader);
|
||||
@@ -357,11 +372,18 @@ namespace AssetStudio
|
||||
{
|
||||
public int m_NameIndex;
|
||||
public int m_Index;
|
||||
public int m_ArraySize;
|
||||
|
||||
public BufferBinding(BinaryReader reader)
|
||||
public BufferBinding(ObjectReader reader)
|
||||
{
|
||||
var version = reader.version;
|
||||
|
||||
m_NameIndex = reader.ReadInt32();
|
||||
m_Index = reader.ReadInt32();
|
||||
if (version[0] >= 2020) //2020.1 and up
|
||||
{
|
||||
m_ArraySize = reader.ReadInt32();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -447,7 +469,12 @@ namespace AssetStudio
|
||||
kShaderGpuProgramMetalVS = 23,
|
||||
kShaderGpuProgramMetalFS = 24,
|
||||
kShaderGpuProgramSPIRV = 25,
|
||||
kShaderGpuProgramConsole = 26
|
||||
kShaderGpuProgramConsoleVS = 26,
|
||||
kShaderGpuProgramConsoleFS = 27,
|
||||
kShaderGpuProgramConsoleHS = 28,
|
||||
kShaderGpuProgramConsoleDS = 29,
|
||||
kShaderGpuProgramConsoleGS = 30,
|
||||
kShaderGpuProgramRayTracing = 31,
|
||||
};
|
||||
|
||||
public class SerializedSubProgram
|
||||
@@ -553,7 +580,14 @@ namespace AssetStudio
|
||||
}
|
||||
if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 2)) //2017.2 and up
|
||||
{
|
||||
var m_ShaderRequirements = reader.ReadInt32();
|
||||
if (version[0] >= 2021) //2021.1 and up
|
||||
{
|
||||
var m_ShaderRequirements = reader.ReadInt64();
|
||||
}
|
||||
else
|
||||
{
|
||||
var m_ShaderRequirements = reader.ReadInt32();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -582,6 +616,10 @@ namespace AssetStudio
|
||||
|
||||
public class SerializedPass
|
||||
{
|
||||
public Hash128[] m_EditorDataHash;
|
||||
public byte[] m_Platforms;
|
||||
public ushort[] m_LocalKeywordMask;
|
||||
public ushort[] m_GlobalKeywordMask;
|
||||
public KeyValuePair<string, int>[] m_NameIndices;
|
||||
public PassType m_Type;
|
||||
public SerializedShaderState m_State;
|
||||
@@ -591,6 +629,7 @@ namespace AssetStudio
|
||||
public SerializedProgram progGeometry;
|
||||
public SerializedProgram progHull;
|
||||
public SerializedProgram progDomain;
|
||||
public SerializedProgram progRayTracing;
|
||||
public bool m_HasInstancingVariant;
|
||||
public string m_UseName;
|
||||
public string m_Name;
|
||||
@@ -601,6 +640,23 @@ namespace AssetStudio
|
||||
{
|
||||
var version = reader.version;
|
||||
|
||||
if (version[0] > 2020 || (version[0] == 2020 && version[1] >= 2)) //2020.2 and up
|
||||
{
|
||||
int numEditorDataHash = reader.ReadInt32();
|
||||
m_EditorDataHash = new Hash128[numEditorDataHash];
|
||||
for (int i = 0; i < numEditorDataHash; i++)
|
||||
{
|
||||
m_EditorDataHash[i] = new Hash128(reader);
|
||||
}
|
||||
reader.AlignStream();
|
||||
m_Platforms = reader.ReadUInt8Array();
|
||||
reader.AlignStream();
|
||||
m_LocalKeywordMask = reader.ReadUInt16Array();
|
||||
reader.AlignStream();
|
||||
m_GlobalKeywordMask = reader.ReadUInt16Array();
|
||||
reader.AlignStream();
|
||||
}
|
||||
|
||||
int numIndices = reader.ReadInt32();
|
||||
m_NameIndices = new KeyValuePair<string, int>[numIndices];
|
||||
for (int i = 0; i < numIndices; i++)
|
||||
@@ -616,6 +672,10 @@ namespace AssetStudio
|
||||
progGeometry = new SerializedProgram(reader);
|
||||
progHull = new SerializedProgram(reader);
|
||||
progDomain = new SerializedProgram(reader);
|
||||
if (version[0] > 2019 || (version[0] == 2019 && version[1] >= 3)) //2019.3 and up
|
||||
{
|
||||
progRayTracing = new SerializedProgram(reader);
|
||||
}
|
||||
m_HasInstancingVariant = reader.ReadBoolean();
|
||||
if (version[0] >= 2018) //2018 and up
|
||||
{
|
||||
@@ -676,6 +736,18 @@ namespace AssetStudio
|
||||
}
|
||||
}
|
||||
|
||||
public class SerializedCustomEditorForRenderPipeline
|
||||
{
|
||||
public string customEditorName;
|
||||
public string renderPipelineType;
|
||||
|
||||
public SerializedCustomEditorForRenderPipeline(BinaryReader reader)
|
||||
{
|
||||
customEditorName = reader.ReadAlignedString();
|
||||
renderPipelineType = reader.ReadAlignedString();
|
||||
}
|
||||
}
|
||||
|
||||
public class SerializedShader
|
||||
{
|
||||
public SerializedProperties m_PropInfo;
|
||||
@@ -684,10 +756,13 @@ namespace AssetStudio
|
||||
public string m_CustomEditorName;
|
||||
public string m_FallbackName;
|
||||
public SerializedShaderDependency[] m_Dependencies;
|
||||
public SerializedCustomEditorForRenderPipeline[] m_CustomEditorForRenderPipelines;
|
||||
public bool m_DisableNoSubshadersMessage;
|
||||
|
||||
public SerializedShader(ObjectReader reader)
|
||||
{
|
||||
var version = reader.version;
|
||||
|
||||
m_PropInfo = new SerializedProperties(reader);
|
||||
|
||||
int numSubShaders = reader.ReadInt32();
|
||||
@@ -708,6 +783,16 @@ namespace AssetStudio
|
||||
m_Dependencies[i] = new SerializedShaderDependency(reader);
|
||||
}
|
||||
|
||||
if (version[0] >= 2021) //2021.1 and up
|
||||
{
|
||||
int m_CustomEditorForRenderPipelinesSize = reader.ReadInt32();
|
||||
m_CustomEditorForRenderPipelines = new SerializedCustomEditorForRenderPipeline[m_CustomEditorForRenderPipelinesSize];
|
||||
for (int i = 0; i < m_CustomEditorForRenderPipelinesSize; i++)
|
||||
{
|
||||
m_CustomEditorForRenderPipelines[i] = new SerializedCustomEditorForRenderPipeline(reader);
|
||||
}
|
||||
}
|
||||
|
||||
m_DisableNoSubshadersMessage = reader.ReadBoolean();
|
||||
reader.AlignStream();
|
||||
}
|
||||
@@ -736,7 +821,11 @@ namespace AssetStudio
|
||||
kShaderCompPlatformWiiU = 17,
|
||||
kShaderCompPlatformVulkan = 18,
|
||||
kShaderCompPlatformSwitch = 19,
|
||||
kShaderCompPlatformXboxOneD3D12 = 20
|
||||
kShaderCompPlatformXboxOneD3D12 = 20,
|
||||
kShaderCompPlatformGameCoreXboxOne = 21,
|
||||
kShaderCompPlatformGameCoreScarlett = 22,
|
||||
kShaderCompPlatformPS5 = 23,
|
||||
kShaderCompPlatformPS5NGGC = 24,
|
||||
};
|
||||
|
||||
public class Shader : NamedObject
|
||||
@@ -759,20 +848,29 @@ namespace AssetStudio
|
||||
{
|
||||
m_ParsedForm = new SerializedShader(reader);
|
||||
platforms = reader.ReadUInt32Array().Select(x => (ShaderCompilerPlatform)x).ToArray();
|
||||
offsets = reader.ReadUInt32Array();
|
||||
compressedLengths = reader.ReadUInt32Array();
|
||||
decompressedLengths = reader.ReadUInt32Array();
|
||||
compressedBlob = reader.ReadBytes(reader.ReadInt32());
|
||||
if (version[0] > 2019 || (version[0] == 2019 && version[1] >= 3)) //2019.3 and up
|
||||
{
|
||||
offsets = reader.ReadUInt32ArrayArray().Select(x => x[0]).ToArray();
|
||||
compressedLengths = reader.ReadUInt32ArrayArray().Select(x => x[0]).ToArray();
|
||||
decompressedLengths = reader.ReadUInt32ArrayArray().Select(x => x[0]).ToArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
offsets = reader.ReadUInt32Array();
|
||||
compressedLengths = reader.ReadUInt32Array();
|
||||
decompressedLengths = reader.ReadUInt32Array();
|
||||
}
|
||||
compressedBlob = reader.ReadUInt8Array();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Script = reader.ReadBytes(reader.ReadInt32());
|
||||
m_Script = reader.ReadUInt8Array();
|
||||
reader.AlignStream();
|
||||
var m_PathName = reader.ReadAlignedString();
|
||||
if (version[0] == 5 && version[1] >= 3) //5.3 - 5.4
|
||||
{
|
||||
decompressedSize = reader.ReadUInt32();
|
||||
m_SubProgramBlob = reader.ReadBytes(reader.ReadInt32());
|
||||
m_SubProgramBlob = reader.ReadUInt8Array();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
|
||||
namespace AssetStudio
|
||||
@@ -32,6 +31,12 @@ namespace AssetStudio
|
||||
kSPMRectangle
|
||||
};
|
||||
|
||||
public enum SpriteMeshType
|
||||
{
|
||||
kSpriteMeshTypeFullRect,
|
||||
kSpriteMeshTypeTight
|
||||
};
|
||||
|
||||
public class SpriteSettings
|
||||
{
|
||||
public uint settingsRaw;
|
||||
@@ -39,6 +44,7 @@ namespace AssetStudio
|
||||
public uint packed;
|
||||
public SpritePackingMode packingMode;
|
||||
public SpritePackingRotation packingRotation;
|
||||
public SpriteMeshType meshType;
|
||||
|
||||
public SpriteSettings(BinaryReader reader)
|
||||
{
|
||||
@@ -47,8 +53,7 @@ namespace AssetStudio
|
||||
packed = settingsRaw & 1; //1
|
||||
packingMode = (SpritePackingMode)((settingsRaw >> 1) & 1); //1
|
||||
packingRotation = (SpritePackingRotation)((settingsRaw >> 2) & 0xf); //4
|
||||
|
||||
//meshType = (settingsRaw >> 6) & 1; //1
|
||||
meshType = (SpriteMeshType)((settingsRaw >> 6) & 1); //1
|
||||
//reserved
|
||||
}
|
||||
}
|
||||
@@ -82,7 +87,7 @@ namespace AssetStudio
|
||||
public ushort[] indices;
|
||||
public Matrix4x4[] m_Bindpose;
|
||||
public BoneWeights4[] m_SourceSkin;
|
||||
public RectangleF textureRect;
|
||||
public Rectf textureRect;
|
||||
public Vector2 textureRectOffset;
|
||||
public Vector2 atlasRectOffset;
|
||||
public SpriteSettings settingsRaw;
|
||||
@@ -118,7 +123,7 @@ namespace AssetStudio
|
||||
m_SubMeshes[i] = new SubMesh(reader);
|
||||
}
|
||||
|
||||
m_IndexBuffer = reader.ReadBytes(reader.ReadInt32());
|
||||
m_IndexBuffer = reader.ReadUInt8Array();
|
||||
reader.AlignStream();
|
||||
|
||||
m_VertexData = new VertexData(reader);
|
||||
@@ -150,7 +155,7 @@ namespace AssetStudio
|
||||
}
|
||||
}
|
||||
|
||||
textureRect = reader.ReadRectangleF();
|
||||
textureRect = new Rectf(reader);
|
||||
textureRectOffset = reader.ReadVector2();
|
||||
if (version[0] > 5 || (version[0] == 5 && version[1] >= 6)) //5.6 and up
|
||||
{
|
||||
@@ -170,9 +175,25 @@ namespace AssetStudio
|
||||
}
|
||||
}
|
||||
|
||||
public class Rectf
|
||||
{
|
||||
public float x;
|
||||
public float y;
|
||||
public float width;
|
||||
public float height;
|
||||
|
||||
public Rectf(BinaryReader reader)
|
||||
{
|
||||
x = reader.ReadSingle();
|
||||
y = reader.ReadSingle();
|
||||
width = reader.ReadSingle();
|
||||
height = reader.ReadSingle();
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class Sprite : NamedObject
|
||||
{
|
||||
public RectangleF m_Rect;
|
||||
public Rectf m_Rect;
|
||||
public Vector2 m_Offset;
|
||||
public Vector4 m_Border;
|
||||
public float m_PixelsToUnits;
|
||||
@@ -187,7 +208,7 @@ namespace AssetStudio
|
||||
|
||||
public Sprite(ObjectReader reader) : base(reader)
|
||||
{
|
||||
m_Rect = reader.ReadRectangleF();
|
||||
m_Rect = new Rectf(reader);
|
||||
m_Offset = reader.ReadVector2();
|
||||
if (version[0] > 4 || (version[0] == 4 && version[1] >= 5)) //4.5 and up
|
||||
{
|
||||
|
||||
@@ -7,19 +7,20 @@ namespace AssetStudio
|
||||
{
|
||||
public PPtr<Texture2D> texture;
|
||||
public PPtr<Texture2D> alphaTexture;
|
||||
public System.Drawing.RectangleF textureRect;
|
||||
public Rectf textureRect;
|
||||
public Vector2 textureRectOffset;
|
||||
public Vector2 atlasRectOffset;
|
||||
public Vector4 uvTransform;
|
||||
public float downscaleMultiplier;
|
||||
public SpriteSettings settingsRaw;
|
||||
public SecondarySpriteTexture[] secondaryTextures;
|
||||
|
||||
public SpriteAtlasData(ObjectReader reader)
|
||||
{
|
||||
var version = reader.version;
|
||||
texture = new PPtr<Texture2D>(reader);
|
||||
alphaTexture = new PPtr<Texture2D>(reader);
|
||||
textureRect = reader.ReadRectangleF();
|
||||
textureRect = new Rectf(reader);
|
||||
textureRectOffset = reader.ReadVector2();
|
||||
if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 2)) //2017.2 and up
|
||||
{
|
||||
@@ -28,6 +29,16 @@ namespace AssetStudio
|
||||
uvTransform = reader.ReadVector4();
|
||||
downscaleMultiplier = reader.ReadSingle();
|
||||
settingsRaw = new SpriteSettings(reader);
|
||||
if (version[0] > 2020 || (version[0] == 2020 && version[1] >= 2)) //2020.2 and up
|
||||
{
|
||||
var secondaryTexturesSize = reader.ReadInt32();
|
||||
secondaryTextures = new SecondarySpriteTexture[secondaryTexturesSize];
|
||||
for (int i = 0; i < secondaryTexturesSize; i++)
|
||||
{
|
||||
secondaryTextures[i] = new SecondarySpriteTexture(reader);
|
||||
}
|
||||
reader.AlignStream();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace AssetStudio
|
||||
|
||||
public TextAsset(ObjectReader reader) : base(reader)
|
||||
{
|
||||
m_Script = reader.ReadBytes(reader.ReadInt32());
|
||||
m_Script = reader.ReadUInt8Array();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,10 @@ namespace AssetStudio
|
||||
{
|
||||
var m_ForcedFallbackFormat = reader.ReadInt32();
|
||||
var m_DownscaleFallback = reader.ReadBoolean();
|
||||
if (version[0] > 2020 || (version[0] == 2020 && version[1] >= 2)) //2020.2 and up
|
||||
{
|
||||
var m_IsAlphaChannelOptional = reader.ReadBoolean();
|
||||
}
|
||||
reader.AlignStream();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,25 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public class StreamingInfo
|
||||
{
|
||||
public uint offset;
|
||||
public ulong offset;
|
||||
public uint size;
|
||||
public string path;
|
||||
|
||||
public StreamingInfo(ObjectReader reader)
|
||||
{
|
||||
offset = reader.ReadUInt32();
|
||||
var version = reader.version;
|
||||
|
||||
if (version[0] >= 2020) //2020.1 and up
|
||||
{
|
||||
offset = reader.ReadUInt64();
|
||||
}
|
||||
else
|
||||
{
|
||||
offset = reader.ReadUInt32();
|
||||
}
|
||||
size = reader.ReadUInt32();
|
||||
path = reader.ReadAlignedString();
|
||||
}
|
||||
@@ -56,7 +60,7 @@ namespace AssetStudio
|
||||
public bool m_MipMap;
|
||||
public int m_MipCount;
|
||||
public GLTextureSettings m_TextureSettings;
|
||||
public Lazy<byte[]> image_data;
|
||||
public ResourceReader image_data;
|
||||
public StreamingInfo m_StreamData;
|
||||
|
||||
public Texture2D(ObjectReader reader) : base(reader)
|
||||
@@ -64,6 +68,10 @@ namespace AssetStudio
|
||||
m_Width = reader.ReadInt32();
|
||||
m_Height = reader.ReadInt32();
|
||||
var m_CompleteImageSize = reader.ReadInt32();
|
||||
if (version[0] >= 2020) //2020.1 and up
|
||||
{
|
||||
var m_MipsStripped = reader.ReadInt32();
|
||||
}
|
||||
m_TextureFormat = (TextureFormat)reader.ReadInt32();
|
||||
if (version[0] < 5 || (version[0] == 5 && version[1] < 2)) //5.2 down
|
||||
{
|
||||
@@ -73,9 +81,29 @@ namespace AssetStudio
|
||||
{
|
||||
m_MipCount = reader.ReadInt32();
|
||||
}
|
||||
var m_IsReadable = reader.ReadBoolean(); //2.6.0 and up
|
||||
var m_ReadAllowed = reader.ReadBoolean(); //3.0.0 - 5.4
|
||||
//bool m_StreamingMipmaps 2018.2 and up
|
||||
if (version[0] > 2 || (version[0] == 2 && version[1] >= 6)) //2.6.0 and up
|
||||
{
|
||||
var m_IsReadable = reader.ReadBoolean();
|
||||
}
|
||||
if (version[0] >= 2020) //2020.1 and up
|
||||
{
|
||||
var m_IsPreProcessed = reader.ReadBoolean();
|
||||
}
|
||||
if (version[0] > 2019 || (version[0] == 2019 && version[1] >= 3)) //2019.3 and up
|
||||
{
|
||||
var m_IgnoreMasterTextureLimit = reader.ReadBoolean();
|
||||
}
|
||||
if (version[0] >= 3) //3.0.0 - 5.4
|
||||
{
|
||||
if (version[0] < 5 || (version[0] == 5 && version[1] <= 4))
|
||||
{
|
||||
var m_ReadAllowed = reader.ReadBoolean();
|
||||
}
|
||||
}
|
||||
if (version[0] > 2018 || (version[0] == 2018 && version[1] >= 2)) //2018.2 and up
|
||||
{
|
||||
var m_StreamingMipmaps = reader.ReadBoolean();
|
||||
}
|
||||
reader.AlignStream();
|
||||
if (version[0] > 2018 || (version[0] == 2018 && version[1] >= 2)) //2018.2 and up
|
||||
{
|
||||
@@ -92,6 +120,11 @@ namespace AssetStudio
|
||||
{
|
||||
var m_ColorSpace = reader.ReadInt32();
|
||||
}
|
||||
if (version[0] > 2020 || (version[0] == 2020 && version[1] >= 2)) //2020.2 and up
|
||||
{
|
||||
var m_PlatformBlob = reader.ReadUInt8Array();
|
||||
reader.AlignStream();
|
||||
}
|
||||
var image_data_size = reader.ReadInt32();
|
||||
if (image_data_size == 0 && ((version[0] == 5 && version[1] >= 3) || version[0] > 5))//5.3.0 and up
|
||||
{
|
||||
@@ -107,7 +140,7 @@ namespace AssetStudio
|
||||
{
|
||||
resourceReader = new ResourceReader(reader, reader.BaseStream.Position, image_data_size);
|
||||
}
|
||||
image_data = new Lazy<byte[]>(resourceReader.GetData);
|
||||
image_data = resourceReader;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,5 +203,14 @@ namespace AssetStudio
|
||||
R8,
|
||||
ETC_RGB4Crunched,
|
||||
ETC2_RGBA8Crunched,
|
||||
ASTC_HDR_4x4,
|
||||
ASTC_HDR_5x5,
|
||||
ASTC_HDR_6x6,
|
||||
ASTC_HDR_8x8,
|
||||
ASTC_HDR_10x10,
|
||||
ASTC_HDR_12x12,
|
||||
RG32,
|
||||
RGB48,
|
||||
RGBA64
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,26 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public class StreamedResource
|
||||
{
|
||||
public string m_Source;
|
||||
public ulong m_Offset;
|
||||
public ulong m_Size;
|
||||
|
||||
public StreamedResource(BinaryReader reader)
|
||||
{
|
||||
m_Source = reader.ReadAlignedString();
|
||||
m_Offset = reader.ReadUInt64();
|
||||
m_Size = reader.ReadUInt64();
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class VideoClip : NamedObject
|
||||
{
|
||||
public Lazy<byte[]> m_VideoData;
|
||||
public ResourceReader m_VideoData;
|
||||
public string m_OriginalPath;
|
||||
public string m_Source;
|
||||
public ulong m_Size;
|
||||
public StreamedResource m_ExternalResources;
|
||||
|
||||
public VideoClip(ObjectReader reader) : base(reader)
|
||||
{
|
||||
@@ -32,22 +41,32 @@ namespace AssetStudio
|
||||
reader.AlignStream();
|
||||
var m_AudioSampleRate = reader.ReadUInt32Array();
|
||||
var m_AudioLanguage = reader.ReadStringArray();
|
||||
//StreamedResource m_ExternalResources
|
||||
m_Source = reader.ReadAlignedString();
|
||||
var m_Offset = reader.ReadUInt64();
|
||||
m_Size = reader.ReadUInt64();
|
||||
if (version[0] >= 2020) //2020.1 and up
|
||||
{
|
||||
var m_VideoShadersSize = reader.ReadInt32();
|
||||
var m_VideoShaders = new PPtr<Shader>[m_VideoShadersSize];
|
||||
for (int i = 0; i < m_VideoShadersSize; i++)
|
||||
{
|
||||
m_VideoShaders[i] = new PPtr<Shader>(reader);
|
||||
}
|
||||
}
|
||||
m_ExternalResources = new StreamedResource(reader);
|
||||
var m_HasSplitAlpha = reader.ReadBoolean();
|
||||
if (version[0] >= 2020) //2020.1 and up
|
||||
{
|
||||
var m_sRGB = reader.ReadBoolean();
|
||||
}
|
||||
|
||||
ResourceReader resourceReader;
|
||||
if (!string.IsNullOrEmpty(m_Source))
|
||||
if (!string.IsNullOrEmpty(m_ExternalResources.m_Source))
|
||||
{
|
||||
resourceReader = new ResourceReader(m_Source, assetsFile, (long)m_Offset, (int)m_Size);
|
||||
resourceReader = new ResourceReader(m_ExternalResources.m_Source, assetsFile, m_ExternalResources.m_Offset, (int)m_ExternalResources.m_Size);
|
||||
}
|
||||
else
|
||||
{
|
||||
resourceReader = new ResourceReader(reader, reader.BaseStream.Position, (int)m_Size);
|
||||
resourceReader = new ResourceReader(reader, reader.BaseStream.Position, (int)m_ExternalResources.m_Size);
|
||||
}
|
||||
m_VideoData = new Lazy<byte[]>(resourceReader.GetData);
|
||||
m_VideoData = resourceReader;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,7 +112,9 @@ namespace AssetStudio
|
||||
{1083, "BoundsInt"},
|
||||
{1093, "m_CorrespondingSourceObject"},
|
||||
{1121, "m_PrefabInstance"},
|
||||
{1138, "m_PrefabAsset"}
|
||||
{1138, "m_PrefabAsset"},
|
||||
{1152, "FileSize"},
|
||||
{1161, "Hash128"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,11 +72,6 @@ namespace AssetStudio
|
||||
return new Vector4(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
|
||||
}
|
||||
|
||||
public static System.Drawing.RectangleF ReadRectangleF(this BinaryReader reader)
|
||||
{
|
||||
return new System.Drawing.RectangleF(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
|
||||
}
|
||||
|
||||
public static Color ReadColor4(this BinaryReader reader)
|
||||
{
|
||||
return new Color(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
|
||||
@@ -102,6 +97,11 @@ namespace AssetStudio
|
||||
return ReadArray(reader.ReadBoolean, reader.ReadInt32());
|
||||
}
|
||||
|
||||
public static byte[] ReadUInt8Array(this BinaryReader reader)
|
||||
{
|
||||
return reader.ReadBytes(reader.ReadInt32());
|
||||
}
|
||||
|
||||
public static ushort[] ReadUInt16Array(this BinaryReader reader)
|
||||
{
|
||||
return ReadArray(reader.ReadUInt16, reader.ReadInt32());
|
||||
@@ -122,6 +122,11 @@ namespace AssetStudio
|
||||
return ReadArray(reader.ReadUInt32, reader.ReadInt32());
|
||||
}
|
||||
|
||||
public static uint[][] ReadUInt32ArrayArray(this BinaryReader reader)
|
||||
{
|
||||
return ReadArray(reader.ReadUInt32Array, reader.ReadInt32());
|
||||
}
|
||||
|
||||
public static uint[] ReadUInt32Array(this BinaryReader reader, int length)
|
||||
{
|
||||
return ReadArray(reader.ReadUInt32, length);
|
||||
|
||||
+32
-18
@@ -134,6 +134,10 @@ namespace AssetStudio
|
||||
public string Path { get; set; }
|
||||
public List<ImportedSubmesh> SubmeshList { get; set; }
|
||||
public List<ImportedBone> BoneList { get; set; }
|
||||
public bool hasNormal { get; set; }
|
||||
public bool[] hasUV { get; set; }
|
||||
public bool hasTangent { get; set; }
|
||||
public bool hasColor { get; set; }
|
||||
}
|
||||
|
||||
public class ImportedSubmesh
|
||||
@@ -145,17 +149,13 @@ namespace AssetStudio
|
||||
|
||||
public class ImportedVertex
|
||||
{
|
||||
public Vector3 Position { get; set; }
|
||||
public Vector3 Vertex { get; set; }
|
||||
public Vector3 Normal { get; set; }
|
||||
public float[][] UV { get; set; }
|
||||
public Vector4 Tangent { get; set; }
|
||||
public Color Color { get; set; }
|
||||
public float[] Weights { get; set; }
|
||||
public int[] BoneIndices { get; set; }
|
||||
public Vector3 Normal { get; set; }
|
||||
public float[] UV { get; set; }
|
||||
public Vector4 Tangent { get; set; }
|
||||
}
|
||||
|
||||
public class ImportedVertexWithColour : ImportedVertex
|
||||
{
|
||||
public Color Colour { get; set; }
|
||||
}
|
||||
|
||||
public class ImportedFace
|
||||
@@ -205,7 +205,7 @@ namespace AssetStudio
|
||||
public class ImportedKeyframedAnimation
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
||||
public float SampleRate { get; set; }
|
||||
public List<ImportedAnimationKeyframedTrack> TrackList { get; set; }
|
||||
|
||||
public ImportedAnimationKeyframedTrack FindTrack(string path)
|
||||
@@ -227,14 +227,13 @@ namespace AssetStudio
|
||||
public List<ImportedKeyframe<Vector3>> Scalings = new List<ImportedKeyframe<Vector3>>();
|
||||
public List<ImportedKeyframe<Vector3>> Rotations = new List<ImportedKeyframe<Vector3>>();
|
||||
public List<ImportedKeyframe<Vector3>> Translations = new List<ImportedKeyframe<Vector3>>();
|
||||
public ImportedBlendShape BlendShape;
|
||||
}
|
||||
|
||||
public class ImportedKeyframe<T>
|
||||
{
|
||||
public float time { get; set; }
|
||||
public T value { get; set; }
|
||||
public T inSlope { get; set; }
|
||||
public T outSlope { get; set; }
|
||||
|
||||
public ImportedKeyframe(float time, T value)
|
||||
{
|
||||
@@ -243,21 +242,36 @@ namespace AssetStudio
|
||||
}
|
||||
}
|
||||
|
||||
public class ImportedBlendShape
|
||||
{
|
||||
public string ChannelName;
|
||||
public List<ImportedKeyframe<float>> Keyframes = new List<ImportedKeyframe<float>>();
|
||||
}
|
||||
|
||||
public class ImportedMorph
|
||||
{
|
||||
public string Path { get; set; }
|
||||
public string ClipName { get; set; }
|
||||
public List<Tuple<float, int, int>> Channels { get; set; }
|
||||
public List<ImportedMorphChannel> Channels { get; set; }
|
||||
}
|
||||
|
||||
public class ImportedMorphChannel
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public List<ImportedMorphKeyframe> KeyframeList { get; set; }
|
||||
public List<ushort> MorphedVertexIndices { get; set; }
|
||||
}
|
||||
|
||||
public class ImportedMorphKeyframe
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public List<ImportedVertex> VertexList { get; set; }
|
||||
public List<ushort> MorphedVertexIndices { get; set; }
|
||||
public bool hasNormals { get; set; }
|
||||
public bool hasTangents { get; set; }
|
||||
public float Weight { get; set; }
|
||||
public List<ImportedMorphVertex> VertexList { get; set; }
|
||||
}
|
||||
|
||||
public class ImportedMorphVertex
|
||||
{
|
||||
public uint Index { get; set; }
|
||||
public ImportedVertex Vertex { get; set; }
|
||||
}
|
||||
|
||||
public static class ImportedHelpers
|
||||
|
||||
@@ -8,7 +8,8 @@ namespace AssetStudio
|
||||
{
|
||||
AssetsFile,
|
||||
BundleFile,
|
||||
WebFile
|
||||
WebFile,
|
||||
ResourceFile
|
||||
}
|
||||
|
||||
public static class ImportHelper
|
||||
@@ -19,8 +20,8 @@ namespace AssetStudio
|
||||
foreach (var splitFile in splitFiles)
|
||||
{
|
||||
var destFile = Path.GetFileNameWithoutExtension(splitFile);
|
||||
var destPath = Path.GetDirectoryName(splitFile) + "\\";
|
||||
var destFull = destPath + destFile;
|
||||
var destPath = Path.GetDirectoryName(splitFile);
|
||||
var destFull = Path.Combine(destPath, destFile);
|
||||
if (!File.Exists(destFull))
|
||||
{
|
||||
var splitParts = Directory.GetFiles(destPath, destFile + ".split*");
|
||||
@@ -42,7 +43,7 @@ namespace AssetStudio
|
||||
public static string[] ProcessingSplitFiles(List<string> selectFile)
|
||||
{
|
||||
var splitFiles = selectFile.Where(x => x.Contains(".split"))
|
||||
.Select(x => Path.GetDirectoryName(x) + "\\" + Path.GetFileNameWithoutExtension(x))
|
||||
.Select(x => Path.Combine(Path.GetDirectoryName(x), Path.GetFileNameWithoutExtension(x)))
|
||||
.Distinct()
|
||||
.ToList();
|
||||
selectFile.RemoveAll(x => x.Contains(".split"));
|
||||
@@ -64,7 +65,7 @@ namespace AssetStudio
|
||||
|
||||
public static FileType CheckFileType(string fileName, out EndianBinaryReader reader)
|
||||
{
|
||||
reader = new EndianBinaryReader(File.OpenRead(fileName));
|
||||
reader = new EndianBinaryReader(File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite));
|
||||
return CheckFileType(reader);
|
||||
}
|
||||
|
||||
@@ -76,7 +77,7 @@ namespace AssetStudio
|
||||
{
|
||||
case "UnityWeb":
|
||||
case "UnityRaw":
|
||||
case "\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA":
|
||||
case "UnityArchive":
|
||||
case "UnityFS":
|
||||
return FileType.BundleFile;
|
||||
case "UnityWebData1.0":
|
||||
@@ -96,7 +97,14 @@ namespace AssetStudio
|
||||
{
|
||||
return FileType.WebFile;
|
||||
}
|
||||
return FileType.AssetsFile;
|
||||
if (SerializedFile.IsSerializedFile(reader))
|
||||
{
|
||||
return FileType.AssetsFile;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FileType.ResourceFile;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,5 +14,13 @@ namespace AssetStudio
|
||||
public static void Info(string message) => Default.Log(LoggerEvent.Info, message);
|
||||
public static void Warning(string message) => Default.Log(LoggerEvent.Warning, message);
|
||||
public static void Error(string message) => Default.Log(LoggerEvent.Error, message);
|
||||
|
||||
public static void Error(string message, Exception e)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine(message);
|
||||
sb.AppendLine(e.ToString());
|
||||
Default.Log(LoggerEvent.Error, sb.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,6 +89,8 @@ namespace AssetStudio
|
||||
|
||||
public static Vector3 Zero => new Vector3();
|
||||
|
||||
public static Vector3 One => new Vector3(1.0f, 1.0f, 1.0f);
|
||||
|
||||
public static Vector3 operator +(Vector3 a, Vector3 b)
|
||||
{
|
||||
return new Vector3(a.X + b.X, a.Y + b.Y, a.Z + b.Z);
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace AssetStudio
|
||||
{
|
||||
public class ObjectInfo
|
||||
{
|
||||
public uint byteStart;
|
||||
public long byteStart;
|
||||
public uint byteSize;
|
||||
public int typeID;
|
||||
public int classID;
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace AssetStudio
|
||||
{
|
||||
public SerializedFile assetsFile;
|
||||
public long m_PathID;
|
||||
public uint byteStart;
|
||||
public long byteStart;
|
||||
public uint byteSize;
|
||||
public ClassIDType type;
|
||||
public SerializedType serializedType;
|
||||
|
||||
@@ -10,7 +10,7 @@ using System.Runtime.InteropServices;
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("AssetStudio")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2018")]
|
||||
[assembly: AssemblyCopyright("Copyright © Perfare 2018-2020")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
@@ -20,7 +20,7 @@ using System.Runtime.InteropServices;
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
|
||||
[assembly: Guid("af56b63c-1764-41b7-9e60-8d485422ac3b")]
|
||||
[assembly: Guid("7662f8c2-7bfd-442e-a948-a43b4f7eb06e")]
|
||||
|
||||
// 程序集的版本信息由下列四个值组成:
|
||||
//
|
||||
@@ -29,7 +29,7 @@ using System.Runtime.InteropServices;
|
||||
// 生成号
|
||||
// 修订号
|
||||
//
|
||||
// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号
|
||||
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
|
||||
//通过使用 "*",如下所示:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
|
||||
@@ -12,12 +12,12 @@ namespace AssetStudio
|
||||
private BinaryReader reader;
|
||||
|
||||
|
||||
public ResourceReader(string path, SerializedFile assetsFile, long offset, int size)
|
||||
public ResourceReader(string path, SerializedFile assetsFile, ulong offset, int size)
|
||||
{
|
||||
needSearch = true;
|
||||
this.path = path;
|
||||
this.assetsFile = assetsFile;
|
||||
this.offset = offset;
|
||||
this.offset = (long)offset;
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
@@ -34,17 +34,18 @@ namespace AssetStudio
|
||||
{
|
||||
var resourceFileName = Path.GetFileName(path);
|
||||
|
||||
if (assetsFile.assetsManager.resourceFileReaders.TryGetValue(resourceFileName.ToUpper(), out var reader))
|
||||
if (assetsFile.assetsManager.resourceFileReaders.TryGetValue(resourceFileName, out reader))
|
||||
{
|
||||
reader.Position = offset;
|
||||
needSearch = false;
|
||||
reader.BaseStream.Position = offset;
|
||||
return reader.ReadBytes(size);
|
||||
}
|
||||
|
||||
var currentDirectory = Path.GetDirectoryName(assetsFile.fullName);
|
||||
var resourceFilePath = currentDirectory + "\\" + resourceFileName;
|
||||
var assetsFileDirectory = Path.GetDirectoryName(assetsFile.fullName);
|
||||
var resourceFilePath = assetsFileDirectory + Path.DirectorySeparatorChar + resourceFileName;
|
||||
if (!File.Exists(resourceFilePath))
|
||||
{
|
||||
var findFiles = Directory.GetFiles(currentDirectory, resourceFileName, SearchOption.AllDirectories);
|
||||
var findFiles = Directory.GetFiles(assetsFileDirectory, resourceFileName, SearchOption.AllDirectories);
|
||||
if (findFiles.Length > 0)
|
||||
{
|
||||
resourceFilePath = findFiles[0];
|
||||
@@ -52,11 +53,11 @@ namespace AssetStudio
|
||||
}
|
||||
if (File.Exists(resourceFilePath))
|
||||
{
|
||||
using (var resourceReader = new BinaryReader(File.OpenRead(resourceFilePath)))
|
||||
{
|
||||
resourceReader.BaseStream.Position = offset;
|
||||
return resourceReader.ReadBytes(size);
|
||||
}
|
||||
reader = new BinaryReader(File.OpenRead(resourceFilePath));
|
||||
needSearch = false;
|
||||
assetsFile.assetsManager.resourceFileReaders.Add(resourceFileName, reader);
|
||||
reader.BaseStream.Position = offset;
|
||||
return reader.ReadBytes(size);
|
||||
}
|
||||
|
||||
throw new FileNotFoundException($"Can't find the resource file {resourceFileName}");
|
||||
|
||||
+118
-34
@@ -13,10 +13,10 @@ namespace AssetStudio
|
||||
public string fullName;
|
||||
public string originalPath;
|
||||
public string fileName;
|
||||
public string upperFileName;
|
||||
public int[] version = { 0, 0, 0, 0 };
|
||||
public BuildType buildType;
|
||||
public Dictionary<long, Object> Objects;
|
||||
public List<Object> Objects;
|
||||
public Dictionary<long, Object> ObjectsDic;
|
||||
|
||||
public SerializedFileHeader header;
|
||||
private EndianType m_FileEndianess;
|
||||
@@ -24,6 +24,7 @@ namespace AssetStudio
|
||||
public BuildTarget m_TargetPlatform = BuildTarget.UnknownPlatform;
|
||||
private bool m_EnableTypeTree = true;
|
||||
public List<SerializedType> m_Types;
|
||||
public List<SerializedType> m_RefTypes;
|
||||
public List<ObjectInfo> m_Objects;
|
||||
private List<LocalSerializedObjectIdentifier> m_ScriptTypes;
|
||||
public List<FileIdentifier> m_Externals;
|
||||
@@ -34,7 +35,6 @@ namespace AssetStudio
|
||||
this.reader = reader;
|
||||
this.fullName = fullName;
|
||||
fileName = Path.GetFileName(fullName);
|
||||
upperFileName = fileName.ToUpper();
|
||||
|
||||
//ReadHeader
|
||||
header = new SerializedFileHeader();
|
||||
@@ -55,6 +55,14 @@ namespace AssetStudio
|
||||
m_FileEndianess = (EndianType)reader.ReadByte();
|
||||
}
|
||||
|
||||
if (header.m_Version >= 22)
|
||||
{
|
||||
header.m_MetadataSize = reader.ReadUInt32();
|
||||
header.m_FileSize = reader.ReadInt64();
|
||||
header.m_DataOffset = reader.ReadInt64();
|
||||
reader.ReadInt64(); // unknown
|
||||
}
|
||||
|
||||
//ReadMetadata
|
||||
if (m_FileEndianess == EndianType.LittleEndian)
|
||||
{
|
||||
@@ -86,18 +94,25 @@ namespace AssetStudio
|
||||
m_Types.Add(ReadSerializedType());
|
||||
}
|
||||
|
||||
var bigIDEnabled = 0;
|
||||
if (header.m_Version >= 7 && header.m_Version < 14)
|
||||
{
|
||||
var bigIDEnabled = reader.ReadInt32();
|
||||
bigIDEnabled = reader.ReadInt32();
|
||||
}
|
||||
|
||||
//ReadObjects
|
||||
int objectCount = reader.ReadInt32();
|
||||
m_Objects = new List<ObjectInfo>(objectCount);
|
||||
Objects = new List<Object>(objectCount);
|
||||
ObjectsDic = new Dictionary<long, Object>(objectCount);
|
||||
for (int i = 0; i < objectCount; i++)
|
||||
{
|
||||
var objectInfo = new ObjectInfo();
|
||||
if (header.m_Version < 14)
|
||||
if (bigIDEnabled != 0)
|
||||
{
|
||||
objectInfo.m_PathID = reader.ReadInt64();
|
||||
}
|
||||
else if (header.m_Version < 14)
|
||||
{
|
||||
objectInfo.m_PathID = reader.ReadInt32();
|
||||
}
|
||||
@@ -106,7 +121,12 @@ namespace AssetStudio
|
||||
reader.AlignStream();
|
||||
objectInfo.m_PathID = reader.ReadInt64();
|
||||
}
|
||||
objectInfo.byteStart = reader.ReadUInt32();
|
||||
|
||||
if (header.m_Version >= 22)
|
||||
objectInfo.byteStart = reader.ReadInt64();
|
||||
else
|
||||
objectInfo.byteStart = reader.ReadUInt32();
|
||||
|
||||
objectInfo.byteStart += header.m_DataOffset;
|
||||
objectInfo.byteSize = reader.ReadUInt32();
|
||||
objectInfo.typeID = reader.ReadInt32();
|
||||
@@ -114,7 +134,6 @@ namespace AssetStudio
|
||||
{
|
||||
objectInfo.classID = reader.ReadUInt16();
|
||||
objectInfo.serializedType = m_Types.Find(x => x.classID == objectInfo.typeID);
|
||||
var isDestroyed = reader.ReadUInt16();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -122,6 +141,16 @@ namespace AssetStudio
|
||||
objectInfo.serializedType = type;
|
||||
objectInfo.classID = type.classID;
|
||||
}
|
||||
if (header.m_Version < 11)
|
||||
{
|
||||
var isDestroyed = reader.ReadUInt16();
|
||||
}
|
||||
if (header.m_Version >= 11 && header.m_Version < 17)
|
||||
{
|
||||
var m_ScriptTypeIndex = reader.ReadInt16();
|
||||
if (objectInfo.serializedType != null)
|
||||
objectInfo.serializedType.m_ScriptTypeIndex = m_ScriptTypeIndex;
|
||||
}
|
||||
if (header.m_Version == 15 || header.m_Version == 16)
|
||||
{
|
||||
var stripped = reader.ReadByte();
|
||||
@@ -169,10 +198,22 @@ namespace AssetStudio
|
||||
m_Externals.Add(m_External);
|
||||
}
|
||||
|
||||
if (header.m_Version >= 20)
|
||||
{
|
||||
int refTypesCount = reader.ReadInt32();
|
||||
m_RefTypes = new List<SerializedType>(refTypesCount);
|
||||
for (int i = 0; i < refTypesCount; i++)
|
||||
{
|
||||
m_RefTypes.Add(ReadSerializedType());
|
||||
}
|
||||
}
|
||||
|
||||
if (header.m_Version >= 5)
|
||||
{
|
||||
//var userInformation = reader.ReadStringToNull();
|
||||
var userInformation = reader.ReadStringToNull();
|
||||
}
|
||||
|
||||
//reader.AlignStream(16);
|
||||
}
|
||||
|
||||
public void SetVersion(string stringVersion)
|
||||
@@ -214,13 +255,18 @@ namespace AssetStudio
|
||||
var typeTree = new List<TypeTreeNode>();
|
||||
if (header.m_Version >= 12 || header.m_Version == 10)
|
||||
{
|
||||
ReadTypeTree5(typeTree);
|
||||
TypeTreeBlobRead(typeTree);
|
||||
}
|
||||
else
|
||||
{
|
||||
ReadTypeTree(typeTree);
|
||||
}
|
||||
|
||||
if (header.m_Version >= 21)
|
||||
{
|
||||
type.m_TypeDependencies = reader.ReadInt32Array();
|
||||
}
|
||||
|
||||
type.m_Nodes = typeTree;
|
||||
}
|
||||
|
||||
@@ -257,42 +303,37 @@ namespace AssetStudio
|
||||
}
|
||||
}
|
||||
|
||||
private void ReadTypeTree5(List<TypeTreeNode> typeTree)
|
||||
private void TypeTreeBlobRead(List<TypeTreeNode> typeTree)
|
||||
{
|
||||
int numberOfNodes = reader.ReadInt32();
|
||||
int stringBufferSize = reader.ReadInt32();
|
||||
|
||||
var nodeSize = 24;
|
||||
if (header.m_Version > 17)
|
||||
for (int i = 0; i < numberOfNodes; i++)
|
||||
{
|
||||
nodeSize = 32;
|
||||
var typeTreeNode = new TypeTreeNode();
|
||||
typeTree.Add(typeTreeNode);
|
||||
typeTreeNode.m_Version = reader.ReadUInt16();
|
||||
typeTreeNode.m_Level = reader.ReadByte();
|
||||
typeTreeNode.m_IsArray = reader.ReadBoolean() ? 1 : 0;
|
||||
typeTreeNode.m_TypeStrOffset = reader.ReadUInt32();
|
||||
typeTreeNode.m_NameStrOffset = reader.ReadUInt32();
|
||||
typeTreeNode.m_ByteSize = reader.ReadInt32();
|
||||
typeTreeNode.m_Index = reader.ReadInt32();
|
||||
typeTreeNode.m_MetaFlag = reader.ReadInt32();
|
||||
if (header.m_Version >= 19)
|
||||
{
|
||||
typeTreeNode.m_RefTypeHash = reader.ReadUInt64();
|
||||
}
|
||||
}
|
||||
reader.Position += numberOfNodes * nodeSize;
|
||||
using (var stringBufferReader = new BinaryReader(new MemoryStream(reader.ReadBytes(stringBufferSize))))
|
||||
var m_StringBuffer = reader.ReadBytes(stringBufferSize);
|
||||
|
||||
using (var stringBufferReader = new BinaryReader(new MemoryStream(m_StringBuffer)))
|
||||
{
|
||||
reader.Position -= numberOfNodes * nodeSize + stringBufferSize;
|
||||
for (int i = 0; i < numberOfNodes; i++)
|
||||
{
|
||||
var typeTreeNode = new TypeTreeNode();
|
||||
typeTree.Add(typeTreeNode);
|
||||
typeTreeNode.m_Version = reader.ReadUInt16();
|
||||
typeTreeNode.m_Level = reader.ReadByte();
|
||||
typeTreeNode.m_IsArray = reader.ReadBoolean() ? 1 : 0;
|
||||
typeTreeNode.m_TypeStrOffset = reader.ReadUInt32();
|
||||
typeTreeNode.m_NameStrOffset = reader.ReadUInt32();
|
||||
typeTreeNode.m_ByteSize = reader.ReadInt32();
|
||||
typeTreeNode.m_Index = reader.ReadInt32();
|
||||
typeTreeNode.m_MetaFlag = reader.ReadInt32();
|
||||
|
||||
if (header.m_Version > 17)
|
||||
{
|
||||
reader.Position += 8;
|
||||
}
|
||||
|
||||
var typeTreeNode = typeTree[i];
|
||||
typeTreeNode.m_Type = ReadString(stringBufferReader, typeTreeNode.m_TypeStrOffset);
|
||||
typeTreeNode.m_Name = ReadString(stringBufferReader, typeTreeNode.m_NameStrOffset);
|
||||
}
|
||||
reader.Position += stringBufferSize;
|
||||
}
|
||||
|
||||
string ReadString(BinaryReader stringBufferReader, uint value)
|
||||
@@ -311,5 +352,48 @@ namespace AssetStudio
|
||||
return offset.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
public void AddObject(Object obj)
|
||||
{
|
||||
Objects.Add(obj);
|
||||
ObjectsDic.Add(obj.m_PathID, obj);
|
||||
}
|
||||
|
||||
public static bool IsSerializedFile(EndianBinaryReader reader)
|
||||
{
|
||||
var fileSize = reader.BaseStream.Length;
|
||||
if (fileSize < 20)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
var m_MetadataSize = reader.ReadUInt32();
|
||||
long m_FileSize = reader.ReadUInt32();
|
||||
var m_Version = reader.ReadUInt32();
|
||||
long m_DataOffset = reader.ReadUInt32();
|
||||
var m_Endianess = reader.ReadByte();
|
||||
var m_Reserved = reader.ReadBytes(3);
|
||||
if (m_Version >= 22)
|
||||
{
|
||||
if (fileSize < 48)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
m_MetadataSize = reader.ReadUInt32();
|
||||
m_FileSize = reader.ReadInt64();
|
||||
m_DataOffset = reader.ReadInt64();
|
||||
}
|
||||
if (m_FileSize != fileSize)
|
||||
{
|
||||
reader.Position = 0;
|
||||
return false;
|
||||
}
|
||||
if (m_DataOffset > fileSize)
|
||||
{
|
||||
reader.Position = 0;
|
||||
return false;
|
||||
}
|
||||
reader.Position = 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,9 +8,9 @@ namespace AssetStudio
|
||||
public class SerializedFileHeader
|
||||
{
|
||||
public uint m_MetadataSize;
|
||||
public uint m_FileSize;
|
||||
public long m_FileSize;
|
||||
public uint m_Version;
|
||||
public uint m_DataOffset;
|
||||
public long m_DataOffset;
|
||||
public byte m_Endianess;
|
||||
public byte[] m_Reserved;
|
||||
}
|
||||
|
||||
@@ -13,5 +13,6 @@ namespace AssetStudio
|
||||
public List<TypeTreeNode> m_Nodes;
|
||||
public byte[] m_ScriptID; //Hash128
|
||||
public byte[] m_OldTypeHash; //Hash128
|
||||
public int[] m_TypeDependencies;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,15 +34,16 @@ namespace AssetStudio
|
||||
return newOutStream;
|
||||
}
|
||||
|
||||
public static void StreamDecompress(Stream inStream, Stream outStream, long inSize, long outSize)
|
||||
public static void StreamDecompress(Stream compressedStream, Stream decompressedStream, long compressedSize, long decompressedSize)
|
||||
{
|
||||
var basePosition = compressedStream.Position;
|
||||
var decoder = new Decoder();
|
||||
var properties = new byte[5];
|
||||
if (inStream.Read(properties, 0, 5) != 5)
|
||||
if (compressedStream.Read(properties, 0, 5) != 5)
|
||||
throw new Exception("input .lzma is too short");
|
||||
decoder.SetDecoderProperties(properties);
|
||||
inSize -= 5L;
|
||||
decoder.Code(inStream, outStream, inSize, outSize, null);
|
||||
decoder.Code(compressedStream, decompressedStream, compressedSize - 5, decompressedSize, null);
|
||||
compressedStream.Position = basePosition + compressedSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
using System.IO;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public class StreamFile
|
||||
{
|
||||
public string path;
|
||||
public string fileName;
|
||||
public Stream stream;
|
||||
}
|
||||
}
|
||||
+68
-195
@@ -1,19 +1,24 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public static class TypeTreeHelper
|
||||
{
|
||||
public static void ReadTypeString(StringBuilder sb, List<TypeTreeNode> members, BinaryReader reader)
|
||||
public static void ReadTypeString(StringBuilder sb, List<TypeTreeNode> members, ObjectReader reader)
|
||||
{
|
||||
reader.Reset();
|
||||
for (int i = 0; i < members.Count; i++)
|
||||
{
|
||||
ReadStringValue(sb, members, reader, ref i);
|
||||
}
|
||||
var readed = reader.Position - reader.byteStart;
|
||||
if (readed != reader.byteSize)
|
||||
{
|
||||
Logger.Info($"Error while read type, read {readed} bytes but expected {reader.byteSize} bytes");
|
||||
}
|
||||
}
|
||||
|
||||
private static void ReadStringValue(StringBuilder sb, List<TypeTreeNode> members, BinaryReader reader, ref int i)
|
||||
@@ -31,6 +36,7 @@ namespace AssetStudio
|
||||
value = reader.ReadSByte();
|
||||
break;
|
||||
case "UInt8":
|
||||
case "char":
|
||||
value = reader.ReadByte();
|
||||
break;
|
||||
case "short":
|
||||
@@ -56,6 +62,7 @@ namespace AssetStudio
|
||||
break;
|
||||
case "UInt64":
|
||||
case "unsigned long long":
|
||||
case "FileSize":
|
||||
value = reader.ReadUInt64();
|
||||
break;
|
||||
case "float":
|
||||
@@ -73,26 +80,6 @@ namespace AssetStudio
|
||||
sb.AppendFormat("{0}{1} {2} = \"{3}\"\r\n", (new string('\t', level)), varTypeStr, varNameStr, str);
|
||||
i += 3;
|
||||
break;
|
||||
case "vector":
|
||||
{
|
||||
if ((members[i + 1].m_MetaFlag & 0x4000) != 0)
|
||||
align = true;
|
||||
append = false;
|
||||
sb.AppendFormat("{0}{1} {2}\r\n", (new string('\t', level)), varTypeStr, varNameStr);
|
||||
sb.AppendFormat("{0}{1} {2}\r\n", (new string('\t', level + 1)), "Array", "Array");
|
||||
var size = reader.ReadInt32();
|
||||
sb.AppendFormat("{0}{1} {2} = {3}\r\n", (new string('\t', level + 1)), "int", "size", size);
|
||||
var vector = GetMembers(members, level, i);
|
||||
i += vector.Count - 1;
|
||||
vector.RemoveRange(0, 3);
|
||||
for (int j = 0; j < size; j++)
|
||||
{
|
||||
sb.AppendFormat("{0}[{1}]\r\n", (new string('\t', level + 2)), j);
|
||||
int tmp = 0;
|
||||
ReadStringValue(sb, vector, reader, ref tmp);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "map":
|
||||
{
|
||||
if ((members[i + 1].m_MetaFlag & 0x4000) != 0)
|
||||
@@ -102,12 +89,11 @@ namespace AssetStudio
|
||||
sb.AppendFormat("{0}{1} {2}\r\n", (new string('\t', level + 1)), "Array", "Array");
|
||||
var size = reader.ReadInt32();
|
||||
sb.AppendFormat("{0}{1} {2} = {3}\r\n", (new string('\t', level + 1)), "int", "size", size);
|
||||
var map = GetMembers(members, level, i);
|
||||
var map = GetMembers(members, i);
|
||||
i += map.Count - 1;
|
||||
map.RemoveRange(0, 4);
|
||||
var first = GetMembers(map, map[0].m_Level, 0);
|
||||
map.RemoveRange(0, first.Count);
|
||||
var second = map;
|
||||
var first = GetMembers(map, 4);
|
||||
var next = 4 + first.Count;
|
||||
var second = GetMembers(map, next);
|
||||
for (int j = 0; j < size; j++)
|
||||
{
|
||||
sb.AppendFormat("{0}[{1}]\r\n", (new string('\t', level + 2)), j);
|
||||
@@ -131,20 +117,37 @@ namespace AssetStudio
|
||||
}
|
||||
default:
|
||||
{
|
||||
if (i != members.Count && members[i + 1].m_Type == "Array")
|
||||
if (i < members.Count - 1 && members[i + 1].m_Type == "Array") //Array
|
||||
{
|
||||
goto case "vector";
|
||||
if ((members[i + 1].m_MetaFlag & 0x4000) != 0)
|
||||
align = true;
|
||||
append = false;
|
||||
sb.AppendFormat("{0}{1} {2}\r\n", (new string('\t', level)), varTypeStr, varNameStr);
|
||||
sb.AppendFormat("{0}{1} {2}\r\n", (new string('\t', level + 1)), "Array", "Array");
|
||||
var size = reader.ReadInt32();
|
||||
sb.AppendFormat("{0}{1} {2} = {3}\r\n", (new string('\t', level + 1)), "int", "size", size);
|
||||
var vector = GetMembers(members, i);
|
||||
i += vector.Count - 1;
|
||||
for (int j = 0; j < size; j++)
|
||||
{
|
||||
sb.AppendFormat("{0}[{1}]\r\n", (new string('\t', level + 2)), j);
|
||||
int tmp = 3;
|
||||
ReadStringValue(sb, vector, reader, ref tmp);
|
||||
}
|
||||
break;
|
||||
}
|
||||
append = false;
|
||||
sb.AppendFormat("{0}{1} {2}\r\n", (new string('\t', level)), varTypeStr, varNameStr);
|
||||
var @class = GetMembers(members, level, i);
|
||||
@class.RemoveAt(0);
|
||||
i += @class.Count;
|
||||
for (int j = 0; j < @class.Count; j++)
|
||||
else //Class
|
||||
{
|
||||
ReadStringValue(sb, @class, reader, ref j);
|
||||
append = false;
|
||||
sb.AppendFormat("{0}{1} {2}\r\n", (new string('\t', level)), varTypeStr, varNameStr);
|
||||
var @class = GetMembers(members, i);
|
||||
i += @class.Count - 1;
|
||||
for (int j = 1; j < @class.Count; j++)
|
||||
{
|
||||
ReadStringValue(sb, @class, reader, ref j);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (append)
|
||||
@@ -153,22 +156,27 @@ namespace AssetStudio
|
||||
reader.AlignStream();
|
||||
}
|
||||
|
||||
public static UType ReadUType(List<TypeTreeNode> members, BinaryReader reader)
|
||||
public static OrderedDictionary ReadType(List<TypeTreeNode> members, ObjectReader reader)
|
||||
{
|
||||
var obj = new UType();
|
||||
reader.Reset();
|
||||
var obj = new OrderedDictionary();
|
||||
for (int i = 1; i < members.Count; i++)
|
||||
{
|
||||
var member = members[i];
|
||||
var varNameStr = member.m_Name;
|
||||
obj[varNameStr] = ReadValue(members, reader, ref i);
|
||||
}
|
||||
var readed = reader.Position - reader.byteStart;
|
||||
if (readed != reader.byteSize)
|
||||
{
|
||||
Logger.Info($"Error while read type, read {readed} bytes but expected {reader.byteSize} bytes");
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
private static object ReadValue(List<TypeTreeNode> members, BinaryReader reader, ref int i)
|
||||
{
|
||||
var member = members[i];
|
||||
var level = member.m_Level;
|
||||
var varTypeStr = member.m_Type;
|
||||
object value;
|
||||
var align = (member.m_MetaFlag & 0x4000) != 0;
|
||||
@@ -178,6 +186,7 @@ namespace AssetStudio
|
||||
value = reader.ReadSByte();
|
||||
break;
|
||||
case "UInt8":
|
||||
case "char":
|
||||
value = reader.ReadByte();
|
||||
break;
|
||||
case "short":
|
||||
@@ -203,6 +212,7 @@ namespace AssetStudio
|
||||
break;
|
||||
case "UInt64":
|
||||
case "unsigned long long":
|
||||
case "FileSize":
|
||||
value = reader.ReadUInt64();
|
||||
break;
|
||||
case "float":
|
||||
@@ -222,14 +232,13 @@ namespace AssetStudio
|
||||
{
|
||||
if ((members[i + 1].m_MetaFlag & 0x4000) != 0)
|
||||
align = true;
|
||||
var map = GetMembers(members, i);
|
||||
i += map.Count - 1;
|
||||
var first = GetMembers(map, 4);
|
||||
var next = 4 + first.Count;
|
||||
var second = GetMembers(map, next);
|
||||
var size = reader.ReadInt32();
|
||||
var dic = new List<KeyValuePair<object, object>>(size);
|
||||
var map = GetMembers(members, level, i);
|
||||
i += map.Count - 1;
|
||||
map.RemoveRange(0, 4);
|
||||
var first = GetMembers(map, map[0].m_Level, 0);
|
||||
map.RemoveRange(0, first.Count);
|
||||
var second = map;
|
||||
for (int j = 0; j < size; j++)
|
||||
{
|
||||
int tmp1 = 0;
|
||||
@@ -248,18 +257,17 @@ namespace AssetStudio
|
||||
}
|
||||
default:
|
||||
{
|
||||
if (i != members.Count && members[i + 1].m_Type == "Array") //Array
|
||||
if (i < members.Count - 1 && members[i + 1].m_Type == "Array") //Array
|
||||
{
|
||||
if ((members[i + 1].m_MetaFlag & 0x4000) != 0)
|
||||
align = true;
|
||||
var vector = GetMembers(members, i);
|
||||
i += vector.Count - 1;
|
||||
var size = reader.ReadInt32();
|
||||
var list = new List<object>(size);
|
||||
var vector = GetMembers(members, level, i);
|
||||
i += vector.Count - 1;
|
||||
vector.RemoveRange(0, 3);
|
||||
for (int j = 0; j < size; j++)
|
||||
{
|
||||
int tmp = 0;
|
||||
int tmp = 3;
|
||||
list.Add(ReadValue(vector, reader, ref tmp));
|
||||
}
|
||||
value = list;
|
||||
@@ -267,11 +275,10 @@ namespace AssetStudio
|
||||
}
|
||||
else //Class
|
||||
{
|
||||
var @class = GetMembers(members, level, i);
|
||||
@class.RemoveAt(0);
|
||||
i += @class.Count;
|
||||
var obj = new UType();
|
||||
for (int j = 0; j < @class.Count; j++)
|
||||
var @class = GetMembers(members, i);
|
||||
i += @class.Count - 1;
|
||||
var obj = new OrderedDictionary();
|
||||
for (int j = 1; j < @class.Count; j++)
|
||||
{
|
||||
var classmember = @class[j];
|
||||
var name = classmember.m_Name;
|
||||
@@ -287,10 +294,11 @@ namespace AssetStudio
|
||||
return value;
|
||||
}
|
||||
|
||||
private static List<TypeTreeNode> GetMembers(List<TypeTreeNode> members, int level, int index)
|
||||
private static List<TypeTreeNode> GetMembers(List<TypeTreeNode> members, int index)
|
||||
{
|
||||
var member2 = new List<TypeTreeNode>();
|
||||
member2.Add(members[0]);
|
||||
member2.Add(members[index]);
|
||||
var level = members[index].m_Level;
|
||||
for (int i = index + 1; i < members.Count; i++)
|
||||
{
|
||||
var member = members[i];
|
||||
@@ -303,140 +311,5 @@ namespace AssetStudio
|
||||
}
|
||||
return member2;
|
||||
}
|
||||
|
||||
public static byte[] WriteUType(UType obj, List<TypeTreeNode> members)
|
||||
{
|
||||
var stream = new MemoryStream();
|
||||
var write = new BinaryWriter(stream);
|
||||
for (int i = 0; i < members.Count; i++)
|
||||
{
|
||||
var member = members[i];
|
||||
var varNameStr = member.m_Name;
|
||||
WriteValue(obj[varNameStr], members, write, ref i);
|
||||
}
|
||||
return stream.ToArray();
|
||||
}
|
||||
|
||||
private static void WriteValue(object value, List<TypeTreeNode> members, BinaryWriter write, ref int i)
|
||||
{
|
||||
var member = members[i];
|
||||
var level = member.m_Level;
|
||||
var varTypeStr = member.m_Type;
|
||||
var align = (member.m_MetaFlag & 0x4000) != 0;
|
||||
switch (varTypeStr)
|
||||
{
|
||||
case "SInt8":
|
||||
write.Write((sbyte)value);
|
||||
break;
|
||||
case "UInt8":
|
||||
write.Write((byte)value);
|
||||
break;
|
||||
case "short":
|
||||
case "SInt16":
|
||||
write.Write((short)value);
|
||||
break;
|
||||
case "UInt16":
|
||||
case "unsigned short":
|
||||
write.Write((ushort)value);
|
||||
break;
|
||||
case "int":
|
||||
case "SInt32":
|
||||
write.Write((int)value);
|
||||
break;
|
||||
case "UInt32":
|
||||
case "unsigned int":
|
||||
case "Type*":
|
||||
write.Write((uint)value);
|
||||
break;
|
||||
case "long long":
|
||||
case "SInt64":
|
||||
write.Write((long)value);
|
||||
break;
|
||||
case "UInt64":
|
||||
case "unsigned long long":
|
||||
write.Write((ulong)value);
|
||||
break;
|
||||
case "float":
|
||||
write.Write((float)value);
|
||||
break;
|
||||
case "double":
|
||||
write.Write((double)value);
|
||||
break;
|
||||
case "bool":
|
||||
write.Write((bool)value);
|
||||
break;
|
||||
case "string":
|
||||
write.WriteAlignedString((string)value);
|
||||
i += 3;
|
||||
break;
|
||||
case "map":
|
||||
{
|
||||
if ((members[i + 1].m_MetaFlag & 0x4000) != 0)
|
||||
align = true;
|
||||
var dic = (List<KeyValuePair<object, object>>)value;
|
||||
var size = dic.Count;
|
||||
write.Write(size);
|
||||
var map = GetMembers(members, level, i);
|
||||
i += map.Count - 1;
|
||||
map.RemoveRange(0, 4);
|
||||
var first = GetMembers(map, map[0].m_Level, 0);
|
||||
map.RemoveRange(0, first.Count);
|
||||
var second = map;
|
||||
for (int j = 0; j < size; j++)
|
||||
{
|
||||
int tmp1 = 0;
|
||||
int tmp2 = 0;
|
||||
WriteValue(dic[j].Key, first, write, ref tmp1);
|
||||
WriteValue(dic[j].Value, second, write, ref tmp2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "TypelessData":
|
||||
{
|
||||
var bytes = ((object[])value).Cast<byte>().ToArray();
|
||||
var size = bytes.Length;
|
||||
write.Write(size);
|
||||
write.Write(bytes);
|
||||
i += 2;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
if (i != members.Count && members[i + 1].m_Type == "Array") //Array
|
||||
{
|
||||
if ((members[i + 1].m_MetaFlag & 0x4000) != 0)
|
||||
align = true;
|
||||
var list = (List<object>)value;
|
||||
var size = list.Count;
|
||||
write.Write(size);
|
||||
var vector = GetMembers(members, level, i);
|
||||
i += vector.Count - 1;
|
||||
vector.RemoveRange(0, 3);
|
||||
for (int j = 0; j < size; j++)
|
||||
{
|
||||
int tmp = 0;
|
||||
WriteValue(list[j], vector, write, ref tmp);
|
||||
}
|
||||
break;
|
||||
}
|
||||
else //Class
|
||||
{
|
||||
var @class = GetMembers(members, level, i);
|
||||
@class.RemoveAt(0);
|
||||
i += @class.Count;
|
||||
var obj = (UType)value;
|
||||
for (int j = 0; j < @class.Count; j++)
|
||||
{
|
||||
var classmember = @class[j];
|
||||
var name = classmember.m_Name;
|
||||
WriteValue(obj[name], @class, write, ref j);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (align)
|
||||
write.AlignStream(4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,11 +11,22 @@ namespace AssetStudio
|
||||
public string m_Name;
|
||||
public int m_ByteSize;
|
||||
public int m_Index;
|
||||
public int m_IsArray;
|
||||
public int m_IsArray; //m_TypeFlags
|
||||
public int m_Version;
|
||||
public int m_MetaFlag;
|
||||
public int m_Level;
|
||||
public uint m_TypeStrOffset;
|
||||
public uint m_NameStrOffset;
|
||||
public ulong m_RefTypeHash;
|
||||
|
||||
public TypeTreeNode() { }
|
||||
|
||||
public TypeTreeNode(string type, string name, int level, bool align)
|
||||
{
|
||||
m_Type = type;
|
||||
m_Name = name;
|
||||
m_Level = level;
|
||||
m_MetaFlag = align ? 0x4000 : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,155 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public class UType : IDictionary<string, object>
|
||||
{
|
||||
private List<string> keys;
|
||||
private List<object> values;
|
||||
|
||||
public UType()
|
||||
{
|
||||
keys = new List<string>();
|
||||
values = new List<object>();
|
||||
}
|
||||
|
||||
private int GetValueIndex(string name)
|
||||
{
|
||||
for (int i = 0, n = keys.Count; i < n; i++)
|
||||
{
|
||||
if (string.Equals(keys[i], name, StringComparison.Ordinal))
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public bool TryGetValue<T>(string key, out T value)
|
||||
{
|
||||
var index = GetValueIndex(key);
|
||||
if (index != -1)
|
||||
{
|
||||
value = (T)values[index];
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
value = default(T);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public object this[string key]
|
||||
{
|
||||
get
|
||||
{
|
||||
var index = GetValueIndex(key);
|
||||
if (index != -1)
|
||||
{
|
||||
return values[index];
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
var index = GetValueIndex(key);
|
||||
if (index == -1)
|
||||
{
|
||||
keys.Add(key);
|
||||
values.Add(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
values[index] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ICollection<string> Keys => keys;
|
||||
|
||||
public ICollection<object> Values => values;
|
||||
|
||||
public int Count => keys.Count;
|
||||
|
||||
public bool IsReadOnly => false;
|
||||
|
||||
public void Add(string key, object value)
|
||||
{
|
||||
keys.Add(key);
|
||||
values.Add(value);
|
||||
}
|
||||
|
||||
public void Add(KeyValuePair<string, object> item)
|
||||
{
|
||||
keys.Add(item.Key);
|
||||
values.Add(item.Value);
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
keys.Clear();
|
||||
values.Clear();
|
||||
}
|
||||
|
||||
public bool Contains(KeyValuePair<string, object> item)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool ContainsKey(string key)
|
||||
{
|
||||
return GetValueIndex(key) != -1;
|
||||
}
|
||||
|
||||
public void CopyTo(KeyValuePair<string, object>[] array, int arrayIndex)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
|
||||
{
|
||||
for (int i = 0, n = keys.Count; i < n; i++)
|
||||
{
|
||||
yield return new KeyValuePair<string, object>(keys[i], values[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public bool Remove(string key)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool Remove(KeyValuePair<string, object> item)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool TryGetValue(string key, out object value)
|
||||
{
|
||||
var index = GetValueIndex(key);
|
||||
if (index != -1)
|
||||
{
|
||||
value = values[index];
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
value = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,7 @@ namespace AssetStudio
|
||||
{
|
||||
public static byte[] gzipMagic = { 0x1f, 0x8b };
|
||||
public static byte[] brotliMagic = { 0x62, 0x72, 0x6F, 0x74, 0x6C, 0x69 };
|
||||
public List<StreamFile> fileList = new List<StreamFile>();
|
||||
public StreamFile[] fileList;
|
||||
|
||||
private class WebData
|
||||
{
|
||||
@@ -78,14 +78,16 @@ namespace AssetStudio
|
||||
data.path = Encoding.UTF8.GetString(reader.ReadBytes(pathLength));
|
||||
dataList.Add(data);
|
||||
}
|
||||
|
||||
foreach (var data in dataList)
|
||||
fileList = new StreamFile[dataList.Count];
|
||||
for (int i = 0; i < dataList.Count; i++)
|
||||
{
|
||||
var data = dataList[i];
|
||||
var file = new StreamFile();
|
||||
file.path = data.path;
|
||||
file.fileName = Path.GetFileName(data.path);
|
||||
reader.BaseStream.Position = data.dataOffset;
|
||||
file.stream = new MemoryStream(reader.ReadBytes(data.dataLength));
|
||||
fileList.Add(file);
|
||||
fileList[i] = file;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
using namespace System;
|
||||
using namespace System::Reflection;
|
||||
using namespace System::Runtime::CompilerServices;
|
||||
using namespace System::Runtime::InteropServices;
|
||||
using namespace System::Security::Permissions;
|
||||
|
||||
[assembly:AssemblyTitleAttribute(L"AssetStudioFBX")];
|
||||
[assembly:AssemblyDescriptionAttribute(L"")];
|
||||
[assembly:AssemblyConfigurationAttribute(L"")];
|
||||
[assembly:AssemblyCompanyAttribute(L"")];
|
||||
[assembly:AssemblyProductAttribute(L"AssetStudioFBX")];
|
||||
[assembly:AssemblyCopyrightAttribute(L"Copyright © Perfare 2018")];
|
||||
[assembly:AssemblyTrademarkAttribute(L"")];
|
||||
[assembly:AssemblyCultureAttribute(L"")];
|
||||
|
||||
[assembly:AssemblyVersionAttribute("1.0.*")];
|
||||
|
||||
[assembly:ComVisible(false)];
|
||||
|
||||
[assembly:CLSCompliantAttribute(true)];
|
||||
@@ -1,38 +0,0 @@
|
||||
#include "AssetStudioFBX.h"
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
char* Fbx::StringToCharArray(String^ s)
|
||||
{
|
||||
return (char*)(void*)Marshal::StringToHGlobalAnsi(s);
|
||||
}
|
||||
|
||||
void Fbx::Init(FbxManager** pSdkManager, FbxScene** pScene)
|
||||
{
|
||||
*pSdkManager = FbxManager::Create();
|
||||
if (!pSdkManager)
|
||||
{
|
||||
throw gcnew Exception(gcnew String("Unable to create the FBX SDK manager"));
|
||||
}
|
||||
|
||||
FbxIOSettings* ios = FbxIOSettings::Create(*pSdkManager, IOSROOT);
|
||||
(*pSdkManager)->SetIOSettings(ios);
|
||||
*pScene = FbxScene::Create(*pSdkManager, "");
|
||||
}
|
||||
|
||||
Vector3 Fbx::QuaternionToEuler(Quaternion q)
|
||||
{
|
||||
FbxAMatrix lMatrixRot;
|
||||
lMatrixRot.SetQ(FbxQuaternion(q.X, q.Y, q.Z, q.W));
|
||||
FbxVector4 lEuler = lMatrixRot.GetR();
|
||||
return Vector3((float)lEuler[0], (float)lEuler[1], (float)lEuler[2]);
|
||||
}
|
||||
|
||||
Quaternion Fbx::EulerToQuaternion(Vector3 v)
|
||||
{
|
||||
FbxAMatrix lMatrixRot;
|
||||
lMatrixRot.SetR(FbxVector4(v.X, v.Y, v.Z));
|
||||
FbxQuaternion lQuaternion = lMatrixRot.GetQ();
|
||||
return Quaternion((float)lQuaternion[0], (float)lQuaternion[1], (float)lQuaternion[2], (float)lQuaternion[3]);
|
||||
}
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <fbxsdk.h>
|
||||
|
||||
#ifdef IOS_REF
|
||||
#undef IOS_REF
|
||||
#define IOS_REF (*(pSdkManager->GetIOSettings()))
|
||||
#endif
|
||||
|
||||
using namespace System;
|
||||
using namespace System::Collections::Generic;
|
||||
using namespace System::IO;
|
||||
using namespace System::Runtime::InteropServices;
|
||||
|
||||
#define WITH_MARSHALLED_STRING(name,str,block)\
|
||||
{ \
|
||||
char* name; \
|
||||
try \
|
||||
{ \
|
||||
name = StringToCharArray(str); \
|
||||
block \
|
||||
} \
|
||||
finally \
|
||||
{ \
|
||||
Marshal::FreeHGlobal((IntPtr)name); \
|
||||
} \
|
||||
}
|
||||
|
||||
static char* FBXVersion[] =
|
||||
{
|
||||
FBX_2010_00_COMPATIBLE,
|
||||
FBX_2011_00_COMPATIBLE,
|
||||
FBX_2012_00_COMPATIBLE,
|
||||
FBX_2013_00_COMPATIBLE,
|
||||
FBX_2014_00_COMPATIBLE,
|
||||
FBX_2016_00_COMPATIBLE
|
||||
};
|
||||
|
||||
namespace AssetStudio {
|
||||
|
||||
public ref class Fbx
|
||||
{
|
||||
public:
|
||||
static Vector3 QuaternionToEuler(Quaternion q);
|
||||
static Quaternion EulerToQuaternion(Vector3 v);
|
||||
static char* StringToCharArray(String^ s);
|
||||
static void Init(FbxManager** pSdkManager, FbxScene** pScene);
|
||||
|
||||
ref class Exporter
|
||||
{
|
||||
public:
|
||||
static void Export(String^ path, IImported^ imported, bool eulerFilter, float filterPrecision, bool allFrames, bool allBones, bool skins, float boneSize, float scaleFactor, bool flatInbetween, int versionIndex, bool isAscii);
|
||||
|
||||
private:
|
||||
bool exportSkins;
|
||||
float boneSize;
|
||||
IImported^ imported;
|
||||
HashSet<String^>^ framePaths;
|
||||
Dictionary<ImportedFrame^, size_t>^ frameToNode;
|
||||
List<ImportedFrame^>^ meshFrames;
|
||||
|
||||
char* cDest;
|
||||
FbxManager* pSdkManager;
|
||||
FbxScene* pScene;
|
||||
FbxExporter* pExporter;
|
||||
FbxArray<FbxSurfacePhong*>* pMaterials;
|
||||
FbxArray<FbxFileTexture*>* pTextures;
|
||||
FbxPose* pBindPose;
|
||||
|
||||
Exporter(String^ path, IImported^ imported, bool allFrames, bool allBones, bool skins, float boneSize, float scaleFactor, int versionIndex, bool isAscii);
|
||||
~Exporter();
|
||||
|
||||
void Exporter::LinkTexture(ImportedMaterialTexture^ texture, FbxFileTexture* pTexture, FbxProperty& prop);
|
||||
void SetJointsNode(ImportedFrame^ frame, HashSet<String^>^ bonePaths, bool allBones);
|
||||
HashSet<String^>^ SearchHierarchy();
|
||||
void SearchHierarchy(ImportedFrame^ frame, HashSet<String^>^ exportFrames);
|
||||
void SetJointsFromImportedMeshes(bool allBones);
|
||||
void ExportFrame(FbxNode* pParentNode, ImportedFrame^ frame);
|
||||
void ExportMesh(FbxNode* pFrameNode, ImportedMesh^ meshList);
|
||||
FbxFileTexture* ExportTexture(ImportedTexture^ matTex);
|
||||
void ExportAnimations(bool eulerFilter, float filterValue, bool flatInbetween);
|
||||
void ExportKeyframedAnimation(ImportedKeyframedAnimation^ parser, FbxString& kTakeName, FbxAnimCurveFilterUnroll* eulerFilter, float filterPrecision, bool flatInbetween);
|
||||
void ExportMorphs(bool morphMask, bool flatInbetween);
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,154 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>15.0</VCProjectVersion>
|
||||
<ProjectGuid>{4F8EF5EF-732B-49CF-9EB3-B23E19AE6267}</ProjectGuid>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<Keyword>ManagedCProj</Keyword>
|
||||
<RootNamespace>AssetStudioFBX</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0.17134.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<CLRSupport>true</CLRSupport>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<CLRSupport>true</CLRSupport>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<CLRSupport>true</CLRSupport>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<CLRSupport>true</CLRSupport>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>FBXSDK_SHARED;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2019.0\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>libfbxsdk.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2019.0\lib\vs2015\x64\release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>FBXSDK_SHARED;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2019.0\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>libfbxsdk.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2019.0\lib\vs2015\x86\release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PreprocessorDefinitions>FBXSDK_SHARED;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2019.0\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>libfbxsdk.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2019.0\lib\vs2015\x64\release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PreprocessorDefinitions>FBXSDK_SHARED;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2019.0\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>libfbxsdk.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2019.0\lib\vs2015\x86\release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="AssemblyInfo.cpp" />
|
||||
<ClCompile Include="AssetStudioFBX.cpp" />
|
||||
<ClCompile Include="AssetStudioFBXExporter.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="AssetStudioFBX.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\AssetStudio\AssetStudio.csproj">
|
||||
<Project>{af56b63c-1764-41b7-9e60-8d485422ac3b}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -1,29 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="源文件">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="头文件">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="AssemblyInfo.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="AssetStudioFBX.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="AssetStudioFBXExporter.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="AssetStudioFBX.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -1,969 +0,0 @@
|
||||
#include "AssetStudioFBX.h"
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
void Fbx::Exporter::Export(String^ path, IImported^ imported, bool eulerFilter, float filterPrecision, bool allFrames, bool allBones, bool skins, float boneSize, float scaleFactor, bool flatInbetween, int versionIndex, bool isAscii)
|
||||
{
|
||||
FileInfo^ file = gcnew FileInfo(path);
|
||||
DirectoryInfo^ dir = file->Directory;
|
||||
if (!dir->Exists)
|
||||
{
|
||||
dir->Create();
|
||||
}
|
||||
String^ currentDir = Directory::GetCurrentDirectory();
|
||||
Directory::SetCurrentDirectory(dir->FullName);
|
||||
path = Path::GetFileName(path);
|
||||
|
||||
Exporter^ exporter = gcnew Exporter(path, imported, allFrames, allBones, skins, boneSize, scaleFactor, versionIndex, isAscii);
|
||||
//TODO exporter->ExportMorphs(false, flatInbetween);
|
||||
exporter->ExportAnimations(eulerFilter, filterPrecision, flatInbetween);
|
||||
exporter->pExporter->Export(exporter->pScene);
|
||||
delete exporter;
|
||||
|
||||
Directory::SetCurrentDirectory(currentDir);
|
||||
}
|
||||
|
||||
Fbx::Exporter::Exporter(String^ path, IImported^ imported, bool allFrames, bool allBones, bool skins, float boneSize, float scaleFactor, int versionIndex, bool isAscii)
|
||||
{
|
||||
this->imported = imported;
|
||||
exportSkins = skins;
|
||||
this->boneSize = boneSize;
|
||||
|
||||
cDest = NULL;
|
||||
pSdkManager = NULL;
|
||||
pScene = NULL;
|
||||
pExporter = NULL;
|
||||
pMaterials = NULL;
|
||||
pTextures = NULL;
|
||||
|
||||
pin_ptr<FbxManager*> pSdkManagerPin = &pSdkManager;
|
||||
pin_ptr<FbxScene*> pScenePin = &pScene;
|
||||
Init(pSdkManagerPin, pScenePin);
|
||||
|
||||
IOS_REF.SetBoolProp(EXP_FBX_MATERIAL, true);
|
||||
IOS_REF.SetBoolProp(EXP_FBX_TEXTURE, true);
|
||||
IOS_REF.SetBoolProp(EXP_FBX_EMBEDDED, false);
|
||||
IOS_REF.SetBoolProp(EXP_FBX_SHAPE, true);
|
||||
IOS_REF.SetBoolProp(EXP_FBX_GOBO, true);
|
||||
IOS_REF.SetBoolProp(EXP_FBX_ANIMATION, true);
|
||||
IOS_REF.SetBoolProp(EXP_FBX_GLOBAL_SETTINGS, true);
|
||||
|
||||
FbxGlobalSettings& globalSettings = pScene->GetGlobalSettings();
|
||||
globalSettings.SetSystemUnit(FbxSystemUnit(scaleFactor));
|
||||
|
||||
cDest = StringToCharArray(path);
|
||||
pExporter = FbxExporter::Create(pScene, "");
|
||||
|
||||
int pFileFormat = 0;
|
||||
if (versionIndex == 0)
|
||||
{
|
||||
pFileFormat = 3;
|
||||
if (isAscii)
|
||||
{
|
||||
pFileFormat = 4;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pExporter->SetFileExportVersion(FBXVersion[versionIndex]);
|
||||
if (isAscii)
|
||||
{
|
||||
pFileFormat = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!pExporter->Initialize(cDest, pFileFormat, pSdkManager->GetIOSettings()))
|
||||
{
|
||||
throw gcnew Exception(gcnew String("Failed to initialize FbxExporter: ") + gcnew String(pExporter->GetStatus().GetErrorString()));
|
||||
}
|
||||
|
||||
framePaths = nullptr;
|
||||
if (!allFrames)
|
||||
{
|
||||
framePaths = SearchHierarchy();
|
||||
if (!framePaths)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
pBindPose = FbxPose::Create(pScene, "BindPose");
|
||||
pBindPose->SetIsBindPose(true);
|
||||
|
||||
frameToNode = gcnew Dictionary<ImportedFrame^, size_t>();
|
||||
meshFrames = imported->MeshList != nullptr ? gcnew List<ImportedFrame^>() : nullptr;
|
||||
ExportFrame(pScene->GetRootNode(), imported->RootFrame);
|
||||
|
||||
if (imported->MeshList != nullptr)
|
||||
{
|
||||
SetJointsFromImportedMeshes(allBones);
|
||||
|
||||
pMaterials = new FbxArray<FbxSurfacePhong*>();
|
||||
pTextures = new FbxArray<FbxFileTexture*>();
|
||||
pMaterials->Reserve(imported->MaterialList->Count);
|
||||
pTextures->Reserve(imported->TextureList->Count);
|
||||
|
||||
for (int i = 0; i < meshFrames->Count; i++)
|
||||
{
|
||||
auto meshFram = meshFrames[i];
|
||||
FbxNode* meshNode = (FbxNode*)frameToNode[meshFram];
|
||||
ImportedMesh^ mesh = ImportedHelpers::FindMesh(meshFram->Path, imported->MeshList);
|
||||
ExportMesh(meshNode, mesh);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SetJointsNode(imported->RootFrame, nullptr, true);
|
||||
}
|
||||
}
|
||||
|
||||
Fbx::Exporter::~Exporter()
|
||||
{
|
||||
imported = nullptr;
|
||||
if (framePaths != nullptr)
|
||||
{
|
||||
framePaths->Clear();
|
||||
}
|
||||
if (frameToNode != nullptr)
|
||||
{
|
||||
frameToNode->Clear();
|
||||
}
|
||||
if (meshFrames != nullptr)
|
||||
{
|
||||
meshFrames->Clear();
|
||||
}
|
||||
|
||||
if (pMaterials != NULL)
|
||||
{
|
||||
delete pMaterials;
|
||||
}
|
||||
if (pTextures != NULL)
|
||||
{
|
||||
delete pTextures;
|
||||
}
|
||||
if (pExporter != NULL)
|
||||
{
|
||||
pExporter->Destroy();
|
||||
}
|
||||
if (pScene != NULL)
|
||||
{
|
||||
pScene->Destroy();
|
||||
}
|
||||
if (pSdkManager != NULL)
|
||||
{
|
||||
pSdkManager->Destroy();
|
||||
}
|
||||
if (cDest != NULL)
|
||||
{
|
||||
Marshal::FreeHGlobal((IntPtr)cDest);
|
||||
}
|
||||
}
|
||||
|
||||
void Fbx::Exporter::SetJointsNode(ImportedFrame^ frame, HashSet<String^>^ bonePaths, bool allBones)
|
||||
{
|
||||
size_t pointer;
|
||||
if (frameToNode->TryGetValue(frame, pointer))
|
||||
{
|
||||
auto pNode = (FbxNode*)pointer;
|
||||
if (allBones || bonePaths->Contains(frame->Path))
|
||||
{
|
||||
FbxSkeleton* pJoint = FbxSkeleton::Create(pScene, "");
|
||||
pJoint->Size.Set(FbxDouble(boneSize));
|
||||
pJoint->SetSkeletonType(FbxSkeleton::eLimbNode);
|
||||
pNode->SetNodeAttribute(pJoint);
|
||||
}
|
||||
else
|
||||
{
|
||||
FbxNull* pNull = FbxNull::Create(pScene, "");
|
||||
if (pNode->GetChildCount() > 0)
|
||||
{
|
||||
pNull->Look.Set(FbxNull::eNone);
|
||||
}
|
||||
|
||||
pNode->SetNodeAttribute(pNull);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < frame->Count; i++)
|
||||
{
|
||||
SetJointsNode(frame[i], bonePaths, allBones);
|
||||
}
|
||||
}
|
||||
|
||||
HashSet<String^>^ Fbx::Exporter::SearchHierarchy()
|
||||
{
|
||||
if (imported->MeshList == nullptr || imported->MeshList->Count == 0)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
HashSet<String^>^ exportFrames = gcnew HashSet<String^>();
|
||||
SearchHierarchy(imported->RootFrame, exportFrames);
|
||||
return exportFrames;
|
||||
}
|
||||
|
||||
void Fbx::Exporter::SearchHierarchy(ImportedFrame^ frame, HashSet<String^>^ exportFrames)
|
||||
{
|
||||
ImportedMesh^ meshListSome = ImportedHelpers::FindMesh(frame->Path, imported->MeshList);
|
||||
if (meshListSome != nullptr)
|
||||
{
|
||||
ImportedFrame^ parent = frame;
|
||||
while (parent != nullptr)
|
||||
{
|
||||
exportFrames->Add(parent->Path);
|
||||
parent = parent->Parent;
|
||||
}
|
||||
|
||||
List<ImportedBone^>^ boneList = meshListSome->BoneList;
|
||||
if (boneList != nullptr)
|
||||
{
|
||||
for (int i = 0; i < boneList->Count; i++)
|
||||
{
|
||||
if (!exportFrames->Contains(boneList[i]->Path))
|
||||
{
|
||||
ImportedFrame^ boneParent = imported->RootFrame->FindFrameByPath(boneList[i]->Path);
|
||||
while (boneParent != nullptr)
|
||||
{
|
||||
exportFrames->Add(boneParent->Path);
|
||||
boneParent = boneParent->Parent;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < frame->Count; i++)
|
||||
{
|
||||
SearchHierarchy(frame[i], exportFrames);
|
||||
}
|
||||
}
|
||||
|
||||
void Fbx::Exporter::SetJointsFromImportedMeshes(bool allBones)
|
||||
{
|
||||
if (!exportSkins)
|
||||
{
|
||||
return;
|
||||
}
|
||||
HashSet<String^>^ bonePaths = gcnew HashSet<String^>();
|
||||
for (int i = 0; i < imported->MeshList->Count; i++)
|
||||
{
|
||||
ImportedMesh^ meshList = imported->MeshList[i];
|
||||
List<ImportedBone^>^ boneList = meshList->BoneList;
|
||||
if (boneList != nullptr)
|
||||
{
|
||||
for (int j = 0; j < boneList->Count; j++)
|
||||
{
|
||||
ImportedBone^ bone = boneList[j];
|
||||
bonePaths->Add(bone->Path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SetJointsNode(imported->RootFrame, bonePaths, allBones);
|
||||
}
|
||||
|
||||
void Fbx::Exporter::ExportFrame(FbxNode* pParentNode, ImportedFrame^ frame)
|
||||
{
|
||||
if (framePaths == nullptr || framePaths->Contains(frame->Path))
|
||||
{
|
||||
FbxNode* pFrameNode;
|
||||
WITH_MARSHALLED_STRING
|
||||
(
|
||||
pName,
|
||||
frame->Name,
|
||||
pFrameNode = FbxNode::Create(pScene, pName);
|
||||
);
|
||||
|
||||
pFrameNode->LclScaling.Set(FbxDouble3(frame->LocalScale.X, frame->LocalScale.Y, frame->LocalScale.Z));
|
||||
pFrameNode->LclRotation.Set(FbxDouble3(frame->LocalRotation.X, frame->LocalRotation.Y, frame->LocalRotation.Z));
|
||||
pFrameNode->LclTranslation.Set(FbxDouble3(frame->LocalPosition.X, frame->LocalPosition.Y, frame->LocalPosition.Z));
|
||||
pFrameNode->SetPreferedAngle(pFrameNode->LclRotation.Get());
|
||||
pParentNode->AddChild(pFrameNode);
|
||||
pBindPose->Add(pFrameNode, pFrameNode->EvaluateGlobalTransform());
|
||||
|
||||
if (imported->MeshList != nullptr && ImportedHelpers::FindMesh(frame->Path, imported->MeshList) != nullptr)
|
||||
{
|
||||
meshFrames->Add(frame);
|
||||
}
|
||||
|
||||
frameToNode->Add(frame, (size_t)pFrameNode);
|
||||
|
||||
for (int i = 0; i < frame->Count; i++)
|
||||
{
|
||||
ExportFrame(pFrameNode, frame[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Fbx::Exporter::ExportMesh(FbxNode* pFrameNode, ImportedMesh^ meshList)
|
||||
{
|
||||
List<ImportedBone^>^ boneList = meshList->BoneList;
|
||||
bool hasBones;
|
||||
if (exportSkins && boneList != nullptr)
|
||||
{
|
||||
hasBones = boneList->Count > 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
hasBones = false;
|
||||
}
|
||||
|
||||
FbxArray<FbxNode*>* pBoneNodeList = nullptr;
|
||||
FbxArray<FbxCluster*>* pClusterArray = nullptr;
|
||||
|
||||
try
|
||||
{
|
||||
if (hasBones)
|
||||
{
|
||||
pBoneNodeList = new FbxArray<FbxNode*>();
|
||||
pBoneNodeList->Reserve(boneList->Count);
|
||||
for (int i = 0; i < boneList->Count; i++)
|
||||
{
|
||||
auto bone = boneList[i];
|
||||
auto frame = imported->RootFrame->FindFrameByPath(bone->Path);
|
||||
auto frameNode = (FbxNode*)frameToNode[frame];
|
||||
pBoneNodeList->Add(frameNode);
|
||||
}
|
||||
|
||||
pClusterArray = new FbxArray<FbxCluster*>();
|
||||
pClusterArray->Reserve(boneList->Count);
|
||||
for (int i = 0; i < boneList->Count; i++)
|
||||
{
|
||||
FbxNode* pNode = pBoneNodeList->GetAt(i);
|
||||
FbxString lClusterName = pNode->GetNameOnly() + FbxString("Cluster");
|
||||
FbxCluster* pCluster = FbxCluster::Create(pScene, lClusterName.Buffer());
|
||||
pCluster->SetLink(pNode);
|
||||
pCluster->SetLinkMode(FbxCluster::eTotalOne);
|
||||
pClusterArray->Add(pCluster);
|
||||
}
|
||||
}
|
||||
|
||||
FbxMesh* pMesh = FbxMesh::Create(pScene, "");
|
||||
pFrameNode->SetNodeAttribute(pMesh);
|
||||
|
||||
int vertexCount = 0;
|
||||
for (int i = 0; i < meshList->SubmeshList->Count; i++)
|
||||
{
|
||||
vertexCount += meshList->SubmeshList[i]->VertexList->Count;
|
||||
}
|
||||
|
||||
pMesh->InitControlPoints(vertexCount);
|
||||
FbxVector4* pControlPoints = pMesh->GetControlPoints();
|
||||
|
||||
FbxGeometryElementNormal* lGeometryElementNormal = pMesh->CreateElementNormal();
|
||||
lGeometryElementNormal->SetMappingMode(FbxGeometryElement::eByControlPoint);
|
||||
lGeometryElementNormal->SetReferenceMode(FbxGeometryElement::eDirect);
|
||||
|
||||
FbxGeometryElementUV* lGeometryElementUV = pMesh->CreateElementUV("UV0");
|
||||
lGeometryElementUV->SetMappingMode(FbxGeometryElement::eByControlPoint);
|
||||
lGeometryElementUV->SetReferenceMode(FbxGeometryElement::eDirect);
|
||||
|
||||
FbxGeometryElementTangent* lGeometryElementTangent = pMesh->CreateElementTangent();
|
||||
lGeometryElementTangent->SetMappingMode(FbxGeometryElement::eByControlPoint);
|
||||
lGeometryElementTangent->SetReferenceMode(FbxGeometryElement::eDirect);
|
||||
|
||||
FbxGeometryElementVertexColor* lGeometryElementVertexColor = nullptr;
|
||||
bool vertexColours = vertexCount > 0 && dynamic_cast<ImportedVertexWithColour^>(meshList->SubmeshList[0]->VertexList[0]) != nullptr;
|
||||
if (vertexColours)
|
||||
{
|
||||
lGeometryElementVertexColor = pMesh->CreateElementVertexColor();
|
||||
lGeometryElementVertexColor->SetMappingMode(FbxGeometryElement::eByControlPoint);
|
||||
lGeometryElementVertexColor->SetReferenceMode(FbxGeometryElement::eDirect);
|
||||
}
|
||||
|
||||
FbxGeometryElementMaterial* lGeometryElementMaterial = pMesh->CreateElementMaterial();
|
||||
lGeometryElementMaterial->SetMappingMode(FbxGeometryElement::eByPolygon);
|
||||
lGeometryElementMaterial->SetReferenceMode(FbxGeometryElement::eIndexToDirect);
|
||||
|
||||
int firstVertex = 0;
|
||||
for (int i = 0; i < meshList->SubmeshList->Count; i++)
|
||||
{
|
||||
ImportedSubmesh^ meshObj = meshList->SubmeshList[i];
|
||||
List<ImportedVertex^>^ vertexList = meshObj->VertexList;
|
||||
List<ImportedFace^>^ faceList = meshObj->FaceList;
|
||||
|
||||
int materialIndex = 0;
|
||||
ImportedMaterial^ mat = ImportedHelpers::FindMaterial(meshObj->Material, imported->MaterialList);
|
||||
if (mat != nullptr)
|
||||
{
|
||||
char* pMatName = NULL;
|
||||
try
|
||||
{
|
||||
pMatName = StringToCharArray(mat->Name);
|
||||
int foundMat = -1;
|
||||
for (int j = 0; j < pMaterials->GetCount(); j++)
|
||||
{
|
||||
FbxSurfacePhong* pMatTemp = pMaterials->GetAt(j);
|
||||
if (strcmp(pMatTemp->GetName(), pMatName) == 0)
|
||||
{
|
||||
foundMat = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
FbxSurfacePhong* pMat;
|
||||
if (foundMat >= 0)
|
||||
{
|
||||
pMat = pMaterials->GetAt(foundMat);
|
||||
}
|
||||
else
|
||||
{
|
||||
FbxString lShadingName = "Phong";
|
||||
Color diffuse = mat->Diffuse;
|
||||
Color ambient = mat->Ambient;
|
||||
Color emissive = mat->Emissive;
|
||||
Color specular = mat->Specular;
|
||||
Color reflection = mat->Reflection;
|
||||
pMat = FbxSurfacePhong::Create(pScene, pMatName);
|
||||
pMat->Diffuse.Set(FbxDouble3(diffuse.R, diffuse.G, diffuse.B));
|
||||
pMat->DiffuseFactor.Set(FbxDouble(diffuse.A));
|
||||
pMat->Ambient.Set(FbxDouble3(ambient.R, ambient.G, ambient.B));
|
||||
pMat->AmbientFactor.Set(FbxDouble(ambient.A));
|
||||
pMat->Emissive.Set(FbxDouble3(emissive.R, emissive.G, emissive.B));
|
||||
pMat->EmissiveFactor.Set(FbxDouble(emissive.A));
|
||||
pMat->Specular.Set(FbxDouble3(specular.R, specular.G, specular.B));
|
||||
pMat->SpecularFactor.Set(FbxDouble(specular.A));
|
||||
pMat->Reflection.Set(FbxDouble3(reflection.R, reflection.G, reflection.B));
|
||||
pMat->ReflectionFactor.Set(FbxDouble(reflection.A));
|
||||
pMat->Shininess.Set(FbxDouble(mat->Shininess));
|
||||
pMat->TransparencyFactor.Set(FbxDouble(mat->Transparency));
|
||||
pMat->ShadingModel.Set(lShadingName);
|
||||
pMaterials->Add(pMat);
|
||||
}
|
||||
materialIndex = pFrameNode->AddMaterial(pMat);
|
||||
|
||||
bool hasTexture = false;
|
||||
|
||||
for each (ImportedMaterialTexture^ texture in mat->Textures)
|
||||
{
|
||||
auto pTexture = ExportTexture(ImportedHelpers::FindTexture(texture->Name, imported->TextureList));
|
||||
if (pTexture != NULL)
|
||||
{
|
||||
if (texture->Dest == 0)
|
||||
{
|
||||
LinkTexture(texture, pTexture, pMat->Diffuse);
|
||||
hasTexture = true;
|
||||
}
|
||||
else if (texture->Dest == 1)
|
||||
{
|
||||
LinkTexture(texture, pTexture, pMat->NormalMap);
|
||||
hasTexture = true;
|
||||
}
|
||||
else if (texture->Dest == 2)
|
||||
{
|
||||
LinkTexture(texture, pTexture, pMat->Specular);
|
||||
hasTexture = true;
|
||||
}
|
||||
else if (texture->Dest == 3)
|
||||
{
|
||||
LinkTexture(texture, pTexture, pMat->Bump);
|
||||
hasTexture = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hasTexture)
|
||||
{
|
||||
pFrameNode->SetShadingMode(FbxNode::eTextureShading);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
Marshal::FreeHGlobal((IntPtr)pMatName);
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = 0; j < vertexList->Count; j++)
|
||||
{
|
||||
ImportedVertex^ vertex = vertexList[j];
|
||||
|
||||
Vector3 coords = vertex->Position;
|
||||
pControlPoints[j + firstVertex] = FbxVector4(coords.X, coords.Y, coords.Z, 0);
|
||||
|
||||
Vector3 normal = vertex->Normal;
|
||||
lGeometryElementNormal->GetDirectArray().Add(FbxVector4(normal.X, normal.Y, normal.Z, 0));
|
||||
|
||||
array<float>^ uv = vertex->UV;
|
||||
if (uv != nullptr)
|
||||
{
|
||||
lGeometryElementUV->GetDirectArray().Add(FbxVector2(uv[0], uv[1]));
|
||||
}
|
||||
|
||||
Vector4 tangent = vertex->Tangent;
|
||||
lGeometryElementTangent->GetDirectArray().Add(FbxVector4(tangent.X, tangent.Y, tangent.Z, tangent.W));
|
||||
|
||||
if (vertexColours)
|
||||
{
|
||||
ImportedVertexWithColour^ vert = (ImportedVertexWithColour^)vertexList[j];
|
||||
lGeometryElementVertexColor->GetDirectArray().Add(FbxColor(vert->Colour.R, vert->Colour.G, vert->Colour.B, vert->Colour.A));
|
||||
}
|
||||
|
||||
if (hasBones && vertex->BoneIndices != nullptr)
|
||||
{
|
||||
auto boneIndices = vertex->BoneIndices;
|
||||
auto weights4 = vertex->Weights;
|
||||
for (int k = 0; k < 4; k++)
|
||||
{
|
||||
if (boneIndices[k] < boneList->Count && weights4[k] > 0)
|
||||
{
|
||||
FbxCluster* pCluster = pClusterArray->GetAt(boneIndices[k]);
|
||||
pCluster->AddControlPointIndex(j + firstVertex, weights4[k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = 0; j < faceList->Count; j++)
|
||||
{
|
||||
ImportedFace^ face = faceList[j];
|
||||
pMesh->BeginPolygon(materialIndex);
|
||||
pMesh->AddPolygon(face->VertexIndices[0] + firstVertex);
|
||||
pMesh->AddPolygon(face->VertexIndices[1] + firstVertex);
|
||||
pMesh->AddPolygon(face->VertexIndices[2] + firstVertex);
|
||||
pMesh->EndPolygon();
|
||||
}
|
||||
|
||||
firstVertex += vertexList->Count;
|
||||
}
|
||||
|
||||
if (hasBones)
|
||||
{
|
||||
FbxSkin* pSkin = FbxSkin::Create(pScene, "");
|
||||
FbxAMatrix lMeshMatrix = pFrameNode->EvaluateGlobalTransform();
|
||||
for (int j = 0; j < boneList->Count; j++)
|
||||
{
|
||||
FbxCluster* pCluster = pClusterArray->GetAt(j);
|
||||
if (pCluster->GetControlPointIndicesCount() > 0)
|
||||
{
|
||||
auto boneMatrix = boneList[j]->Matrix;
|
||||
FbxAMatrix lBoneMatrix;
|
||||
for (int m = 0; m < 4; m++)
|
||||
{
|
||||
for (int n = 0; n < 4; n++)
|
||||
{
|
||||
lBoneMatrix.mData[m][n] = boneMatrix[m, n];
|
||||
}
|
||||
}
|
||||
|
||||
pCluster->SetTransformMatrix(lMeshMatrix);
|
||||
pCluster->SetTransformLinkMatrix(lMeshMatrix * lBoneMatrix.Inverse());
|
||||
|
||||
pSkin->AddCluster(pCluster);
|
||||
}
|
||||
}
|
||||
|
||||
if (pSkin->GetClusterCount() > 0)
|
||||
{
|
||||
pMesh->AddDeformer(pSkin);
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (pBoneNodeList != NULL)
|
||||
{
|
||||
delete pBoneNodeList;
|
||||
}
|
||||
if (pClusterArray != NULL)
|
||||
{
|
||||
delete pClusterArray;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FbxFileTexture* Fbx::Exporter::ExportTexture(ImportedTexture^ matTex)
|
||||
{
|
||||
FbxFileTexture* pTex = NULL;
|
||||
|
||||
if (matTex != nullptr)
|
||||
{
|
||||
String^ matTexName = matTex->Name;
|
||||
char* pTexName = NULL;
|
||||
try
|
||||
{
|
||||
pTexName = StringToCharArray(matTexName);
|
||||
int foundTex = -1;
|
||||
for (int i = 0; i < pTextures->GetCount(); i++)
|
||||
{
|
||||
FbxFileTexture* pTexTemp = pTextures->GetAt(i);
|
||||
if (strcmp(pTexTemp->GetName(), pTexName) == 0)
|
||||
{
|
||||
foundTex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (foundTex >= 0)
|
||||
{
|
||||
pTex = pTextures->GetAt(foundTex);
|
||||
}
|
||||
else
|
||||
{
|
||||
pTex = FbxFileTexture::Create(pScene, pTexName);
|
||||
pTex->SetFileName(pTexName);
|
||||
pTex->SetTextureUse(FbxTexture::eStandard);
|
||||
pTex->SetMappingType(FbxTexture::eUV);
|
||||
pTex->SetMaterialUse(FbxFileTexture::eModelMaterial);
|
||||
pTex->SetSwapUV(false);
|
||||
pTex->SetTranslation(0.0, 0.0);
|
||||
pTex->SetScale(1.0, 1.0);
|
||||
pTex->SetRotation(0.0, 0.0);
|
||||
pTextures->Add(pTex);
|
||||
|
||||
String^ path = Path::GetDirectoryName(gcnew String(pExporter->GetFileName().Buffer()));
|
||||
if (path == String::Empty)
|
||||
{
|
||||
path = ".";
|
||||
}
|
||||
FileInfo^ file = gcnew FileInfo(path + Path::DirectorySeparatorChar + Path::GetFileName(matTex->Name));
|
||||
DirectoryInfo^ dir = file->Directory;
|
||||
if (!dir->Exists)
|
||||
{
|
||||
dir->Create();
|
||||
}
|
||||
BinaryWriter^ writer = gcnew BinaryWriter(file->Create());
|
||||
writer->Write(matTex->Data);
|
||||
writer->Close();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
Marshal::FreeHGlobal((IntPtr)pTexName);
|
||||
}
|
||||
}
|
||||
|
||||
return pTex;
|
||||
}
|
||||
|
||||
void Fbx::Exporter::LinkTexture(ImportedMaterialTexture^ texture, FbxFileTexture* pTexture, FbxProperty& prop)
|
||||
{
|
||||
pTexture->SetTranslation(texture->Offset.X, texture->Offset.Y);
|
||||
pTexture->SetScale(texture->Scale.X, texture->Scale.Y);
|
||||
prop.ConnectSrcObject(pTexture);
|
||||
}
|
||||
|
||||
void Fbx::Exporter::ExportAnimations(bool eulerFilter, float filterPrecision, bool flatInbetween)
|
||||
{
|
||||
auto importedAnimationList = imported->AnimationList;
|
||||
if (importedAnimationList == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
FbxAnimCurveFilterUnroll* lFilter = eulerFilter ? new FbxAnimCurveFilterUnroll() : NULL;
|
||||
|
||||
for (int i = 0; i < importedAnimationList->Count; i++)
|
||||
{
|
||||
auto importedAnimation = importedAnimationList[i];
|
||||
FbxString kTakeName;
|
||||
if (importedAnimation->Name)
|
||||
{
|
||||
WITH_MARSHALLED_STRING
|
||||
(
|
||||
pClipName,
|
||||
importedAnimation->Name,
|
||||
kTakeName = FbxString(pClipName);
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
kTakeName = FbxString("Take") + FbxString(i);
|
||||
}
|
||||
ExportKeyframedAnimation(importedAnimation, kTakeName, lFilter, filterPrecision, flatInbetween);
|
||||
}
|
||||
}
|
||||
|
||||
void Fbx::Exporter::ExportKeyframedAnimation(ImportedKeyframedAnimation^ parser, FbxString& kTakeName, FbxAnimCurveFilterUnroll* eulerFilter, float filterPrecision, bool flatInbetween)
|
||||
{
|
||||
List<ImportedAnimationKeyframedTrack^>^ pAnimationList = parser->TrackList;
|
||||
|
||||
char* lTakeName = kTakeName.Buffer();
|
||||
|
||||
FbxAnimStack* lAnimStack = FbxAnimStack::Create(pScene, lTakeName);
|
||||
FbxAnimLayer* lAnimLayer = FbxAnimLayer::Create(pScene, "Base Layer");
|
||||
lAnimStack->AddMember(lAnimLayer);
|
||||
|
||||
for (int j = 0; j < pAnimationList->Count; j++)
|
||||
{
|
||||
ImportedAnimationKeyframedTrack^ keyframeList = pAnimationList[j];
|
||||
if (keyframeList->Path == nullptr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
auto frame = imported->RootFrame->FindFrameByPath(keyframeList->Path);
|
||||
if (frame != nullptr)
|
||||
{
|
||||
FbxNode* pNode = (FbxNode*)frameToNode[frame];
|
||||
|
||||
FbxAnimCurve* lCurveSX = pNode->LclScaling.GetCurve(lAnimLayer, FBXSDK_CURVENODE_COMPONENT_X, true);
|
||||
FbxAnimCurve* lCurveSY = pNode->LclScaling.GetCurve(lAnimLayer, FBXSDK_CURVENODE_COMPONENT_Y, true);
|
||||
FbxAnimCurve* lCurveSZ = pNode->LclScaling.GetCurve(lAnimLayer, FBXSDK_CURVENODE_COMPONENT_Z, true);
|
||||
FbxAnimCurve* lCurveRX = pNode->LclRotation.GetCurve(lAnimLayer, FBXSDK_CURVENODE_COMPONENT_X, true);
|
||||
FbxAnimCurve* lCurveRY = pNode->LclRotation.GetCurve(lAnimLayer, FBXSDK_CURVENODE_COMPONENT_Y, true);
|
||||
FbxAnimCurve* lCurveRZ = pNode->LclRotation.GetCurve(lAnimLayer, FBXSDK_CURVENODE_COMPONENT_Z, true);
|
||||
FbxAnimCurve* lCurveTX = pNode->LclTranslation.GetCurve(lAnimLayer, FBXSDK_CURVENODE_COMPONENT_X, true);
|
||||
FbxAnimCurve* lCurveTY = pNode->LclTranslation.GetCurve(lAnimLayer, FBXSDK_CURVENODE_COMPONENT_Y, true);
|
||||
FbxAnimCurve* lCurveTZ = pNode->LclTranslation.GetCurve(lAnimLayer, FBXSDK_CURVENODE_COMPONENT_Z, true);
|
||||
|
||||
lCurveSX->KeyModifyBegin();
|
||||
lCurveSY->KeyModifyBegin();
|
||||
lCurveSZ->KeyModifyBegin();
|
||||
lCurveRX->KeyModifyBegin();
|
||||
lCurveRY->KeyModifyBegin();
|
||||
lCurveRZ->KeyModifyBegin();
|
||||
lCurveTX->KeyModifyBegin();
|
||||
lCurveTY->KeyModifyBegin();
|
||||
lCurveTZ->KeyModifyBegin();
|
||||
|
||||
FbxTime lTime;
|
||||
|
||||
for each (auto Scaling in keyframeList->Scalings)
|
||||
{
|
||||
lTime.SetSecondDouble(Scaling->time);
|
||||
|
||||
lCurveSX->KeySet(lCurveSX->KeyAdd(lTime), lTime, Scaling->value.X);
|
||||
lCurveSY->KeySet(lCurveSY->KeyAdd(lTime), lTime, Scaling->value.Y);
|
||||
lCurveSZ->KeySet(lCurveSZ->KeyAdd(lTime), lTime, Scaling->value.Z);
|
||||
}
|
||||
for each (auto Rotation in keyframeList->Rotations)
|
||||
{
|
||||
lTime.SetSecondDouble(Rotation->time);
|
||||
|
||||
lCurveRX->KeySet(lCurveRX->KeyAdd(lTime), lTime, Rotation->value.X);
|
||||
lCurveRY->KeySet(lCurveRY->KeyAdd(lTime), lTime, Rotation->value.Y);
|
||||
lCurveRZ->KeySet(lCurveRZ->KeyAdd(lTime), lTime, Rotation->value.Z);
|
||||
}
|
||||
for each (auto Translation in keyframeList->Translations)
|
||||
{
|
||||
lTime.SetSecondDouble(Translation->time);
|
||||
|
||||
lCurveTX->KeySet(lCurveTX->KeyAdd(lTime), lTime, Translation->value.X);
|
||||
lCurveTY->KeySet(lCurveTY->KeyAdd(lTime), lTime, Translation->value.Y);
|
||||
lCurveTZ->KeySet(lCurveTZ->KeyAdd(lTime), lTime, Translation->value.Z);
|
||||
}
|
||||
|
||||
lCurveSX->KeyModifyEnd();
|
||||
lCurveSY->KeyModifyEnd();
|
||||
lCurveSZ->KeyModifyEnd();
|
||||
lCurveRX->KeyModifyEnd();
|
||||
lCurveRY->KeyModifyEnd();
|
||||
lCurveRZ->KeyModifyEnd();
|
||||
lCurveTX->KeyModifyEnd();
|
||||
lCurveTY->KeyModifyEnd();
|
||||
lCurveTZ->KeyModifyEnd();
|
||||
|
||||
if (eulerFilter)
|
||||
{
|
||||
FbxAnimCurve* lCurve[3];
|
||||
lCurve[0] = lCurveRX;
|
||||
lCurve[1] = lCurveRY;
|
||||
lCurve[2] = lCurveRZ;
|
||||
eulerFilter->Reset();
|
||||
eulerFilter->SetQualityTolerance(filterPrecision);
|
||||
eulerFilter->Apply(lCurve, 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Fbx::Exporter::ExportMorphs(bool morphMask, bool flatInbetween)
|
||||
{
|
||||
/*if (imported->MeshList == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int meshIdx = 0; meshIdx < imported->MeshList->Count; meshIdx++)
|
||||
{
|
||||
ImportedMesh^ meshList = imported->MeshList[meshIdx];
|
||||
FbxNode* pBaseNode = NULL;
|
||||
for (int nodeIdx = 0; nodeIdx < pMeshNodes->GetCount(); nodeIdx++)
|
||||
{
|
||||
FbxNode* pMeshNode = pMeshNodes->GetAt(nodeIdx);
|
||||
String^ framePath = gcnew String(pMeshNode->GetName());
|
||||
FbxNode* rootNode = pMeshNode;
|
||||
while ((rootNode = rootNode->GetParent()) != pScene->GetRootNode())
|
||||
{
|
||||
framePath = gcnew String(rootNode->GetName()) + "/" + framePath;
|
||||
}
|
||||
if (framePath == meshList->Path)
|
||||
{
|
||||
pBaseNode = pMeshNode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (pBaseNode == NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for each (ImportedMorph^ morph in imported->MorphList)
|
||||
{
|
||||
if (morph->Path != meshList->Path)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
int meshVertexIndex = 0;
|
||||
for (int meshObjIdx = pBaseNode->GetChildCount() - meshList->SubmeshList->Count; meshObjIdx < meshList->SubmeshList->Count; meshObjIdx++)
|
||||
{
|
||||
List<ImportedVertex^>^ vertList = meshList->SubmeshList[meshObjIdx]->VertexList;
|
||||
FbxNode* pBaseMeshNode = pBaseNode->GetChild(meshObjIdx);
|
||||
FbxMesh* pBaseMesh = pBaseMeshNode->GetMesh();
|
||||
int numColourSets = pBaseMesh->GetElementVertexColorCount();
|
||||
|
||||
FbxBlendShape* lBlendShape;
|
||||
WITH_MARSHALLED_STRING
|
||||
(
|
||||
pShapeName,
|
||||
morph->ClipName + (meshList->SubmeshList->Count > 1 ? "_" + meshObjIdx : String::Empty),
|
||||
lBlendShape = FbxBlendShape::Create(pScene, pShapeName);
|
||||
);
|
||||
FbxProperty rootGroupProp = FbxProperty::Create(lBlendShape, FbxStringDT, "RootGroup");
|
||||
pBaseMesh->AddDeformer(lBlendShape);
|
||||
List<ImportedMorphKeyframe^>^ keyframes = morph->KeyframeList;
|
||||
for (int i = 0; i < morph->Channels->Count; i++)
|
||||
{
|
||||
FbxBlendShapeChannel* lBlendShapeChannel;
|
||||
if (!flatInbetween)
|
||||
{
|
||||
WITH_MARSHALLED_STRING
|
||||
(
|
||||
pChannelName,
|
||||
gcnew String(lBlendShape->GetName()) + "." + keyframes[morph->Channels[i]->Item2]->Name->Substring(0, keyframes[morph->Channels[i]->Item2]->Name->LastIndexOf("_")),
|
||||
lBlendShapeChannel = FbxBlendShapeChannel::Create(pScene, pChannelName);
|
||||
);
|
||||
lBlendShapeChannel->DeformPercent = morph->Channels[i]->Item1;
|
||||
lBlendShape->AddBlendShapeChannel(lBlendShapeChannel);
|
||||
}
|
||||
|
||||
for (int frameIdx = 0; frameIdx < morph->Channels[i]->Item3; frameIdx++)
|
||||
{
|
||||
int shapeIdx = morph->Channels[i]->Item2 + frameIdx;
|
||||
ImportedMorphKeyframe^ keyframe = keyframes[shapeIdx];
|
||||
|
||||
FbxShape* pShape;
|
||||
if (!flatInbetween)
|
||||
{
|
||||
char* pMorphShapeName;
|
||||
try
|
||||
{
|
||||
pMorphShapeName = StringToCharArray(keyframe->Name);
|
||||
if (pScene->FindMember<FbxShape>(pMorphShapeName))
|
||||
{
|
||||
Marshal::FreeHGlobal((IntPtr)pMorphShapeName);
|
||||
pMorphShapeName = StringToCharArray(morph->ClipName + (meshList->SubmeshList->Count > 1 ? "_" + meshObjIdx : String::Empty) + "__" + keyframe->Name);
|
||||
}
|
||||
pShape = FbxShape::Create(pScene, pMorphShapeName);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Marshal::FreeHGlobal((IntPtr)pMorphShapeName);
|
||||
}
|
||||
if (frameIdx == morph->Channels[i]->Item3 - 1)
|
||||
{
|
||||
FbxProperty::Create(lBlendShape, FbxStringDT, rootGroupProp.GetName() + "|" + pShape->GetName());
|
||||
}
|
||||
lBlendShapeChannel->AddTargetShape(pShape, keyframe->Weight);
|
||||
}
|
||||
else
|
||||
{
|
||||
lBlendShapeChannel = FbxBlendShapeChannel::Create(pScene, "");
|
||||
lBlendShapeChannel->DeformPercent = morph->Channels[i]->Item1;
|
||||
lBlendShape->AddBlendShapeChannel(lBlendShapeChannel);
|
||||
|
||||
WITH_MARSHALLED_STRING
|
||||
(
|
||||
pMorphShapeName,
|
||||
morph->ClipName + (meshList->SubmeshList->Count > 1 ? "_" + meshObjIdx : String::Empty) + "." + keyframe->Name,
|
||||
pShape = FbxShape::Create(pScene, pMorphShapeName);
|
||||
);
|
||||
lBlendShapeChannel->AddTargetShape(pShape, 100);
|
||||
|
||||
FbxProperty weightProp;
|
||||
WITH_MARSHALLED_STRING
|
||||
(
|
||||
pWeightName,
|
||||
gcnew String(pShape->GetName()) + ".Weight",
|
||||
weightProp = FbxProperty::Create(pBaseMesh, FbxDoubleDT, pWeightName);
|
||||
);
|
||||
weightProp.ModifyFlag(FbxPropertyFlags::eUserDefined, true);
|
||||
weightProp.Set<double>(keyframe->Weight);
|
||||
}
|
||||
|
||||
pShape->InitControlPoints(vertList->Count);
|
||||
FbxVector4* pControlPoints = pShape->GetControlPoints();
|
||||
|
||||
for (int j = 0; j < vertList->Count; j++)
|
||||
{
|
||||
ImportedVertex^ vertex = vertList[j];
|
||||
Vector3 coords = vertex->Position;
|
||||
pControlPoints[j] = FbxVector4(coords.X, coords.Y, coords.Z, 0);
|
||||
}
|
||||
List<unsigned short>^ meshIndices = keyframe->MorphedVertexIndices;
|
||||
for (int j = 0; j < meshIndices->Count; j++)
|
||||
{
|
||||
int controlPointIndex = meshIndices[j] - meshVertexIndex;
|
||||
if (controlPointIndex >= 0 && controlPointIndex < vertList->Count)
|
||||
{
|
||||
Vector3 coords = keyframe->VertexList[j]->Position;
|
||||
pControlPoints[controlPointIndex] = FbxVector4(coords.X, coords.Y, coords.Z, 0);
|
||||
}
|
||||
}
|
||||
if (flatInbetween && meshIndices->Count == 0)
|
||||
{
|
||||
Vector3 coords = vertList[0]->Position;
|
||||
pControlPoints[0] = FbxVector4(coords.X - 1.0e-6, coords.Y, coords.Z, 0);
|
||||
}
|
||||
|
||||
if (flatInbetween && frameIdx > 0)
|
||||
{
|
||||
int shapeIdx = morph->Channels[i]->Item2 + frameIdx - 1;
|
||||
ImportedMorphKeyframe^ keyframe = keyframes[shapeIdx];
|
||||
|
||||
List<unsigned short>^ meshIndices = keyframe->MorphedVertexIndices;
|
||||
for (int j = 0; j < meshIndices->Count; j++)
|
||||
{
|
||||
int controlPointIndex = meshIndices[j] - meshVertexIndex;
|
||||
if (controlPointIndex >= 0 && controlPointIndex < vertList->Count)
|
||||
{
|
||||
Vector3 coords = keyframe->VertexList[j]->Position - vertList[controlPointIndex]->Position;
|
||||
pControlPoints[controlPointIndex] -= FbxVector4(coords.X, coords.Y, coords.Z, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (morphMask && frameIdx == 0)
|
||||
{
|
||||
int colourSetIdx = numColourSets + shapeIdx;
|
||||
FbxGeometryElementVertexColor* lGeometryElementVertexColor = pBaseMesh->GetElementVertexColor(colourSetIdx);
|
||||
if (lGeometryElementVertexColor == NULL)
|
||||
{
|
||||
lGeometryElementVertexColor = pBaseMesh->CreateElementVertexColor();
|
||||
}
|
||||
lGeometryElementVertexColor->SetMappingMode(FbxGeometryElement::eByControlPoint);
|
||||
lGeometryElementVertexColor->SetReferenceMode(FbxGeometryElement::eDirect);
|
||||
WITH_MARSHALLED_STRING
|
||||
(
|
||||
pColourLayerName, morph->ClipName + (meshList->SubmeshList->Count > 1 ? "_" + meshObjIdx : String::Empty) + "." + keyframe->Name,
|
||||
lGeometryElementVertexColor->SetName(pColourLayerName);
|
||||
);
|
||||
for (int j = 0; j < vertList->Count; j++)
|
||||
{
|
||||
lGeometryElementVertexColor->GetDirectArray().Add(FbxColor(1, 1, 1));
|
||||
}
|
||||
for (int j = 0; j < meshIndices->Count; j++)
|
||||
{
|
||||
int controlPointIndex = meshIndices[j] - meshVertexIndex;
|
||||
if (controlPointIndex >= 0 && controlPointIndex < vertList->Count)
|
||||
{
|
||||
lGeometryElementVertexColor->GetDirectArray().SetAt(controlPointIndex, FbxColor(0, 0, 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
meshVertexIndex += meshList->SubmeshList[meshObjIdx]->VertexList->Count;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
// Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "winres.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Language neutral resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU)
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL
|
||||
#pragma code_page(65001)
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE
|
||||
BEGIN
|
||||
"#include ""winres.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,0,0,1
|
||||
PRODUCTVERSION 1,0,0,1
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x40004L
|
||||
FILETYPE 0x2L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "000004b0"
|
||||
BEGIN
|
||||
VALUE "FileDescription", "AssetStudioFBXNative"
|
||||
VALUE "FileVersion", "1.0.0.1"
|
||||
VALUE "InternalName", "AssetStudioFBXNative.dll"
|
||||
VALUE "LegalCopyright", "Copyright (C) Perfare 2018-2020; Copyright (C) hozuki 2020"
|
||||
VALUE "OriginalFilename", "AssetStudioFBXNative.dll"
|
||||
VALUE "ProductName", "AssetStudioFBXNative"
|
||||
VALUE "ProductVersion", "1.0.0.1"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x0, 1200
|
||||
END
|
||||
END
|
||||
|
||||
#endif // Language neutral resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
||||
@@ -0,0 +1,202 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{11ea25a3-ed68-40ee-a9d0-7fde3b583027}</ProjectGuid>
|
||||
<RootNamespace>AssetStudioFBXNative</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<TargetExt>.dll</TargetExt>
|
||||
<OutDir>bin\$(Platform)\$(Configuration)\</OutDir>
|
||||
<IntDir>obj\$(Platform)\$(Configuration)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<TargetExt>.dll</TargetExt>
|
||||
<OutDir>bin\$(Platform)\$(Configuration)\</OutDir>
|
||||
<IntDir>obj\$(Platform)\$(Configuration)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<TargetExt>.dll</TargetExt>
|
||||
<OutDir>bin\$(Platform)\$(Configuration)\</OutDir>
|
||||
<IntDir>obj\$(Platform)\$(Configuration)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<TargetExt>.dll</TargetExt>
|
||||
<OutDir>bin\$(Platform)\$(Configuration)\</OutDir>
|
||||
<IntDir>obj\$(Platform)\$(Configuration)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_AS_DLL;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<AdditionalIncludeDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.0.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>libfbxsdk-mt.lib;libxml2-mt.lib;zlib-mt.lib;wininet.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.0.1\lib\vs2017\x86\debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<IgnoreSpecificDefaultLibraries>LIBCMT;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_AS_DLL;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<AdditionalIncludeDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.0.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>libfbxsdk-mt.lib;libxml2-mt.lib;zlib-mt.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.0.1\lib\vs2017\x86\release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_AS_DLL;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<AdditionalIncludeDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.0.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>libfbxsdk-mt.lib;libxml2-mt.lib;zlib-mt.lib;wininet.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.0.1\lib\vs2017\x64\debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<IgnoreSpecificDefaultLibraries>LIBCMT;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_AS_DLL;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<AdditionalIncludeDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.0.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>libfbxsdk-mt.lib;libxml2-mt.lib;zlib-mt.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.0.1\lib\vs2017\x64\release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="asfbx_anim_context.cpp" />
|
||||
<ClCompile Include="asfbx_context.cpp" />
|
||||
<ClCompile Include="api.cpp" />
|
||||
<ClCompile Include="asfbx_morph_context.cpp" />
|
||||
<ClCompile Include="asfbx_skin_context.cpp" />
|
||||
<ClCompile Include="utils.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="api.h" />
|
||||
<ClInclude Include="asfbx_anim_context.h" />
|
||||
<ClInclude Include="asfbx_context.h" />
|
||||
<ClInclude Include="asfbx_morph_context.h" />
|
||||
<ClInclude Include="asfbx_skin_context.h" />
|
||||
<ClInclude Include="bool32_t.h" />
|
||||
<ClInclude Include="dllexport.h" />
|
||||
<ClInclude Include="resource.h" />
|
||||
<ClInclude Include="utils.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="cpp.hint" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="AssetStudioFBXNative.rc" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
<Target Name="AfterBuild">
|
||||
<MSBuild Condition=" '$(Platform)' == 'Win32' " Projects="$(MSBuildProjectFile)" Properties="Platform=x64;PlatFormTarget=x64" RunEachTargetSeparately="true" />
|
||||
</Target>
|
||||
</Project>
|
||||
@@ -0,0 +1,74 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="源文件">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;c++;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="头文件">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="资源文件">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="utils.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="api.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="asfbx_context.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="asfbx_skin_context.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="asfbx_anim_context.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="asfbx_morph_context.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="dllexport.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="api.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="utils.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="bool32_t.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asfbx_context.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asfbx_skin_context.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asfbx_anim_context.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="asfbx_morph_context.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="resource.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="cpp.hint" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="AssetStudioFBXNative.rc">
|
||||
<Filter>资源文件</Filter>
|
||||
</ResourceCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,161 @@
|
||||
#pragma once
|
||||
|
||||
#include "dllexport.h"
|
||||
#include "bool32_t.h"
|
||||
|
||||
namespace fbxsdk
|
||||
{
|
||||
class FbxNode;
|
||||
class FbxFileTexture;
|
||||
template<typename T, const int Alignment = 16>
|
||||
class FbxArray;
|
||||
class FbxCluster;
|
||||
class FbxMesh;
|
||||
class FbxSurfacePhong;
|
||||
}
|
||||
|
||||
struct AsFbxContext;
|
||||
struct AsFbxSkinContext;
|
||||
struct AsFbxAnimContext;
|
||||
struct AsFbxMorphContext;
|
||||
|
||||
AS_API(void) AsUtilQuaternionToEuler(float qx, float qy, float qz, float qw, float* vx, float* vy, float* vz);
|
||||
|
||||
AS_API(void) AsUtilEulerToQuaternion(float vx, float vy, float vz, float* qx, float* qy, float* qz, float* qw);
|
||||
|
||||
// All strings ([const] char *) in this header are UTF-8 strings.
|
||||
|
||||
AS_API(AsFbxContext*) AsFbxCreateContext();
|
||||
|
||||
// Do not free pErrMsg
|
||||
AS_API(bool32_t) AsFbxInitializeContext(AsFbxContext* pContext, const char* pFileName, float scaleFactor, int32_t versionIndex, bool32_t isAscii, bool32_t is60Fps, const char** pErrMsg);
|
||||
|
||||
AS_API(void) AsFbxDisposeContext(AsFbxContext** ppContext);
|
||||
|
||||
AS_API(void) AsFbxSetFramePaths(AsFbxContext* pContext, const char* ppPaths[], int32_t count);
|
||||
|
||||
AS_API(void) AsFbxExportScene(AsFbxContext* pContext);
|
||||
|
||||
AS_API(fbxsdk::FbxNode*) AsFbxGetSceneRootNode(AsFbxContext* pContext);
|
||||
|
||||
AS_API(fbxsdk::FbxNode*) AsFbxExportSingleFrame(AsFbxContext* pContext, fbxsdk::FbxNode* pParentNode, const char* pFramePath, const char* pFrameName, float localPositionX, float localPositionY, float localPositionZ, float localRotationX, float localRotationY, float localRotationZ, float localScaleX, float localScaleY, float localScaleZ);
|
||||
|
||||
AS_API(void) AsFbxSetJointsNode_CastToBone(AsFbxContext* pContext, fbxsdk::FbxNode* pNode, float boneSize);
|
||||
|
||||
AS_API(void) AsFbxSetJointsNode_BoneInPath(AsFbxContext* pContext, fbxsdk::FbxNode* pNode, float boneSize);
|
||||
|
||||
AS_API(void) AsFbxSetJointsNode_Generic(AsFbxContext* pContext, fbxsdk::FbxNode* pNode);
|
||||
|
||||
AS_API(void) AsFbxPrepareMaterials(AsFbxContext* pContext, int32_t materialCount, int32_t textureCount);
|
||||
|
||||
AS_API(fbxsdk::FbxFileTexture*) AsFbxCreateTexture(AsFbxContext* pContext, const char* pMatTexName);
|
||||
|
||||
AS_API(void) AsFbxLinkTexture(int32_t dest, fbxsdk::FbxFileTexture* pTexture, fbxsdk::FbxSurfacePhong* pMaterial, float offsetX, float offsetY, float scaleX, float scaleY);
|
||||
|
||||
AS_API(fbxsdk::FbxArray<fbxsdk::FbxCluster*>*) AsFbxMeshCreateClusterArray(int32_t boneCount);
|
||||
|
||||
AS_API(void) AsFbxMeshDisposeClusterArray(fbxsdk::FbxArray<fbxsdk::FbxCluster*>** ppArray);
|
||||
|
||||
AS_API(fbxsdk::FbxCluster*) AsFbxMeshCreateCluster(AsFbxContext* pContext, fbxsdk::FbxNode* pBoneNode);
|
||||
|
||||
AS_API(void) AsFbxMeshAddCluster(fbxsdk::FbxArray<fbxsdk::FbxCluster*>* pArray, /* CanBeNull */ fbxsdk::FbxCluster* pCluster);
|
||||
|
||||
AS_API(fbxsdk::FbxMesh*) AsFbxMeshCreateMesh(AsFbxContext* pContext, fbxsdk::FbxNode* pFrameNode);
|
||||
|
||||
AS_API(void) AsFbxMeshInitControlPoints(fbxsdk::FbxMesh* pMesh, int32_t vertexCount);
|
||||
|
||||
AS_API(void) AsFbxMeshCreateElementNormal(fbxsdk::FbxMesh* pMesh);
|
||||
|
||||
AS_API(void) AsFbxMeshCreateDiffuseUV(fbxsdk::FbxMesh* pMesh, int32_t uv);
|
||||
|
||||
AS_API(void) AsFbxMeshCreateNormalMapUV(fbxsdk::FbxMesh* pMesh, int32_t uv);
|
||||
|
||||
AS_API(void) AsFbxMeshCreateElementTangent(fbxsdk::FbxMesh* pMesh);
|
||||
|
||||
AS_API(void) AsFbxMeshCreateElementVertexColor(fbxsdk::FbxMesh* pMesh);
|
||||
|
||||
AS_API(void) AsFbxMeshCreateElementMaterial(fbxsdk::FbxMesh* pMesh);
|
||||
|
||||
AS_API(fbxsdk::FbxSurfacePhong*) AsFbxCreateMaterial(AsFbxContext* pContext, const char* pMatName,
|
||||
float diffuseR, float diffuseG, float diffuseB,
|
||||
float ambientR, float ambientG, float ambientB,
|
||||
float emissiveR, float emissiveG, float emissiveB,
|
||||
float specularR, float specularG, float specularB,
|
||||
float reflectR, float reflectG, float reflectB,
|
||||
float shininess, float transparency);
|
||||
|
||||
AS_API(int32_t) AsFbxAddMaterialToFrame(fbxsdk::FbxNode* pFrameNode, fbxsdk::FbxSurfacePhong* pMaterial);
|
||||
|
||||
AS_API(void) AsFbxSetFrameShadingModeToTextureShading(fbxsdk::FbxNode* pFrameNode);
|
||||
|
||||
AS_API(void) AsFbxMeshSetControlPoint(fbxsdk::FbxMesh* pMesh, int32_t index, float x, float y, float z);
|
||||
|
||||
AS_API(void) AsFbxMeshAddPolygon(fbxsdk::FbxMesh* pMesh, int32_t materialIndex, int32_t index0, int32_t index1, int32_t index2);
|
||||
|
||||
AS_API(void) AsFbxMeshElementNormalAdd(fbxsdk::FbxMesh* pMesh, int32_t elementIndex, float x, float y, float z);
|
||||
|
||||
AS_API(void) AsFbxMeshElementUVAdd(fbxsdk::FbxMesh* pMesh, int32_t elementIndex, float u, float v);
|
||||
|
||||
AS_API(void) AsFbxMeshElementTangentAdd(fbxsdk::FbxMesh* pMesh, int32_t elementIndex, float x, float y, float z, float w);
|
||||
|
||||
AS_API(void) AsFbxMeshElementVertexColorAdd(fbxsdk::FbxMesh* pMesh, int32_t elementIndex, float r, float g, float b, float a);
|
||||
|
||||
AS_API(void) AsFbxMeshSetBoneWeight(fbxsdk::FbxArray<fbxsdk::FbxCluster*>* pClusterArray, int32_t boneIndex, int32_t vertexIndex, float weight);
|
||||
|
||||
AS_API(AsFbxSkinContext*) AsFbxMeshCreateSkinContext(AsFbxContext* pContext, fbxsdk::FbxNode* pFrameNode);
|
||||
|
||||
AS_API(void) AsFbxMeshDisposeSkinContext(AsFbxSkinContext** ppSkinContext);
|
||||
|
||||
AS_API(bool32_t) FbxClusterArray_HasItemAt(fbxsdk::FbxArray<fbxsdk::FbxCluster*>* pClusterArray, int32_t index);
|
||||
|
||||
AS_API(void) AsFbxMeshSkinAddCluster(AsFbxSkinContext* pSkinContext, fbxsdk::FbxArray<fbxsdk::FbxCluster*>* pClusterArray, int32_t index, float pBoneMatrix[16]);
|
||||
|
||||
AS_API(void) AsFbxMeshAddDeformer(AsFbxSkinContext* pSkinContext, fbxsdk::FbxMesh* pMesh);
|
||||
|
||||
AS_API(AsFbxAnimContext*) AsFbxAnimCreateContext(bool32_t eulerFilter);
|
||||
|
||||
AS_API(void) AsFbxAnimDisposeContext(AsFbxAnimContext** ppAnimContext);
|
||||
|
||||
AS_API(void) AsFbxAnimPrepareStackAndLayer(AsFbxContext* pContext, AsFbxAnimContext* pAnimContext, const char* pTakeName);
|
||||
|
||||
AS_API(void) AsFbxAnimLoadCurves(fbxsdk::FbxNode* pNode, AsFbxAnimContext* pAnimContext);
|
||||
|
||||
AS_API(void) AsFbxAnimBeginKeyModify(AsFbxAnimContext* pAnimContext);
|
||||
|
||||
AS_API(void) AsFbxAnimEndKeyModify(AsFbxAnimContext* pAnimContext);
|
||||
|
||||
AS_API(void) AsFbxAnimAddScalingKey(AsFbxAnimContext* pAnimContext, float time, float x, float y, float z);
|
||||
|
||||
AS_API(void) AsFbxAnimAddRotationKey(AsFbxAnimContext* pAnimContext, float time, float x, float y, float z);
|
||||
|
||||
AS_API(void) AsFbxAnimAddTranslationKey(AsFbxAnimContext* pAnimContext, float time, float x, float y, float z);
|
||||
|
||||
AS_API(void) AsFbxAnimApplyEulerFilter(AsFbxAnimContext* pAnimContext, float filterPrecision);
|
||||
|
||||
AS_API(int32_t) AsFbxAnimGetCurrentBlendShapeChannelCount(AsFbxAnimContext* pAnimContext, fbxsdk::FbxNode* pNode);
|
||||
|
||||
AS_API(bool32_t) AsFbxAnimIsBlendShapeChannelMatch(AsFbxAnimContext* pAnimContext, int32_t channelIndex, const char* channelName);
|
||||
|
||||
AS_API(void) AsFbxAnimBeginBlendShapeAnimCurve(AsFbxAnimContext* pAnimContext, int32_t channelIndex);
|
||||
|
||||
AS_API(void) AsFbxAnimEndBlendShapeAnimCurve(AsFbxAnimContext* pAnimContext);
|
||||
|
||||
AS_API(void) AsFbxAnimAddBlendShapeKeyframe(AsFbxAnimContext* pAnimContext, float time, float value);
|
||||
|
||||
AS_API(AsFbxMorphContext*) AsFbxMorphCreateContext();
|
||||
|
||||
AS_API(void) AsFbxMorphInitializeContext(AsFbxContext* pContext, AsFbxMorphContext* pMorphContext, fbxsdk::FbxNode* pNode);
|
||||
|
||||
AS_API(void) AsFbxMorphDisposeContext(AsFbxMorphContext** ppMorphContext);
|
||||
|
||||
AS_API(void) AsFbxMorphAddBlendShapeChannel(AsFbxContext* pContext, AsFbxMorphContext* pMorphContext, const char* channelName);
|
||||
|
||||
AS_API(void) AsFbxMorphAddBlendShapeChannelShape(AsFbxContext* pContext, AsFbxMorphContext* pMorphContext, float weight, const char* shapeName);
|
||||
|
||||
AS_API(void) AsFbxMorphCopyBlendShapeControlPoints(AsFbxMorphContext* pMorphContext);
|
||||
|
||||
AS_API(void) AsFbxMorphSetBlendShapeVertex(AsFbxMorphContext* pMorphContext, uint32_t index, float x, float y, float z);
|
||||
|
||||
AS_API(void) AsFbxMorphCopyBlendShapeControlPointsNormal(AsFbxMorphContext* pMorphContext);
|
||||
|
||||
AS_API(void) AsFbxMorphSetBlendShapeVertexNormal(AsFbxMorphContext* pMorphContext, uint32_t index, float x, float y, float z);
|
||||
@@ -0,0 +1,27 @@
|
||||
#include "asfbx_anim_context.h"
|
||||
|
||||
AsFbxAnimContext::AsFbxAnimContext(bool32_t eulerFilter)
|
||||
: lFilter(nullptr)
|
||||
{
|
||||
if (eulerFilter)
|
||||
{
|
||||
lFilter = new FbxAnimCurveFilterUnroll();
|
||||
}
|
||||
|
||||
lAnimStack = nullptr;
|
||||
lAnimLayer = nullptr;
|
||||
|
||||
lCurveSX = nullptr;
|
||||
lCurveSY = nullptr;
|
||||
lCurveSZ = nullptr;
|
||||
lCurveRX = nullptr;
|
||||
lCurveRY = nullptr;
|
||||
lCurveRZ = nullptr;
|
||||
lCurveTX = nullptr;
|
||||
lCurveTY = nullptr;
|
||||
lCurveTZ = nullptr;
|
||||
|
||||
pMesh = nullptr;
|
||||
lBlendShape = nullptr;
|
||||
lAnimCurve = nullptr;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include <fbxsdk.h>
|
||||
|
||||
#include "bool32_t.h"
|
||||
|
||||
struct AsFbxAnimContext
|
||||
{
|
||||
|
||||
FbxAnimCurveFilterUnroll* lFilter;
|
||||
|
||||
FbxAnimStack* lAnimStack;
|
||||
FbxAnimLayer* lAnimLayer;
|
||||
|
||||
FbxAnimCurve* lCurveSX;
|
||||
FbxAnimCurve* lCurveSY;
|
||||
FbxAnimCurve* lCurveSZ;
|
||||
FbxAnimCurve* lCurveRX;
|
||||
FbxAnimCurve* lCurveRY;
|
||||
FbxAnimCurve* lCurveRZ;
|
||||
FbxAnimCurve* lCurveTX;
|
||||
FbxAnimCurve* lCurveTY;
|
||||
FbxAnimCurve* lCurveTZ;
|
||||
|
||||
FbxMesh* pMesh;
|
||||
FbxBlendShape* lBlendShape;
|
||||
FbxAnimCurve* lAnimCurve;
|
||||
|
||||
AsFbxAnimContext(bool32_t eulerFilter);
|
||||
~AsFbxAnimContext() = default;
|
||||
|
||||
};
|
||||
@@ -0,0 +1,33 @@
|
||||
#include <fbxsdk.h>
|
||||
|
||||
#include "asfbx_context.h"
|
||||
|
||||
AsFbxContext::AsFbxContext()
|
||||
{
|
||||
pSdkManager = nullptr;
|
||||
pScene = nullptr;
|
||||
pTextures = nullptr;
|
||||
pMaterials = nullptr;
|
||||
pExporter = nullptr;
|
||||
pBindPose = nullptr;
|
||||
}
|
||||
|
||||
AsFbxContext::~AsFbxContext()
|
||||
{
|
||||
framePaths.clear();
|
||||
|
||||
delete pMaterials;
|
||||
delete pTextures;
|
||||
|
||||
if (pExporter != nullptr) {
|
||||
pExporter->Destroy();
|
||||
}
|
||||
|
||||
if (pScene != nullptr) {
|
||||
pScene->Destroy();
|
||||
}
|
||||
|
||||
if (pSdkManager != nullptr) {
|
||||
pSdkManager->Destroy();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <unordered_set>
|
||||
|
||||
namespace fbxsdk
|
||||
{
|
||||
class FbxManager;
|
||||
class FbxScene;
|
||||
class FbxExporter;
|
||||
template<typename T, const int Alignment = 16>
|
||||
class FbxArray;
|
||||
class FbxFileTexture;
|
||||
class FbxSurfacePhong;
|
||||
class FbxPose;
|
||||
}
|
||||
|
||||
struct AsFbxContext
|
||||
{
|
||||
|
||||
fbxsdk::FbxManager* pSdkManager;
|
||||
fbxsdk::FbxScene* pScene;
|
||||
fbxsdk::FbxArray<fbxsdk::FbxFileTexture*>* pTextures;
|
||||
fbxsdk::FbxArray<fbxsdk::FbxSurfacePhong*>* pMaterials;
|
||||
fbxsdk::FbxExporter* pExporter;
|
||||
fbxsdk::FbxPose* pBindPose;
|
||||
|
||||
std::unordered_set<std::string> framePaths;
|
||||
|
||||
AsFbxContext();
|
||||
~AsFbxContext();
|
||||
};
|
||||
@@ -0,0 +1,9 @@
|
||||
#include "asfbx_morph_context.h"
|
||||
|
||||
AsFbxMorphContext::AsFbxMorphContext()
|
||||
{
|
||||
pMesh = nullptr;
|
||||
lBlendShape = nullptr;
|
||||
lBlendShapeChannel = nullptr;
|
||||
lShape = nullptr;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include <fbxsdk.h>
|
||||
|
||||
struct AsFbxMorphContext
|
||||
{
|
||||
|
||||
FbxMesh* pMesh;
|
||||
FbxBlendShape* lBlendShape;
|
||||
FbxBlendShapeChannel* lBlendShapeChannel;
|
||||
FbxShape* lShape;
|
||||
|
||||
AsFbxMorphContext();
|
||||
~AsFbxMorphContext() = default;
|
||||
|
||||
};
|
||||
@@ -0,0 +1,16 @@
|
||||
#include "asfbx_skin_context.h"
|
||||
#include "asfbx_context.h"
|
||||
|
||||
AsFbxSkinContext::AsFbxSkinContext(AsFbxContext* pContext, FbxNode* pFrameNode)
|
||||
: pSkin(nullptr)
|
||||
{
|
||||
if (pContext != nullptr && pContext->pScene != nullptr)
|
||||
{
|
||||
pSkin = FbxSkin::Create(pContext->pScene, "");
|
||||
}
|
||||
|
||||
if (pFrameNode != nullptr)
|
||||
{
|
||||
lMeshMatrix = pFrameNode->EvaluateGlobalTransform();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include <fbxsdk.h>
|
||||
|
||||
struct AsFbxContext;
|
||||
|
||||
struct AsFbxSkinContext
|
||||
{
|
||||
|
||||
FbxSkin* pSkin;
|
||||
FbxAMatrix lMeshMatrix;
|
||||
|
||||
AsFbxSkinContext(AsFbxContext* pContext, FbxNode* pFrameNode);
|
||||
~AsFbxSkinContext() = default;
|
||||
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
typedef uint32_t bool32_t;
|
||||
@@ -0,0 +1 @@
|
||||
#define AS_API(ret_type)
|
||||
@@ -0,0 +1,56 @@
|
||||
#pragma once
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#if _MSC_VER < 1910 // MSVC 2017-
|
||||
#error MSVC 2017 or later is required.
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(WIN32) || defined(_WIN32) || defined(__CYGWIN__) || defined(__MINGW__)
|
||||
#ifdef _AS_DLL
|
||||
#ifdef __GNUC__
|
||||
#define _AS_EXPORT __attribute__ ((dllexport))
|
||||
#else
|
||||
#define _AS_EXPORT __declspec(dllexport)
|
||||
#endif
|
||||
#else
|
||||
#ifdef __GNUC__
|
||||
#define _AS_EXPORT __attribute__ ((dllimport))
|
||||
#else
|
||||
#define _AS_EXPORT __declspec(dllimport)
|
||||
#endif
|
||||
#endif
|
||||
#define _AS_LOCAL
|
||||
#else
|
||||
#if __GNUC__ >= 4
|
||||
#define _AS_EXPORT __attribute__ ((visibility ("default")))
|
||||
#define _AS_LOCAL __attribute__ ((visibility ("hidden")))
|
||||
#else
|
||||
#define _AS_EXPORT
|
||||
#define _AS_LOCAL
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#ifndef _EXTERN_C_STMT
|
||||
#define _EXTERN_C_STMT extern "C"
|
||||
#endif
|
||||
#else
|
||||
#ifndef _EXTERN_C_STMT
|
||||
#define _EXTERN_C_STMT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef _AS_CALL
|
||||
#if defined(WIN32) || defined(_WIN32)
|
||||
#define _AS_CALL __stdcall
|
||||
#else
|
||||
#define _AS_CALL /* __cdecl */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define AS_API(ret_type) _EXTERN_C_STMT _AS_EXPORT ret_type _AS_CALL
|
||||
#else
|
||||
#define AS_API(ret_type) _EXTERN_C_STMT _AS_EXPORT _AS_CALL ret_type
|
||||
#endif
|
||||
@@ -0,0 +1,14 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by AssetStudioFBXNative.rc
|
||||
|
||||
// 新对象的下一组默认值
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 101
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1001
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,43 @@
|
||||
#include <fbxsdk.h>
|
||||
#include <cassert>
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
Vector3::Vector3()
|
||||
: X(0), Y(0), Z(0)
|
||||
{
|
||||
}
|
||||
|
||||
Vector3::Vector3(float x, float y, float z)
|
||||
: X(x), Y(y), Z(z)
|
||||
{
|
||||
}
|
||||
|
||||
Quaternion::Quaternion()
|
||||
: X(0), Y(0), Z(0), W(1)
|
||||
{
|
||||
}
|
||||
|
||||
Quaternion::Quaternion(float x, float y, float z)
|
||||
: X(x), Y(y), Z(z), W(1)
|
||||
{
|
||||
}
|
||||
|
||||
Quaternion::Quaternion(float x, float y, float z, float w)
|
||||
: X(x), Y(y), Z(z), W(w)
|
||||
{
|
||||
}
|
||||
|
||||
Vector3 QuaternionToEuler(Quaternion q) {
|
||||
FbxAMatrix lMatrixRot;
|
||||
lMatrixRot.SetQ(FbxQuaternion(q.X, q.Y, q.Z, q.W));
|
||||
FbxVector4 lEuler = lMatrixRot.GetR();
|
||||
return Vector3((float)lEuler[0], (float)lEuler[1], (float)lEuler[2]);
|
||||
}
|
||||
|
||||
Quaternion EulerToQuaternion(Vector3 v) {
|
||||
FbxAMatrix lMatrixRot;
|
||||
lMatrixRot.SetR(FbxVector4(v.X, v.Y, v.Z));
|
||||
FbxQuaternion lQuaternion = lMatrixRot.GetQ();
|
||||
return Quaternion((float)lQuaternion[0], (float)lQuaternion[1], (float)lQuaternion[2], (float)lQuaternion[3]);
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
struct Vector3 {
|
||||
|
||||
float X;
|
||||
float Y;
|
||||
float Z;
|
||||
|
||||
Vector3();
|
||||
Vector3(float x, float y, float z);
|
||||
|
||||
};
|
||||
|
||||
struct Quaternion {
|
||||
|
||||
float X;
|
||||
float Y;
|
||||
float Z;
|
||||
float W;
|
||||
|
||||
Quaternion();
|
||||
Quaternion(float x, float y, float z);
|
||||
Quaternion(float x, float y, float z, float w);
|
||||
|
||||
};
|
||||
|
||||
Vector3 QuaternionToEuler(Quaternion q);
|
||||
|
||||
Quaternion EulerToQuaternion(Vector3 v);
|
||||
@@ -0,0 +1,60 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{BD76E63F-1517-47FA-8233-33E853A3ACEE}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>AssetStudio.FbxInterop</RootNamespace>
|
||||
<AssemblyName>AssetStudioFBXWrapper</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<Deterministic>true</Deterministic>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Fbx.PInvoke.cs" />
|
||||
<Compile Include="FbxDll.cs" />
|
||||
<Compile Include="FbxExporterContext.cs" />
|
||||
<Compile Include="FbxExporterContext.PInvoke.cs" />
|
||||
<Compile Include="Fbx.cs" />
|
||||
<Compile Include="FbxExporter.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\AssetStudio.PInvoke\AssetStudio.PInvoke.csproj">
|
||||
<Project>{40c796b5-88ce-4adc-acd6-2f4862b7f136}</Project>
|
||||
<Name>AssetStudio.PInvoke</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\AssetStudio\AssetStudio.csproj">
|
||||
<Project>{7662f8c2-7bfd-442e-a948-a43b4f7eb06e}</Project>
|
||||
<Name>AssetStudio</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
||||
@@ -0,0 +1,16 @@
|
||||
using System.Runtime.InteropServices;
|
||||
using AssetStudio.FbxInterop;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
partial class Fbx
|
||||
{
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern void AsUtilQuaternionToEuler(float qx, float qy, float qz, float qw, out float vx, out float vy, out float vz);
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern void AsUtilEulerToQuaternion(float vx, float vy, float vz, out float qx, out float qy, out float qz, out float qw);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
using AssetStudio.FbxInterop;
|
||||
using AssetStudio.PInvoke;
|
||||
using System.IO;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public static partial class Fbx
|
||||
{
|
||||
|
||||
static Fbx()
|
||||
{
|
||||
DllLoader.PreloadDll(FbxDll.DllName);
|
||||
}
|
||||
|
||||
public static Vector3 QuaternionToEuler(Quaternion q)
|
||||
{
|
||||
AsUtilQuaternionToEuler(q.X, q.Y, q.Z, q.W, out var x, out var y, out var z);
|
||||
return new Vector3(x, y, z);
|
||||
}
|
||||
|
||||
public static Quaternion EulerToQuaternion(Vector3 v)
|
||||
{
|
||||
AsUtilEulerToQuaternion(v.X, v.Y, v.Z, out var x, out var y, out var z, out var w);
|
||||
return new Quaternion(x, y, z, w);
|
||||
}
|
||||
|
||||
public static class Exporter
|
||||
{
|
||||
|
||||
public static void Export(string path, IImported imported, bool eulerFilter, float filterPrecision,
|
||||
bool allNodes, bool skins, bool animation, bool blendShape, bool castToBone, float boneSize, float scaleFactor, int versionIndex, bool isAscii)
|
||||
{
|
||||
var file = new FileInfo(path);
|
||||
var dir = file.Directory;
|
||||
|
||||
if (!dir.Exists)
|
||||
{
|
||||
dir.Create();
|
||||
}
|
||||
|
||||
var currentDir = Directory.GetCurrentDirectory();
|
||||
Directory.SetCurrentDirectory(dir.FullName);
|
||||
|
||||
var name = Path.GetFileName(path);
|
||||
|
||||
using (var exporter = new FbxExporter(name, imported, allNodes, skins, castToBone, boneSize, scaleFactor, versionIndex, isAscii))
|
||||
{
|
||||
exporter.Initialize();
|
||||
exporter.ExportAll(blendShape, animation, eulerFilter, filterPrecision);
|
||||
}
|
||||
|
||||
Directory.SetCurrentDirectory(currentDir);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace AssetStudio.FbxInterop
|
||||
{
|
||||
internal static class FbxDll
|
||||
{
|
||||
|
||||
internal const string DllName = "AssetStudioFBXNative";
|
||||
internal const string FbxsdkDllName = "libfbxsdk";
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,242 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace AssetStudio.FbxInterop
|
||||
{
|
||||
internal sealed class FbxExporter : IDisposable
|
||||
{
|
||||
|
||||
private FbxExporterContext _context;
|
||||
|
||||
private readonly string _fileName;
|
||||
private readonly IImported _imported;
|
||||
private readonly bool _allNodes;
|
||||
private readonly bool _exportSkins;
|
||||
private readonly bool _castToBone;
|
||||
private readonly float _boneSize;
|
||||
private readonly float _scaleFactor;
|
||||
private readonly int _versionIndex;
|
||||
private readonly bool _isAscii;
|
||||
|
||||
internal FbxExporter(string fileName, IImported imported, bool allNodes, bool exportSkins, bool castToBone, float boneSize, float scaleFactor, int versionIndex, bool isAscii)
|
||||
{
|
||||
_context = new FbxExporterContext();
|
||||
|
||||
_fileName = fileName;
|
||||
_imported = imported;
|
||||
_allNodes = allNodes;
|
||||
_exportSkins = exportSkins;
|
||||
_castToBone = castToBone;
|
||||
_boneSize = boneSize;
|
||||
_scaleFactor = scaleFactor;
|
||||
_versionIndex = versionIndex;
|
||||
_isAscii = isAscii;
|
||||
}
|
||||
|
||||
~FbxExporter()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (IsDisposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
public bool IsDisposed { get; private set; }
|
||||
|
||||
private void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
_context.Dispose();
|
||||
}
|
||||
|
||||
IsDisposed = true;
|
||||
}
|
||||
|
||||
internal void Initialize()
|
||||
{
|
||||
var is60Fps = _imported.AnimationList.Count > 0 && _imported.AnimationList[0].SampleRate.Equals(60.0f);
|
||||
|
||||
_context.Initialize(_fileName, _scaleFactor, _versionIndex, _isAscii, is60Fps);
|
||||
|
||||
if (!_allNodes)
|
||||
{
|
||||
var framePaths = SearchHierarchy();
|
||||
|
||||
_context.SetFramePaths(framePaths);
|
||||
}
|
||||
}
|
||||
|
||||
internal void ExportAll(bool blendShape, bool animation, bool eulerFilter, float filterPrecision)
|
||||
{
|
||||
var meshFrames = new List<ImportedFrame>();
|
||||
|
||||
ExportRootFrame(meshFrames);
|
||||
|
||||
if (_imported.MeshList != null)
|
||||
{
|
||||
SetJointsFromImportedMeshes();
|
||||
|
||||
PrepareMaterials();
|
||||
|
||||
ExportMeshFrames(_imported.RootFrame, meshFrames);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetJointsNode(_imported.RootFrame, null, true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (blendShape)
|
||||
{
|
||||
ExportMorphs();
|
||||
}
|
||||
|
||||
if (animation)
|
||||
{
|
||||
ExportAnimations(eulerFilter, filterPrecision);
|
||||
}
|
||||
|
||||
ExportScene();
|
||||
}
|
||||
|
||||
private void ExportMorphs()
|
||||
{
|
||||
_context.ExportMorphs(_imported.RootFrame, _imported.MorphList);
|
||||
}
|
||||
|
||||
private void ExportAnimations(bool eulerFilter, float filterPrecision)
|
||||
{
|
||||
_context.ExportAnimations(_imported.RootFrame, _imported.AnimationList, eulerFilter, filterPrecision);
|
||||
}
|
||||
|
||||
private void ExportRootFrame(List<ImportedFrame> meshFrames)
|
||||
{
|
||||
_context.ExportFrame(_imported.MeshList, meshFrames, _imported.RootFrame);
|
||||
}
|
||||
|
||||
private void ExportScene()
|
||||
{
|
||||
_context.ExportScene();
|
||||
}
|
||||
|
||||
private void SetJointsFromImportedMeshes()
|
||||
{
|
||||
if (!_exportSkins)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Debug.Assert(_imported.MeshList != null);
|
||||
|
||||
var bonePaths = new HashSet<string>();
|
||||
|
||||
foreach (var mesh in _imported.MeshList)
|
||||
{
|
||||
var boneList = mesh.BoneList;
|
||||
|
||||
if (boneList != null)
|
||||
{
|
||||
foreach (var bone in boneList)
|
||||
{
|
||||
bonePaths.Add(bone.Path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SetJointsNode(_imported.RootFrame, bonePaths, _castToBone);
|
||||
}
|
||||
|
||||
private void SetJointsNode(ImportedFrame rootFrame, HashSet<string> bonePaths, bool castToBone)
|
||||
{
|
||||
_context.SetJointsNode(rootFrame, bonePaths, castToBone, _boneSize);
|
||||
}
|
||||
|
||||
private void PrepareMaterials()
|
||||
{
|
||||
_context.PrepareMaterials(_imported.MaterialList.Count, _imported.TextureList.Count);
|
||||
}
|
||||
|
||||
private void ExportMeshFrames(ImportedFrame rootFrame, List<ImportedFrame> meshFrames)
|
||||
{
|
||||
foreach (var meshFrame in meshFrames)
|
||||
{
|
||||
_context.ExportMeshFromFrame(rootFrame, meshFrame, _imported.MeshList, _imported.MaterialList, _imported.TextureList, _exportSkins);
|
||||
}
|
||||
}
|
||||
|
||||
private HashSet<string> SearchHierarchy()
|
||||
{
|
||||
if (_imported.MeshList == null || _imported.MeshList.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var exportFrames = new HashSet<string>();
|
||||
|
||||
SearchHierarchy(_imported.RootFrame, _imported.MeshList, exportFrames);
|
||||
|
||||
return exportFrames;
|
||||
}
|
||||
|
||||
private static void SearchHierarchy(ImportedFrame rootFrame, List<ImportedMesh> meshList, HashSet<string> exportFrames)
|
||||
{
|
||||
var frameStack = new Stack<ImportedFrame>();
|
||||
|
||||
frameStack.Push(rootFrame);
|
||||
|
||||
while (frameStack.Count > 0)
|
||||
{
|
||||
var frame = frameStack.Pop();
|
||||
|
||||
var meshListSome = ImportedHelpers.FindMesh(frame.Path, meshList);
|
||||
|
||||
if (meshListSome != null)
|
||||
{
|
||||
var parent = frame;
|
||||
|
||||
while (parent != null)
|
||||
{
|
||||
exportFrames.Add(parent.Path);
|
||||
parent = parent.Parent;
|
||||
}
|
||||
|
||||
var boneList = meshListSome.BoneList;
|
||||
|
||||
if (boneList != null)
|
||||
{
|
||||
foreach (var bone in boneList)
|
||||
{
|
||||
if (!exportFrames.Contains(bone.Path))
|
||||
{
|
||||
var boneParent = rootFrame.FindFrameByPath(bone.Path);
|
||||
|
||||
while (boneParent != null)
|
||||
{
|
||||
exportFrames.Add(boneParent.Path);
|
||||
boneParent = boneParent.Parent;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = frame.Count - 1; i >= 0; i -= 1)
|
||||
{
|
||||
frameStack.Push(frame[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,325 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using AssetStudio.PInvoke;
|
||||
|
||||
namespace AssetStudio.FbxInterop
|
||||
{
|
||||
partial class FbxExporterContext
|
||||
{
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern IntPtr AsFbxCreateContext();
|
||||
|
||||
private static bool AsFbxInitializeContext(IntPtr context, string fileName, float scaleFactor, int versionIndex, bool isAscii, bool is60Fps, out string errorMessage)
|
||||
{
|
||||
bool b;
|
||||
IntPtr pErrMsg;
|
||||
|
||||
using (var fileNameUtf8 = new Utf8StringHandle(fileName))
|
||||
{
|
||||
b = AsFbxInitializeContext(context, fileNameUtf8.DangerousGetHandle(), scaleFactor, versionIndex, isAscii, is60Fps, out pErrMsg);
|
||||
}
|
||||
|
||||
errorMessage = Utf8StringHandle.ReadUtf8StringFromPointer(pErrMsg);
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
// Do not free the pointer strErrorMessage
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
private static extern bool AsFbxInitializeContext(IntPtr context, IntPtr strFileName, float scaleFactor, int versionIndex, [MarshalAs(UnmanagedType.Bool)] bool isAscii, [MarshalAs(UnmanagedType.Bool)] bool is60Fps, out IntPtr strErrorMessage);
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern void AsFbxDisposeContext(ref IntPtr ppContext);
|
||||
|
||||
private static void AsFbxSetFramePaths(IntPtr context, string[] framePaths)
|
||||
{
|
||||
var framePathCount = framePaths.Length;
|
||||
|
||||
if (framePathCount == 0)
|
||||
{
|
||||
AsFbxSetFramePaths(context, Array.Empty<IntPtr>(), 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
var utf8Paths = new Utf8StringHandle[framePathCount];
|
||||
|
||||
try
|
||||
{
|
||||
for (var i = 0; i < framePathCount; i += 1)
|
||||
{
|
||||
utf8Paths[i] = new Utf8StringHandle(framePaths[i]);
|
||||
}
|
||||
|
||||
var pathPointers = new IntPtr[framePathCount];
|
||||
|
||||
for (var i = 0; i < framePathCount; i += 1)
|
||||
{
|
||||
pathPointers[i] = utf8Paths[i].DangerousGetHandle();
|
||||
}
|
||||
|
||||
AsFbxSetFramePaths(context, pathPointers, framePathCount);
|
||||
}
|
||||
finally
|
||||
{
|
||||
foreach (var path in utf8Paths)
|
||||
{
|
||||
path?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern void AsFbxSetFramePaths(IntPtr context, [MarshalAs(UnmanagedType.LPArray)] IntPtr[] strFramePaths, int count);
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern void AsFbxExportScene(IntPtr context);
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern IntPtr AsFbxGetSceneRootNode(IntPtr context);
|
||||
|
||||
private static IntPtr AsFbxExportSingleFrame(IntPtr context, IntPtr parentNode, string framePath, string frameName, in Vector3 localPosition, in Vector3 localRotation, in Vector3 localScale)
|
||||
{
|
||||
using (var framePathUtf8 = new Utf8StringHandle(framePath))
|
||||
{
|
||||
using (var frameNameUtf8 = new Utf8StringHandle(frameName))
|
||||
{
|
||||
return AsFbxExportSingleFrame(context, parentNode, framePathUtf8.DangerousGetHandle(), frameNameUtf8.DangerousGetHandle(), localPosition.X, localPosition.Y, localPosition.Z, localRotation.X, localRotation.Y, localRotation.Z, localScale.X, localScale.Y, localScale.Z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern IntPtr AsFbxExportSingleFrame(IntPtr context, IntPtr parentNode, IntPtr strFramePath, IntPtr strFrameName, float localPositionX, float localPositionY, float localPositionZ, float localRotationX, float localRotationY, float localRotationZ, float localScaleX, float localScaleY, float localScaleZ);
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern void AsFbxSetJointsNode_CastToBone(IntPtr context, IntPtr node, float boneSize);
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern void AsFbxSetJointsNode_BoneInPath(IntPtr context, IntPtr node, float boneSize);
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern void AsFbxSetJointsNode_Generic(IntPtr context, IntPtr node);
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern void AsFbxPrepareMaterials(IntPtr context, int materialCount, int textureCount);
|
||||
|
||||
private static IntPtr AsFbxCreateTexture(IntPtr context, string matTexName)
|
||||
{
|
||||
using (var matTexNameUtf8 = new Utf8StringHandle(matTexName))
|
||||
{
|
||||
return AsFbxCreateTexture(context, matTexNameUtf8.DangerousGetHandle());
|
||||
}
|
||||
}
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern IntPtr AsFbxCreateTexture(IntPtr context, IntPtr strMatTexName);
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern void AsFbxLinkTexture(int dest, IntPtr texture, IntPtr material, float offsetX, float offsetY, float scaleX, float scaleY);
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern IntPtr AsFbxMeshCreateClusterArray(int boneCount);
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern void AsFbxMeshDisposeClusterArray(ref IntPtr ppArray);
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern IntPtr AsFbxMeshCreateCluster(IntPtr context, IntPtr boneNode);
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern void AsFbxMeshAddCluster(IntPtr array, IntPtr cluster);
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern IntPtr AsFbxMeshCreateMesh(IntPtr context, IntPtr frameNode);
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern void AsFbxMeshInitControlPoints(IntPtr mesh, int vertexCount);
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern void AsFbxMeshCreateElementNormal(IntPtr mesh);
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern void AsFbxMeshCreateDiffuseUV(IntPtr mesh, int uv);
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern void AsFbxMeshCreateNormalMapUV(IntPtr mesh, int uv);
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern void AsFbxMeshCreateElementTangent(IntPtr mesh);
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern void AsFbxMeshCreateElementVertexColor(IntPtr mesh);
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern void AsFbxMeshCreateElementMaterial(IntPtr mesh);
|
||||
|
||||
private static IntPtr AsFbxCreateMaterial(IntPtr pContext, string matName, in Color diffuse, in Color ambient, in Color emissive, in Color specular, in Color reflection, float shininess, float transparency)
|
||||
{
|
||||
using (var matNameUtf8 = new Utf8StringHandle(matName))
|
||||
{
|
||||
return AsFbxCreateMaterial(pContext, matNameUtf8.DangerousGetHandle(), diffuse.R, diffuse.G, diffuse.B, ambient.R, ambient.G, ambient.B, emissive.R, emissive.G, emissive.B, specular.R, specular.G, specular.B, reflection.R, reflection.G, reflection.B, shininess, transparency);
|
||||
}
|
||||
}
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern IntPtr AsFbxCreateMaterial(IntPtr pContext, IntPtr pMatName,
|
||||
float diffuseR, float diffuseG, float diffuseB,
|
||||
float ambientR, float ambientG, float ambientB,
|
||||
float emissiveR, float emissiveG, float emissiveB,
|
||||
float specularR, float specularG, float specularB,
|
||||
float reflectR, float reflectG, float reflectB,
|
||||
float shininess, float transparency);
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern int AsFbxAddMaterialToFrame(IntPtr frameNode, IntPtr material);
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern void AsFbxSetFrameShadingModeToTextureShading(IntPtr frameNode);
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern void AsFbxMeshSetControlPoint(IntPtr mesh, int index, float x, float y, float z);
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern void AsFbxMeshAddPolygon(IntPtr mesh, int materialIndex, int index0, int index1, int index2);
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern void AsFbxMeshElementNormalAdd(IntPtr mesh, int elementIndex, float x, float y, float z);
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern void AsFbxMeshElementUVAdd(IntPtr mesh, int elementIndex, float u, float v);
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern void AsFbxMeshElementTangentAdd(IntPtr mesh, int elementIndex, float x, float y, float z, float w);
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern void AsFbxMeshElementVertexColorAdd(IntPtr mesh, int elementIndex, float r, float g, float b, float a);
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern void AsFbxMeshSetBoneWeight(IntPtr pClusterArray, int boneIndex, int vertexIndex, float weight);
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern IntPtr AsFbxMeshCreateSkinContext(IntPtr context, IntPtr frameNode);
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern void AsFbxMeshDisposeSkinContext(ref IntPtr ppSkinContext);
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
private static extern bool FbxClusterArray_HasItemAt(IntPtr pClusterArray, int index);
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private unsafe static extern void AsFbxMeshSkinAddCluster(IntPtr pSkinContext, IntPtr pClusterArray, int index, float* pBoneMatrix);
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern void AsFbxMeshAddDeformer(IntPtr pSkinContext, IntPtr pMesh);
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern IntPtr AsFbxAnimCreateContext([MarshalAs(UnmanagedType.Bool)] bool eulerFilter);
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern void AsFbxAnimDisposeContext(ref IntPtr ppAnimContext);
|
||||
|
||||
private static void AsFbxAnimPrepareStackAndLayer(IntPtr pContext, IntPtr pAnimContext, string takeName)
|
||||
{
|
||||
using (var takeNameUtf8 = new Utf8StringHandle(takeName))
|
||||
{
|
||||
AsFbxAnimPrepareStackAndLayer(pContext, pAnimContext, takeNameUtf8.DangerousGetHandle());
|
||||
}
|
||||
}
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern void AsFbxAnimPrepareStackAndLayer(IntPtr pContext, IntPtr pAnimContext, IntPtr strTakeName);
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern void AsFbxAnimLoadCurves(IntPtr pNode, IntPtr pAnimContext);
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern void AsFbxAnimBeginKeyModify(IntPtr pAnimContext);
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern void AsFbxAnimEndKeyModify(IntPtr pAnimContext);
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern void AsFbxAnimAddScalingKey(IntPtr pAnimContext, float time, float x, float y, float z);
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern void AsFbxAnimAddRotationKey(IntPtr pAnimContext, float time, float x, float y, float z);
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern void AsFbxAnimAddTranslationKey(IntPtr pAnimContext, float time, float x, float y, float z);
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern void AsFbxAnimApplyEulerFilter(IntPtr pAnimContext, float filterPrecision);
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern int AsFbxAnimGetCurrentBlendShapeChannelCount(IntPtr pAnimContext, IntPtr pNode);
|
||||
|
||||
private static bool AsFbxAnimIsBlendShapeChannelMatch(IntPtr pAnimContext, int channelIndex, string channelName)
|
||||
{
|
||||
using (var channelNameUtf8 = new Utf8StringHandle(channelName))
|
||||
{
|
||||
return AsFbxAnimIsBlendShapeChannelMatch(pAnimContext, channelIndex, channelNameUtf8.DangerousGetHandle());
|
||||
}
|
||||
}
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
private static extern bool AsFbxAnimIsBlendShapeChannelMatch(IntPtr pAnimContext, int channelIndex, IntPtr strChannelName);
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern void AsFbxAnimBeginBlendShapeAnimCurve(IntPtr pAnimContext, int channelIndex);
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern void AsFbxAnimEndBlendShapeAnimCurve(IntPtr pAnimContext);
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern void AsFbxAnimAddBlendShapeKeyframe(IntPtr pAnimContext, float time, float value);
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern IntPtr AsFbxMorphCreateContext();
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern void AsFbxMorphInitializeContext(IntPtr pContext, IntPtr pMorphContext, IntPtr pNode);
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern void AsFbxMorphDisposeContext(ref IntPtr ppMorphContext);
|
||||
|
||||
private static void AsFbxMorphAddBlendShapeChannel(IntPtr pContext, IntPtr pMorphContext, string channelName)
|
||||
{
|
||||
using (var channelNameUtf8 = new Utf8StringHandle(channelName))
|
||||
{
|
||||
AsFbxMorphAddBlendShapeChannel(pContext, pMorphContext, channelNameUtf8.DangerousGetHandle());
|
||||
}
|
||||
}
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern void AsFbxMorphAddBlendShapeChannel(IntPtr pContext, IntPtr pMorphContext, IntPtr strChannelName);
|
||||
|
||||
private static void AsFbxMorphAddBlendShapeChannelShape(IntPtr pContext, IntPtr pMorphContext, float weight, string shapeName)
|
||||
{
|
||||
using (var shapeNameUtf8 = new Utf8StringHandle(shapeName))
|
||||
{
|
||||
AsFbxMorphAddBlendShapeChannelShape(pContext, pMorphContext, weight, shapeNameUtf8.DangerousGetHandle());
|
||||
}
|
||||
}
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern void AsFbxMorphAddBlendShapeChannelShape(IntPtr pContext, IntPtr pMorphContext, float weight, IntPtr strShapeName);
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern void AsFbxMorphCopyBlendShapeControlPoints(IntPtr pMorphContext);
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern void AsFbxMorphSetBlendShapeVertex(IntPtr pMorphContext, uint index, float x, float y, float z);
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern void AsFbxMorphCopyBlendShapeControlPointsNormal(IntPtr pMorphContext);
|
||||
|
||||
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern void AsFbxMorphSetBlendShapeVertexNormal(IntPtr pMorphContext, uint index, float x, float y, float z);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,649 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace AssetStudio.FbxInterop
|
||||
{
|
||||
internal sealed partial class FbxExporterContext : IDisposable
|
||||
{
|
||||
|
||||
private IntPtr _pContext;
|
||||
private readonly Dictionary<ImportedFrame, IntPtr> _frameToNode;
|
||||
private readonly List<KeyValuePair<string, IntPtr>> _createdMaterials;
|
||||
private readonly Dictionary<string, IntPtr> _createdTextures;
|
||||
|
||||
public FbxExporterContext()
|
||||
{
|
||||
_pContext = AsFbxCreateContext();
|
||||
_frameToNode = new Dictionary<ImportedFrame, IntPtr>();
|
||||
_createdMaterials = new List<KeyValuePair<string, IntPtr>>();
|
||||
_createdTextures = new Dictionary<string, IntPtr>();
|
||||
}
|
||||
|
||||
~FbxExporterContext()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (IsDisposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
public bool IsDisposed { get; private set; }
|
||||
|
||||
private void Dispose(bool disposing)
|
||||
{
|
||||
IsDisposed = true;
|
||||
|
||||
_frameToNode.Clear();
|
||||
_createdMaterials.Clear();
|
||||
_createdTextures.Clear();
|
||||
|
||||
AsFbxDisposeContext(ref _pContext);
|
||||
}
|
||||
|
||||
private void EnsureNotDisposed()
|
||||
{
|
||||
if (IsDisposed)
|
||||
{
|
||||
throw new ObjectDisposedException(nameof(FbxExporterContext));
|
||||
}
|
||||
}
|
||||
|
||||
internal void Initialize(string fileName, float scaleFactor, int versionIndex, bool isAscii, bool is60Fps)
|
||||
{
|
||||
EnsureNotDisposed();
|
||||
|
||||
var b = AsFbxInitializeContext(_pContext, fileName, scaleFactor, versionIndex, isAscii, is60Fps, out var errorMessage);
|
||||
|
||||
if (!b)
|
||||
{
|
||||
var fullMessage = $"Failed to initialize FbxExporter: {errorMessage}";
|
||||
throw new ApplicationException(fullMessage);
|
||||
}
|
||||
}
|
||||
|
||||
internal void SetFramePaths(HashSet<string> framePaths)
|
||||
{
|
||||
EnsureNotDisposed();
|
||||
|
||||
if (framePaths == null || framePaths.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var framePathList = new List<string>(framePaths);
|
||||
var framePathArray = framePathList.ToArray();
|
||||
|
||||
AsFbxSetFramePaths(_pContext, framePathArray);
|
||||
}
|
||||
|
||||
internal void ExportScene()
|
||||
{
|
||||
EnsureNotDisposed();
|
||||
|
||||
AsFbxExportScene(_pContext);
|
||||
}
|
||||
|
||||
internal void ExportFrame(List<ImportedMesh> meshList, List<ImportedFrame> meshFrames, ImportedFrame rootFrame)
|
||||
{
|
||||
var rootNode = AsFbxGetSceneRootNode(_pContext);
|
||||
|
||||
Debug.Assert(rootNode != IntPtr.Zero);
|
||||
|
||||
var nodeStack = new Stack<IntPtr>();
|
||||
var frameStack = new Stack<ImportedFrame>();
|
||||
|
||||
nodeStack.Push(rootNode);
|
||||
frameStack.Push(rootFrame);
|
||||
|
||||
while (nodeStack.Count > 0)
|
||||
{
|
||||
var parentNode = nodeStack.Pop();
|
||||
var frame = frameStack.Pop();
|
||||
|
||||
var childNode = AsFbxExportSingleFrame(_pContext, parentNode, frame.Path, frame.Name, frame.LocalPosition, frame.LocalRotation, frame.LocalScale);
|
||||
|
||||
if (meshList != null && ImportedHelpers.FindMesh(frame.Path, meshList) != null)
|
||||
{
|
||||
meshFrames.Add(frame);
|
||||
}
|
||||
|
||||
_frameToNode.Add(frame, childNode);
|
||||
|
||||
for (var i = frame.Count - 1; i >= 0; i -= 1)
|
||||
{
|
||||
nodeStack.Push(childNode);
|
||||
frameStack.Push(frame[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void SetJointsNode(ImportedFrame rootFrame, HashSet<string> bonePaths, bool castToBone, float boneSize)
|
||||
{
|
||||
var frameStack = new Stack<ImportedFrame>();
|
||||
|
||||
frameStack.Push(rootFrame);
|
||||
|
||||
while (frameStack.Count > 0)
|
||||
{
|
||||
var frame = frameStack.Pop();
|
||||
|
||||
if (_frameToNode.TryGetValue(frame, out var node))
|
||||
{
|
||||
Debug.Assert(node != IntPtr.Zero);
|
||||
|
||||
if (castToBone)
|
||||
{
|
||||
AsFbxSetJointsNode_CastToBone(_pContext, node, boneSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Assert(bonePaths != null);
|
||||
|
||||
if (bonePaths.Contains(frame.Path))
|
||||
{
|
||||
AsFbxSetJointsNode_BoneInPath(_pContext, node, boneSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
AsFbxSetJointsNode_Generic(_pContext, node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = frame.Count - 1; i >= 0; i -= 1)
|
||||
{
|
||||
frameStack.Push(frame[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void PrepareMaterials(int materialCount, int textureCount)
|
||||
{
|
||||
AsFbxPrepareMaterials(_pContext, materialCount, textureCount);
|
||||
}
|
||||
|
||||
internal void ExportMeshFromFrame(ImportedFrame rootFrame, ImportedFrame meshFrame, List<ImportedMesh> meshList, List<ImportedMaterial> materialList, List<ImportedTexture> textureList, bool exportSkins)
|
||||
{
|
||||
var meshNode = _frameToNode[meshFrame];
|
||||
var mesh = ImportedHelpers.FindMesh(meshFrame.Path, meshList);
|
||||
|
||||
ExportMesh(rootFrame, materialList, textureList, meshNode, mesh, exportSkins);
|
||||
}
|
||||
|
||||
private IntPtr ExportTexture(ImportedTexture texture)
|
||||
{
|
||||
if (texture == null)
|
||||
{
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
|
||||
if (_createdTextures.ContainsKey(texture.Name))
|
||||
{
|
||||
return _createdTextures[texture.Name];
|
||||
}
|
||||
|
||||
var pTex = AsFbxCreateTexture(_pContext, texture.Name);
|
||||
|
||||
_createdTextures.Add(texture.Name, pTex);
|
||||
|
||||
var file = new FileInfo(texture.Name);
|
||||
|
||||
using (var writer = new BinaryWriter(file.Create()))
|
||||
{
|
||||
writer.Write(texture.Data);
|
||||
}
|
||||
|
||||
return pTex;
|
||||
}
|
||||
|
||||
private void ExportMesh(ImportedFrame rootFrame, List<ImportedMaterial> materialList, List<ImportedTexture> textureList, IntPtr frameNode, ImportedMesh importedMesh, bool exportSkins)
|
||||
{
|
||||
var boneList = importedMesh.BoneList;
|
||||
var totalBoneCount = 0;
|
||||
var hasBones = false;
|
||||
if (exportSkins && boneList?.Count > 0)
|
||||
{
|
||||
totalBoneCount = boneList.Count;
|
||||
hasBones = true;
|
||||
}
|
||||
|
||||
var pClusterArray = IntPtr.Zero;
|
||||
|
||||
try
|
||||
{
|
||||
if (hasBones)
|
||||
{
|
||||
pClusterArray = AsFbxMeshCreateClusterArray(totalBoneCount);
|
||||
|
||||
foreach (var bone in boneList)
|
||||
{
|
||||
if (bone.Path != null)
|
||||
{
|
||||
var frame = rootFrame.FindFrameByPath(bone.Path);
|
||||
var boneNode = _frameToNode[frame];
|
||||
|
||||
var cluster = AsFbxMeshCreateCluster(_pContext, boneNode);
|
||||
|
||||
AsFbxMeshAddCluster(pClusterArray, cluster);
|
||||
}
|
||||
else
|
||||
{
|
||||
AsFbxMeshAddCluster(pClusterArray, IntPtr.Zero);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var mesh = AsFbxMeshCreateMesh(_pContext, frameNode);
|
||||
|
||||
var totalVertexCount = 0;
|
||||
|
||||
foreach (var m in importedMesh.SubmeshList)
|
||||
{
|
||||
totalVertexCount += m.VertexList.Count;
|
||||
}
|
||||
|
||||
AsFbxMeshInitControlPoints(mesh, totalVertexCount);
|
||||
|
||||
if (importedMesh.hasNormal)
|
||||
{
|
||||
AsFbxMeshCreateElementNormal(mesh);
|
||||
}
|
||||
|
||||
if (importedMesh.hasUV[0])
|
||||
{
|
||||
AsFbxMeshCreateDiffuseUV(mesh, 0);
|
||||
}
|
||||
|
||||
if (importedMesh.hasUV[1])
|
||||
{
|
||||
AsFbxMeshCreateNormalMapUV(mesh, 1);
|
||||
}
|
||||
|
||||
if (importedMesh.hasTangent)
|
||||
{
|
||||
AsFbxMeshCreateElementTangent(mesh);
|
||||
}
|
||||
|
||||
if (importedMesh.hasColor)
|
||||
{
|
||||
AsFbxMeshCreateElementVertexColor(mesh);
|
||||
}
|
||||
|
||||
AsFbxMeshCreateElementMaterial(mesh);
|
||||
|
||||
var firstVertex = 0;
|
||||
|
||||
foreach (var meshObj in importedMesh.SubmeshList)
|
||||
{
|
||||
var materialIndex = 0;
|
||||
var mat = ImportedHelpers.FindMaterial(meshObj.Material, materialList);
|
||||
|
||||
if (mat != null)
|
||||
{
|
||||
var foundMat = _createdMaterials.FindIndex(kv => kv.Key == mat.Name);
|
||||
IntPtr pMat;
|
||||
|
||||
if (foundMat >= 0)
|
||||
{
|
||||
pMat = _createdMaterials[foundMat].Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
var diffuse = mat.Diffuse;
|
||||
var ambient = mat.Ambient;
|
||||
var emissive = mat.Emissive;
|
||||
var specular = mat.Specular;
|
||||
var reflection = mat.Reflection;
|
||||
|
||||
pMat = AsFbxCreateMaterial(_pContext, mat.Name, in diffuse, in ambient, in emissive, in specular, in reflection, mat.Shininess, mat.Transparency);
|
||||
|
||||
_createdMaterials.Add(new KeyValuePair<string, IntPtr>(mat.Name, pMat));
|
||||
}
|
||||
|
||||
materialIndex = AsFbxAddMaterialToFrame(frameNode, pMat);
|
||||
|
||||
var hasTexture = false;
|
||||
|
||||
foreach (var texture in mat.Textures)
|
||||
{
|
||||
var tex = ImportedHelpers.FindTexture(texture.Name, textureList);
|
||||
var pTexture = ExportTexture(tex);
|
||||
|
||||
if (pTexture != IntPtr.Zero)
|
||||
{
|
||||
switch (texture.Dest)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
{
|
||||
AsFbxLinkTexture(texture.Dest, pTexture, pMat, texture.Offset.X, texture.Offset.Y, texture.Scale.X, texture.Scale.Y);
|
||||
hasTexture = true;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hasTexture)
|
||||
{
|
||||
AsFbxSetFrameShadingModeToTextureShading(frameNode);
|
||||
}
|
||||
}
|
||||
|
||||
var vertexList = meshObj.VertexList;
|
||||
|
||||
var vertexCount = vertexList.Count;
|
||||
|
||||
for (var j = 0; j < vertexCount; j += 1)
|
||||
{
|
||||
var importedVertex = vertexList[j];
|
||||
|
||||
var vertex = importedVertex.Vertex;
|
||||
AsFbxMeshSetControlPoint(mesh, j + firstVertex, vertex.X, vertex.Y, vertex.Z);
|
||||
|
||||
if (importedMesh.hasNormal)
|
||||
{
|
||||
var normal = importedVertex.Normal;
|
||||
AsFbxMeshElementNormalAdd(mesh, 0, normal.X, normal.Y, normal.Z);
|
||||
}
|
||||
|
||||
for (var uvIndex = 0; uvIndex < 2; uvIndex += 1)
|
||||
{
|
||||
if (importedMesh.hasUV[uvIndex])
|
||||
{
|
||||
var uv = importedVertex.UV[uvIndex];
|
||||
AsFbxMeshElementUVAdd(mesh, uvIndex, uv[0], uv[1]);
|
||||
}
|
||||
}
|
||||
|
||||
if (importedMesh.hasTangent)
|
||||
{
|
||||
var tangent = importedVertex.Tangent;
|
||||
AsFbxMeshElementTangentAdd(mesh, 0, tangent.X, tangent.Y, tangent.Z, tangent.W);
|
||||
}
|
||||
|
||||
if (importedMesh.hasColor)
|
||||
{
|
||||
var color = importedVertex.Color;
|
||||
AsFbxMeshElementVertexColorAdd(mesh, 0, color.R, color.G, color.B, color.A);
|
||||
}
|
||||
|
||||
if (hasBones && importedVertex.BoneIndices != null)
|
||||
{
|
||||
var boneIndices = importedVertex.BoneIndices;
|
||||
var boneWeights = importedVertex.Weights;
|
||||
|
||||
for (var k = 0; k < 4; k += 1)
|
||||
{
|
||||
if (boneIndices[k] < totalBoneCount && boneWeights[k] > 0)
|
||||
{
|
||||
AsFbxMeshSetBoneWeight(pClusterArray, boneIndices[k], j + firstVertex, boneWeights[k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var face in meshObj.FaceList)
|
||||
{
|
||||
var index0 = face.VertexIndices[0] + firstVertex;
|
||||
var index1 = face.VertexIndices[1] + firstVertex;
|
||||
var index2 = face.VertexIndices[2] + firstVertex;
|
||||
|
||||
AsFbxMeshAddPolygon(mesh, materialIndex, index0, index1, index2);
|
||||
}
|
||||
|
||||
firstVertex += vertexCount;
|
||||
}
|
||||
|
||||
if (hasBones)
|
||||
{
|
||||
IntPtr pSkinContext = IntPtr.Zero;
|
||||
|
||||
try
|
||||
{
|
||||
pSkinContext = AsFbxMeshCreateSkinContext(_pContext, frameNode);
|
||||
|
||||
unsafe
|
||||
{
|
||||
var boneMatrix = stackalloc float[16];
|
||||
|
||||
for (var j = 0; j < totalBoneCount; j += 1)
|
||||
{
|
||||
if (!FbxClusterArray_HasItemAt(pClusterArray, j))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var m = boneList[j].Matrix;
|
||||
|
||||
CopyMatrix4x4(in m, boneMatrix);
|
||||
|
||||
AsFbxMeshSkinAddCluster(pSkinContext, pClusterArray, j, boneMatrix);
|
||||
}
|
||||
}
|
||||
|
||||
AsFbxMeshAddDeformer(pSkinContext, mesh);
|
||||
}
|
||||
finally
|
||||
{
|
||||
AsFbxMeshDisposeSkinContext(ref pSkinContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
AsFbxMeshDisposeClusterArray(ref pClusterArray);
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static unsafe void CopyMatrix4x4(in Matrix4x4 matrix, float* buffer)
|
||||
{
|
||||
for (var m = 0; m < 4; m += 1)
|
||||
{
|
||||
for (var n = 0; n < 4; n += 1)
|
||||
{
|
||||
var index = IndexFrom4x4(m, n);
|
||||
buffer[index] = matrix[m, n];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static int IndexFrom4x4(int m, int n)
|
||||
{
|
||||
return 4 * m + n;
|
||||
}
|
||||
|
||||
internal void ExportAnimations(ImportedFrame rootFrame, List<ImportedKeyframedAnimation> animationList, bool eulerFilter, float filterPrecision)
|
||||
{
|
||||
if (animationList == null || animationList.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var pAnimContext = IntPtr.Zero;
|
||||
|
||||
try
|
||||
{
|
||||
pAnimContext = AsFbxAnimCreateContext(eulerFilter);
|
||||
|
||||
for (int i = 0; i < animationList.Count; i++)
|
||||
{
|
||||
var importedAnimation = animationList[i];
|
||||
string takeName;
|
||||
|
||||
if (importedAnimation.Name != null)
|
||||
{
|
||||
takeName = importedAnimation.Name;
|
||||
}
|
||||
else
|
||||
{
|
||||
takeName = $"Take{i.ToString()}";
|
||||
}
|
||||
|
||||
AsFbxAnimPrepareStackAndLayer(_pContext, pAnimContext, takeName);
|
||||
|
||||
ExportKeyframedAnimation(rootFrame, importedAnimation, pAnimContext, filterPrecision);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
AsFbxAnimDisposeContext(ref pAnimContext);
|
||||
}
|
||||
}
|
||||
|
||||
private void ExportKeyframedAnimation(ImportedFrame rootFrame, ImportedKeyframedAnimation parser, IntPtr pAnimContext, float filterPrecision)
|
||||
{
|
||||
foreach (var track in parser.TrackList)
|
||||
{
|
||||
if (track.Path == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var frame = rootFrame.FindFrameByPath(track.Path);
|
||||
|
||||
if (frame == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var pNode = _frameToNode[frame];
|
||||
|
||||
AsFbxAnimLoadCurves(pNode, pAnimContext);
|
||||
|
||||
AsFbxAnimBeginKeyModify(pAnimContext);
|
||||
|
||||
foreach (var scaling in track.Scalings)
|
||||
{
|
||||
var value = scaling.value;
|
||||
AsFbxAnimAddScalingKey(pAnimContext, scaling.time, value.X, value.Y, value.Z);
|
||||
}
|
||||
|
||||
foreach (var rotation in track.Rotations)
|
||||
{
|
||||
var value = rotation.value;
|
||||
AsFbxAnimAddRotationKey(pAnimContext, rotation.time, value.X, value.Y, value.Z);
|
||||
}
|
||||
|
||||
foreach (var translation in track.Translations)
|
||||
{
|
||||
var value = translation.value;
|
||||
AsFbxAnimAddTranslationKey(pAnimContext, translation.time, value.X, value.Y, value.Z);
|
||||
}
|
||||
|
||||
AsFbxAnimEndKeyModify(pAnimContext);
|
||||
|
||||
AsFbxAnimApplyEulerFilter(pAnimContext, filterPrecision);
|
||||
|
||||
var blendShape = track.BlendShape;
|
||||
|
||||
if (blendShape != null)
|
||||
{
|
||||
var channelCount = AsFbxAnimGetCurrentBlendShapeChannelCount(pAnimContext, pNode);
|
||||
|
||||
if (channelCount > 0)
|
||||
{
|
||||
for (var channelIndex = 0; channelIndex < channelCount; channelIndex += 1)
|
||||
{
|
||||
if (!AsFbxAnimIsBlendShapeChannelMatch(pAnimContext, channelIndex, blendShape.ChannelName))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
AsFbxAnimBeginBlendShapeAnimCurve(pAnimContext, channelIndex);
|
||||
|
||||
foreach (var keyframe in blendShape.Keyframes)
|
||||
{
|
||||
AsFbxAnimAddBlendShapeKeyframe(pAnimContext, keyframe.time, keyframe.value);
|
||||
}
|
||||
|
||||
AsFbxAnimEndBlendShapeAnimCurve(pAnimContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void ExportMorphs(ImportedFrame rootFrame, List<ImportedMorph> morphList)
|
||||
{
|
||||
if (morphList == null || morphList.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var morph in morphList)
|
||||
{
|
||||
var frame = rootFrame.FindFrameByPath(morph.Path);
|
||||
|
||||
if (frame == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var pNode = _frameToNode[frame];
|
||||
|
||||
var pMorphContext = IntPtr.Zero;
|
||||
|
||||
try
|
||||
{
|
||||
pMorphContext = AsFbxMorphCreateContext();
|
||||
|
||||
AsFbxMorphInitializeContext(_pContext, pMorphContext, pNode);
|
||||
|
||||
foreach (var channel in morph.Channels)
|
||||
{
|
||||
AsFbxMorphAddBlendShapeChannel(_pContext, pMorphContext, channel.Name);
|
||||
|
||||
for (var i = 0; i < channel.KeyframeList.Count; i++)
|
||||
{
|
||||
var keyframe = channel.KeyframeList[i];
|
||||
|
||||
AsFbxMorphAddBlendShapeChannelShape(_pContext, pMorphContext, keyframe.Weight, i == 0 ? channel.Name : $"{channel.Name}_{i + 1}");
|
||||
|
||||
AsFbxMorphCopyBlendShapeControlPoints(pMorphContext);
|
||||
|
||||
foreach (var vertex in keyframe.VertexList)
|
||||
{
|
||||
var v = vertex.Vertex.Vertex;
|
||||
AsFbxMorphSetBlendShapeVertex(pMorphContext, vertex.Index, v.X, v.Y, v.Z);
|
||||
}
|
||||
|
||||
if (keyframe.hasNormals)
|
||||
{
|
||||
AsFbxMorphCopyBlendShapeControlPointsNormal(pMorphContext);
|
||||
|
||||
foreach (var vertex in keyframe.VertexList)
|
||||
{
|
||||
var v = vertex.Vertex.Normal;
|
||||
AsFbxMorphSetBlendShapeVertexNormal(pMorphContext, vertex.Index, v.X, v.Y, v.Z);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
AsFbxMorphDisposeContext(ref pMorphContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
[assembly: AssemblyTitle("AssetStudioFBXWrapper")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("AssetStudioFBXWrapper")]
|
||||
[assembly: AssemblyCopyright("Copyright © Perfare 2018-2020; Copyright © hozuki 2020")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
[assembly: Guid("bd76e63f-1517-47fa-8233-33e853a3acee")]
|
||||
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
@@ -1,83 +1,52 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
|
||||
<ProductVersion>8.0.30703</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{24551E2D-E9B6-4CD6-8F2A-D9F4A13E7853}</ProjectGuid>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}</ProjectGuid>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>AssetStudioGUI</RootNamespace>
|
||||
<AssemblyName>AssetStudioGUI</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<TargetFrameworkProfile>
|
||||
</TargetFrameworkProfile>
|
||||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<IsWebBootstrapper>false</IsWebBootstrapper>
|
||||
<PublishUrl>publish\</PublishUrl>
|
||||
<Install>true</Install>
|
||||
<InstallFrom>Disk</InstallFrom>
|
||||
<UpdateEnabled>false</UpdateEnabled>
|
||||
<UpdateMode>Foreground</UpdateMode>
|
||||
<UpdateInterval>7</UpdateInterval>
|
||||
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
|
||||
<UpdatePeriodically>false</UpdatePeriodically>
|
||||
<UpdateRequired>false</UpdateRequired>
|
||||
<MapFileExtensions>true</MapFileExtensions>
|
||||
<ApplicationRevision>0</ApplicationRevision>
|
||||
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
|
||||
<UseApplicationTrust>false</UseApplicationTrust>
|
||||
<BootstrapperEnabled>true</BootstrapperEnabled>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<Deterministic>true</Deterministic>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ApplicationIcon>Resources\as.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\x64\Debug\</OutputPath>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<LangVersion>7.3</LangVersion>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
||||
<OutputPath>bin\x64\Release\</OutputPath>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\x86\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
|
||||
<OutputPath>bin\x86\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<LangVersion>7.3</LangVersion>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="OpenTK">
|
||||
<HintPath>Libraries\OpenTK.dll</HintPath>
|
||||
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="OpenTK.GLControl">
|
||||
<HintPath>Libraries\OpenTK.GLControl.dll</HintPath>
|
||||
<Reference Include="OpenTK, Version=3.1.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\OpenTK.3.1.0\lib\net20\OpenTK.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="OpenTK.GLControl, Version=3.1.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\OpenTK.GLControl.3.1.0\lib\net20\OpenTK.GLControl.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
@@ -85,37 +54,42 @@
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Deployment" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="GUILogger.cs" />
|
||||
<Compile Include="GUIProgress.cs" />
|
||||
<Compile Include="Components\GameObjectTreeNode.cs" />
|
||||
<Compile Include="Components\OpenFolderDialog.cs" />
|
||||
<Compile Include="Components\AssetItem.cs" />
|
||||
<Compile Include="Exporter.cs" />
|
||||
<Compile Include="Studio.cs" />
|
||||
<Compile Include="ExportOptions.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="ExportOptions.Designer.cs">
|
||||
<DependentUpon>ExportOptions.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Components\GOHierarchy.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="AssetStudioGUIForm.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="AssetStudioGUIForm.Designer.cs">
|
||||
<Compile Include="AssetStudioGUIForm.designer.cs">
|
||||
<DependentUpon>AssetStudioGUIForm.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Components\TypeTreeItem.cs" />
|
||||
<Compile Include="Components\AssetItem.cs" />
|
||||
<Compile Include="Components\GameObjectTreeNode.cs" />
|
||||
<Compile Include="Components\GOHierarchy.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Components\OpenFolderDialog.cs" />
|
||||
<Compile Include="Components\TreeViewExtensions.cs" />
|
||||
<Compile Include="Components\TypeTreeItem.cs" />
|
||||
<Compile Include="Exporter.cs" />
|
||||
<Compile Include="ExportOptions.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="ExportOptions.designer.cs">
|
||||
<DependentUpon>ExportOptions.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="GUILogger.cs" />
|
||||
<Compile Include="GUIProgress.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Studio.cs" />
|
||||
<EmbeddedResource Include="AssetStudioGUIForm.resx">
|
||||
<DependentUpon>AssetStudioGUIForm.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="ExportOptions.resx">
|
||||
<DependentUpon>ExportOptions.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
@@ -129,11 +103,8 @@
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
<DesignTime>True</DesignTime>
|
||||
</Compile>
|
||||
<EmbeddedResource Include="AssetStudioGUIForm.resx">
|
||||
<DependentUpon>AssetStudioGUIForm.cs</DependentUpon>
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
<None Include="app.config" />
|
||||
<None Include="OpenTK.dll.config" />
|
||||
<None Include="packages.config" />
|
||||
<None Include="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||
@@ -145,21 +116,7 @@
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<BootstrapperPackage Include=".NETFramework,Version=v4.0,Profile=Client">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>Microsoft .NET Framework 4 Client Profile %28x86 and x64%29</ProductName>
|
||||
<Install>true</Install>
|
||||
</BootstrapperPackage>
|
||||
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>.NET Framework 3.5 SP1</ProductName>
|
||||
<Install>false</Install>
|
||||
</BootstrapperPackage>
|
||||
<BootstrapperPackage Include="Microsoft.Windows.Installer.4.5">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>Windows Installer 4.5</ProductName>
|
||||
<Install>true</Install>
|
||||
</BootstrapperPackage>
|
||||
<None Include="App.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Resources\preview.png" />
|
||||
@@ -167,26 +124,31 @@
|
||||
<ItemGroup>
|
||||
<None Include="Resources\as.ico" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ContentWithTargetPath Include="Libraries\x86\fmod.dll">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
<TargetPath>x86\fmod.dll</TargetPath>
|
||||
</ContentWithTargetPath>
|
||||
<ContentWithTargetPath Include="Libraries\x64\fmod.dll">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
<TargetPath>x64\fmod.dll</TargetPath>
|
||||
</ContentWithTargetPath>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\AssetStudioUtility\AssetStudioUtility.csproj">
|
||||
<Project>{9131c403-7fe8-444d-9af5-5fe5df76ff24}</Project>
|
||||
<Project>{80aec261-21ee-4e4f-a93b-7a744dc84888}</Project>
|
||||
<Name>AssetStudioUtility</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\AssetStudio\AssetStudio.csproj">
|
||||
<Project>{af56b63c-1764-41b7-9e60-8d485422ac3b}</Project>
|
||||
<Project>{7662f8c2-7bfd-442e-a948-a43b4f7eb06e}</Project>
|
||||
<Name>AssetStudio</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent>xcopy /y "$(ProjectDir)Libraries" "$(TargetDir)"
|
||||
xcopy /y "$(ProjectDir)Libraries\$(PlatformName)" "$(TargetDir)"</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
<Copy SourceFiles="$(SolutionDir)AssetStudioFBXNative\bin\Win32\$(Configuration)\AssetStudioFBXNative.dll" DestinationFolder="$(TargetDir)x86" ContinueOnError="true" />
|
||||
<Copy SourceFiles="$(SolutionDir)AssetStudioFBXNative\bin\x64\$(Configuration)\AssetStudioFBXNative.dll" DestinationFolder="$(TargetDir)x64" ContinueOnError="true" />
|
||||
<Copy SourceFiles="$(SolutionDir)Texture2DDecoderNative\bin\Win32\$(Configuration)\Texture2DDecoderNative.dll" DestinationFolder="$(TargetDir)x86" ContinueOnError="true" />
|
||||
<Copy SourceFiles="$(SolutionDir)Texture2DDecoderNative\bin\x64\$(Configuration)\Texture2DDecoderNative.dll" DestinationFolder="$(TargetDir)x64" ContinueOnError="true" />
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
+381
-242
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -147,9 +147,6 @@ The quick brown fox jumps over the lazy dog. 1234567890</value>
|
||||
<metadata name="openFileDialog1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>636, 17</value>
|
||||
</metadata>
|
||||
<metadata name="saveFileDialog1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>784, 17</value>
|
||||
</metadata>
|
||||
<metadata name="contextMenuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>147, 17</value>
|
||||
</metadata>
|
||||
|
||||
@@ -7,11 +7,11 @@ namespace AssetStudioGUI
|
||||
{
|
||||
public Object Asset;
|
||||
public SerializedFile SourceFile;
|
||||
public string Container = string.Empty;
|
||||
public string TypeString;
|
||||
public long m_PathID;
|
||||
public long FullSize;
|
||||
public ClassIDType Type;
|
||||
public string TypeString;
|
||||
|
||||
public string Extension;
|
||||
public string InfoText;
|
||||
public string UniqueID;
|
||||
public GameObjectTreeNode TreeNode;
|
||||
@@ -20,9 +20,21 @@ namespace AssetStudioGUI
|
||||
{
|
||||
Asset = asset;
|
||||
SourceFile = asset.assetsFile;
|
||||
FullSize = asset.byteSize;
|
||||
Type = asset.type;
|
||||
TypeString = Type.ToString();
|
||||
m_PathID = asset.m_PathID;
|
||||
FullSize = asset.byteSize;
|
||||
}
|
||||
|
||||
public void SetSubItems()
|
||||
{
|
||||
SubItems.AddRange(new[]
|
||||
{
|
||||
Container, //Container
|
||||
TypeString, //Type
|
||||
m_PathID.ToString(), //PathID
|
||||
FullSize.ToString(), //Size
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Generated
+160
-71
@@ -31,27 +31,33 @@
|
||||
this.OKbutton = new System.Windows.Forms.Button();
|
||||
this.Cancel = new System.Windows.Forms.Button();
|
||||
this.groupBox1 = new System.Windows.Forms.GroupBox();
|
||||
this.openAfterExport = new System.Windows.Forms.CheckBox();
|
||||
this.restoreExtensionName = new System.Windows.Forms.CheckBox();
|
||||
this.assetGroupOptions = new System.Windows.Forms.ComboBox();
|
||||
this.label6 = new System.Windows.Forms.Label();
|
||||
this.convertAudio = new System.Windows.Forms.CheckBox();
|
||||
this.panel1 = new System.Windows.Forms.Panel();
|
||||
this.totga = new System.Windows.Forms.RadioButton();
|
||||
this.tojpg = new System.Windows.Forms.RadioButton();
|
||||
this.topng = new System.Windows.Forms.RadioButton();
|
||||
this.tobmp = new System.Windows.Forms.RadioButton();
|
||||
this.converttexture = new System.Windows.Forms.CheckBox();
|
||||
this.groupBox2 = new System.Windows.Forms.GroupBox();
|
||||
this.exportBlendShape = new System.Windows.Forms.CheckBox();
|
||||
this.exportAnimations = new System.Windows.Forms.CheckBox();
|
||||
this.scaleFactor = new System.Windows.Forms.NumericUpDown();
|
||||
this.label5 = new System.Windows.Forms.Label();
|
||||
this.fbxFormat = new System.Windows.Forms.ComboBox();
|
||||
this.label4 = new System.Windows.Forms.Label();
|
||||
this.fbxVersion = new System.Windows.Forms.ComboBox();
|
||||
this.label3 = new System.Windows.Forms.Label();
|
||||
this.flatInbetween = new System.Windows.Forms.CheckBox();
|
||||
this.boneSize = new System.Windows.Forms.NumericUpDown();
|
||||
this.label2 = new System.Windows.Forms.Label();
|
||||
this.skins = new System.Windows.Forms.CheckBox();
|
||||
this.exportSkins = new System.Windows.Forms.CheckBox();
|
||||
this.label1 = new System.Windows.Forms.Label();
|
||||
this.filterPrecision = new System.Windows.Forms.NumericUpDown();
|
||||
this.allBones = new System.Windows.Forms.CheckBox();
|
||||
this.allFrames = new System.Windows.Forms.CheckBox();
|
||||
this.castToBone = new System.Windows.Forms.CheckBox();
|
||||
this.exportAllNodes = new System.Windows.Forms.CheckBox();
|
||||
this.eulerFilter = new System.Windows.Forms.CheckBox();
|
||||
this.groupBox1.SuspendLayout();
|
||||
this.panel1.SuspendLayout();
|
||||
@@ -63,18 +69,18 @@
|
||||
//
|
||||
// OKbutton
|
||||
//
|
||||
this.OKbutton.Location = new System.Drawing.Point(321, 267);
|
||||
this.OKbutton.Location = new System.Drawing.Point(308, 320);
|
||||
this.OKbutton.Name = "OKbutton";
|
||||
this.OKbutton.Size = new System.Drawing.Size(75, 21);
|
||||
this.OKbutton.TabIndex = 6;
|
||||
this.OKbutton.Text = "OK";
|
||||
this.OKbutton.UseVisualStyleBackColor = true;
|
||||
this.OKbutton.Click += new System.EventHandler(this.fbxOKbutton_Click);
|
||||
this.OKbutton.Click += new System.EventHandler(this.OKbutton_Click);
|
||||
//
|
||||
// Cancel
|
||||
//
|
||||
this.Cancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
|
||||
this.Cancel.Location = new System.Drawing.Point(402, 267);
|
||||
this.Cancel.Location = new System.Drawing.Point(389, 320);
|
||||
this.Cancel.Name = "Cancel";
|
||||
this.Cancel.Size = new System.Drawing.Size(75, 21);
|
||||
this.Cancel.TabIndex = 7;
|
||||
@@ -85,22 +91,73 @@
|
||||
// groupBox1
|
||||
//
|
||||
this.groupBox1.AutoSize = true;
|
||||
this.groupBox1.Controls.Add(this.openAfterExport);
|
||||
this.groupBox1.Controls.Add(this.restoreExtensionName);
|
||||
this.groupBox1.Controls.Add(this.assetGroupOptions);
|
||||
this.groupBox1.Controls.Add(this.label6);
|
||||
this.groupBox1.Controls.Add(this.convertAudio);
|
||||
this.groupBox1.Controls.Add(this.panel1);
|
||||
this.groupBox1.Controls.Add(this.converttexture);
|
||||
this.groupBox1.Location = new System.Drawing.Point(232, 12);
|
||||
this.groupBox1.Location = new System.Drawing.Point(12, 12);
|
||||
this.groupBox1.Name = "groupBox1";
|
||||
this.groupBox1.Size = new System.Drawing.Size(245, 114);
|
||||
this.groupBox1.Size = new System.Drawing.Size(232, 302);
|
||||
this.groupBox1.TabIndex = 9;
|
||||
this.groupBox1.TabStop = false;
|
||||
this.groupBox1.Text = "Convert";
|
||||
this.groupBox1.Text = "Export";
|
||||
//
|
||||
// openAfterExport
|
||||
//
|
||||
this.openAfterExport.AutoSize = true;
|
||||
this.openAfterExport.Checked = true;
|
||||
this.openAfterExport.CheckState = System.Windows.Forms.CheckState.Checked;
|
||||
this.openAfterExport.Location = new System.Drawing.Point(6, 160);
|
||||
this.openAfterExport.Name = "openAfterExport";
|
||||
this.openAfterExport.Size = new System.Drawing.Size(168, 16);
|
||||
this.openAfterExport.TabIndex = 10;
|
||||
this.openAfterExport.Text = "Open folder after export";
|
||||
this.openAfterExport.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// restoreExtensionName
|
||||
//
|
||||
this.restoreExtensionName.AutoSize = true;
|
||||
this.restoreExtensionName.Checked = true;
|
||||
this.restoreExtensionName.CheckState = System.Windows.Forms.CheckState.Checked;
|
||||
this.restoreExtensionName.Location = new System.Drawing.Point(6, 58);
|
||||
this.restoreExtensionName.Name = "restoreExtensionName";
|
||||
this.restoreExtensionName.Size = new System.Drawing.Size(216, 16);
|
||||
this.restoreExtensionName.TabIndex = 9;
|
||||
this.restoreExtensionName.Text = "Restore TextAsset extension name";
|
||||
this.restoreExtensionName.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// assetGroupOptions
|
||||
//
|
||||
this.assetGroupOptions.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||
this.assetGroupOptions.FormattingEnabled = true;
|
||||
this.assetGroupOptions.Items.AddRange(new object[] {
|
||||
"type name",
|
||||
"container path",
|
||||
"source file name",
|
||||
"do not group"});
|
||||
this.assetGroupOptions.Location = new System.Drawing.Point(6, 32);
|
||||
this.assetGroupOptions.Name = "assetGroupOptions";
|
||||
this.assetGroupOptions.Size = new System.Drawing.Size(149, 20);
|
||||
this.assetGroupOptions.TabIndex = 8;
|
||||
//
|
||||
// label6
|
||||
//
|
||||
this.label6.AutoSize = true;
|
||||
this.label6.Location = new System.Drawing.Point(6, 17);
|
||||
this.label6.Name = "label6";
|
||||
this.label6.Size = new System.Drawing.Size(149, 12);
|
||||
this.label6.TabIndex = 7;
|
||||
this.label6.Text = "Group exported assets by";
|
||||
//
|
||||
// convertAudio
|
||||
//
|
||||
this.convertAudio.AutoSize = true;
|
||||
this.convertAudio.Checked = true;
|
||||
this.convertAudio.CheckState = System.Windows.Forms.CheckState.Checked;
|
||||
this.convertAudio.Location = new System.Drawing.Point(6, 78);
|
||||
this.convertAudio.Location = new System.Drawing.Point(6, 138);
|
||||
this.convertAudio.Name = "convertAudio";
|
||||
this.convertAudio.Size = new System.Drawing.Size(198, 16);
|
||||
this.convertAudio.TabIndex = 6;
|
||||
@@ -109,14 +166,25 @@
|
||||
//
|
||||
// panel1
|
||||
//
|
||||
this.panel1.Controls.Add(this.totga);
|
||||
this.panel1.Controls.Add(this.tojpg);
|
||||
this.panel1.Controls.Add(this.topng);
|
||||
this.panel1.Controls.Add(this.tobmp);
|
||||
this.panel1.Location = new System.Drawing.Point(30, 42);
|
||||
this.panel1.Location = new System.Drawing.Point(20, 102);
|
||||
this.panel1.Name = "panel1";
|
||||
this.panel1.Size = new System.Drawing.Size(146, 30);
|
||||
this.panel1.Size = new System.Drawing.Size(202, 30);
|
||||
this.panel1.TabIndex = 5;
|
||||
//
|
||||
// totga
|
||||
//
|
||||
this.totga.AutoSize = true;
|
||||
this.totga.Location = new System.Drawing.Point(150, 6);
|
||||
this.totga.Name = "totga";
|
||||
this.totga.Size = new System.Drawing.Size(41, 16);
|
||||
this.totga.TabIndex = 2;
|
||||
this.totga.Text = "TGA";
|
||||
this.totga.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// tojpg
|
||||
//
|
||||
this.tojpg.AutoSize = true;
|
||||
@@ -154,7 +222,7 @@
|
||||
this.converttexture.AutoSize = true;
|
||||
this.converttexture.Checked = true;
|
||||
this.converttexture.CheckState = System.Windows.Forms.CheckState.Checked;
|
||||
this.converttexture.Location = new System.Drawing.Point(6, 20);
|
||||
this.converttexture.Location = new System.Drawing.Point(6, 80);
|
||||
this.converttexture.Name = "converttexture";
|
||||
this.converttexture.Size = new System.Drawing.Size(126, 16);
|
||||
this.converttexture.TabIndex = 1;
|
||||
@@ -164,28 +232,53 @@
|
||||
// groupBox2
|
||||
//
|
||||
this.groupBox2.AutoSize = true;
|
||||
this.groupBox2.Controls.Add(this.exportBlendShape);
|
||||
this.groupBox2.Controls.Add(this.exportAnimations);
|
||||
this.groupBox2.Controls.Add(this.scaleFactor);
|
||||
this.groupBox2.Controls.Add(this.label5);
|
||||
this.groupBox2.Controls.Add(this.fbxFormat);
|
||||
this.groupBox2.Controls.Add(this.label4);
|
||||
this.groupBox2.Controls.Add(this.fbxVersion);
|
||||
this.groupBox2.Controls.Add(this.label3);
|
||||
this.groupBox2.Controls.Add(this.flatInbetween);
|
||||
this.groupBox2.Controls.Add(this.boneSize);
|
||||
this.groupBox2.Controls.Add(this.label2);
|
||||
this.groupBox2.Controls.Add(this.skins);
|
||||
this.groupBox2.Controls.Add(this.exportSkins);
|
||||
this.groupBox2.Controls.Add(this.label1);
|
||||
this.groupBox2.Controls.Add(this.filterPrecision);
|
||||
this.groupBox2.Controls.Add(this.allBones);
|
||||
this.groupBox2.Controls.Add(this.allFrames);
|
||||
this.groupBox2.Controls.Add(this.castToBone);
|
||||
this.groupBox2.Controls.Add(this.exportAllNodes);
|
||||
this.groupBox2.Controls.Add(this.eulerFilter);
|
||||
this.groupBox2.Location = new System.Drawing.Point(12, 12);
|
||||
this.groupBox2.Location = new System.Drawing.Point(250, 12);
|
||||
this.groupBox2.Name = "groupBox2";
|
||||
this.groupBox2.Size = new System.Drawing.Size(214, 276);
|
||||
this.groupBox2.Size = new System.Drawing.Size(214, 302);
|
||||
this.groupBox2.TabIndex = 11;
|
||||
this.groupBox2.TabStop = false;
|
||||
this.groupBox2.Text = "Fbx";
|
||||
//
|
||||
// exportBlendShape
|
||||
//
|
||||
this.exportBlendShape.AutoSize = true;
|
||||
this.exportBlendShape.Checked = true;
|
||||
this.exportBlendShape.CheckState = System.Windows.Forms.CheckState.Checked;
|
||||
this.exportBlendShape.Location = new System.Drawing.Point(6, 127);
|
||||
this.exportBlendShape.Name = "exportBlendShape";
|
||||
this.exportBlendShape.Size = new System.Drawing.Size(126, 16);
|
||||
this.exportBlendShape.TabIndex = 22;
|
||||
this.exportBlendShape.Text = "Export blendshape";
|
||||
this.exportBlendShape.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// exportAnimations
|
||||
//
|
||||
this.exportAnimations.AutoSize = true;
|
||||
this.exportAnimations.Checked = true;
|
||||
this.exportAnimations.CheckState = System.Windows.Forms.CheckState.Checked;
|
||||
this.exportAnimations.Location = new System.Drawing.Point(6, 105);
|
||||
this.exportAnimations.Name = "exportAnimations";
|
||||
this.exportAnimations.Size = new System.Drawing.Size(126, 16);
|
||||
this.exportAnimations.TabIndex = 21;
|
||||
this.exportAnimations.Text = "Export animations";
|
||||
this.exportAnimations.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// scaleFactor
|
||||
//
|
||||
this.scaleFactor.DecimalPlaces = 2;
|
||||
@@ -194,7 +287,7 @@
|
||||
0,
|
||||
0,
|
||||
131072});
|
||||
this.scaleFactor.Location = new System.Drawing.Point(83, 155);
|
||||
this.scaleFactor.Location = new System.Drawing.Point(83, 202);
|
||||
this.scaleFactor.Name = "scaleFactor";
|
||||
this.scaleFactor.Size = new System.Drawing.Size(60, 21);
|
||||
this.scaleFactor.TabIndex = 20;
|
||||
@@ -208,7 +301,7 @@
|
||||
// label5
|
||||
//
|
||||
this.label5.AutoSize = true;
|
||||
this.label5.Location = new System.Drawing.Point(6, 157);
|
||||
this.label5.Location = new System.Drawing.Point(6, 204);
|
||||
this.label5.Name = "label5";
|
||||
this.label5.Size = new System.Drawing.Size(71, 12);
|
||||
this.label5.TabIndex = 19;
|
||||
@@ -221,7 +314,7 @@
|
||||
this.fbxFormat.Items.AddRange(new object[] {
|
||||
"Binary",
|
||||
"Ascii"});
|
||||
this.fbxFormat.Location = new System.Drawing.Point(75, 207);
|
||||
this.fbxFormat.Location = new System.Drawing.Point(77, 233);
|
||||
this.fbxFormat.Name = "fbxFormat";
|
||||
this.fbxFormat.Size = new System.Drawing.Size(61, 20);
|
||||
this.fbxFormat.TabIndex = 18;
|
||||
@@ -229,7 +322,7 @@
|
||||
// label4
|
||||
//
|
||||
this.label4.AutoSize = true;
|
||||
this.label4.Location = new System.Drawing.Point(4, 210);
|
||||
this.label4.Location = new System.Drawing.Point(6, 236);
|
||||
this.label4.Name = "label4";
|
||||
this.label4.Size = new System.Drawing.Size(59, 12);
|
||||
this.label4.TabIndex = 17;
|
||||
@@ -246,7 +339,7 @@
|
||||
"7.3",
|
||||
"7.4",
|
||||
"7.5"});
|
||||
this.fbxVersion.Location = new System.Drawing.Point(75, 236);
|
||||
this.fbxVersion.Location = new System.Drawing.Point(77, 262);
|
||||
this.fbxVersion.Name = "fbxVersion";
|
||||
this.fbxVersion.Size = new System.Drawing.Size(47, 20);
|
||||
this.fbxVersion.TabIndex = 16;
|
||||
@@ -254,25 +347,15 @@
|
||||
// label3
|
||||
//
|
||||
this.label3.AutoSize = true;
|
||||
this.label3.Location = new System.Drawing.Point(4, 239);
|
||||
this.label3.Location = new System.Drawing.Point(6, 265);
|
||||
this.label3.Name = "label3";
|
||||
this.label3.Size = new System.Drawing.Size(65, 12);
|
||||
this.label3.TabIndex = 15;
|
||||
this.label3.Text = "FBXVersion";
|
||||
//
|
||||
// flatInbetween
|
||||
//
|
||||
this.flatInbetween.AutoSize = true;
|
||||
this.flatInbetween.Location = new System.Drawing.Point(6, 182);
|
||||
this.flatInbetween.Name = "flatInbetween";
|
||||
this.flatInbetween.Size = new System.Drawing.Size(102, 16);
|
||||
this.flatInbetween.TabIndex = 12;
|
||||
this.flatInbetween.Text = "FlatInbetween";
|
||||
this.flatInbetween.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// boneSize
|
||||
//
|
||||
this.boneSize.Location = new System.Drawing.Point(65, 128);
|
||||
this.boneSize.Location = new System.Drawing.Point(65, 175);
|
||||
this.boneSize.Name = "boneSize";
|
||||
this.boneSize.Size = new System.Drawing.Size(46, 21);
|
||||
this.boneSize.TabIndex = 11;
|
||||
@@ -285,23 +368,23 @@
|
||||
// label2
|
||||
//
|
||||
this.label2.AutoSize = true;
|
||||
this.label2.Location = new System.Drawing.Point(6, 130);
|
||||
this.label2.Location = new System.Drawing.Point(6, 177);
|
||||
this.label2.Name = "label2";
|
||||
this.label2.Size = new System.Drawing.Size(53, 12);
|
||||
this.label2.TabIndex = 10;
|
||||
this.label2.Text = "BoneSize";
|
||||
//
|
||||
// skins
|
||||
// exportSkins
|
||||
//
|
||||
this.skins.AutoSize = true;
|
||||
this.skins.Checked = true;
|
||||
this.skins.CheckState = System.Windows.Forms.CheckState.Checked;
|
||||
this.skins.Location = new System.Drawing.Point(6, 105);
|
||||
this.skins.Name = "skins";
|
||||
this.skins.Size = new System.Drawing.Size(54, 16);
|
||||
this.skins.TabIndex = 8;
|
||||
this.skins.Text = "Skins";
|
||||
this.skins.UseVisualStyleBackColor = true;
|
||||
this.exportSkins.AutoSize = true;
|
||||
this.exportSkins.Checked = true;
|
||||
this.exportSkins.CheckState = System.Windows.Forms.CheckState.Checked;
|
||||
this.exportSkins.Location = new System.Drawing.Point(6, 83);
|
||||
this.exportSkins.Name = "exportSkins";
|
||||
this.exportSkins.Size = new System.Drawing.Size(96, 16);
|
||||
this.exportSkins.TabIndex = 8;
|
||||
this.exportSkins.Text = "Export skins";
|
||||
this.exportSkins.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// label1
|
||||
//
|
||||
@@ -330,27 +413,27 @@
|
||||
0,
|
||||
131072});
|
||||
//
|
||||
// allBones
|
||||
// castToBone
|
||||
//
|
||||
this.allBones.AutoSize = true;
|
||||
this.allBones.Checked = true;
|
||||
this.allBones.CheckState = System.Windows.Forms.CheckState.Checked;
|
||||
this.allBones.Location = new System.Drawing.Point(6, 83);
|
||||
this.allBones.Name = "allBones";
|
||||
this.allBones.Size = new System.Drawing.Size(72, 16);
|
||||
this.allBones.TabIndex = 5;
|
||||
this.allBones.Text = "AllBones";
|
||||
this.allBones.UseVisualStyleBackColor = true;
|
||||
this.castToBone.AutoSize = true;
|
||||
this.castToBone.Location = new System.Drawing.Point(6, 149);
|
||||
this.castToBone.Name = "castToBone";
|
||||
this.castToBone.Size = new System.Drawing.Size(156, 16);
|
||||
this.castToBone.TabIndex = 5;
|
||||
this.castToBone.Text = "All nodes cast to bone";
|
||||
this.castToBone.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// allFrames
|
||||
// exportAllNodes
|
||||
//
|
||||
this.allFrames.AutoSize = true;
|
||||
this.allFrames.Location = new System.Drawing.Point(6, 61);
|
||||
this.allFrames.Name = "allFrames";
|
||||
this.allFrames.Size = new System.Drawing.Size(78, 16);
|
||||
this.allFrames.TabIndex = 4;
|
||||
this.allFrames.Text = "AllFrames";
|
||||
this.allFrames.UseVisualStyleBackColor = true;
|
||||
this.exportAllNodes.AutoSize = true;
|
||||
this.exportAllNodes.Checked = true;
|
||||
this.exportAllNodes.CheckState = System.Windows.Forms.CheckState.Checked;
|
||||
this.exportAllNodes.Location = new System.Drawing.Point(6, 61);
|
||||
this.exportAllNodes.Name = "exportAllNodes";
|
||||
this.exportAllNodes.Size = new System.Drawing.Size(120, 16);
|
||||
this.exportAllNodes.TabIndex = 4;
|
||||
this.exportAllNodes.Text = "Export all nodes";
|
||||
this.exportAllNodes.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// eulerFilter
|
||||
//
|
||||
@@ -370,7 +453,7 @@
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.CancelButton = this.Cancel;
|
||||
this.ClientSize = new System.Drawing.Size(490, 301);
|
||||
this.ClientSize = new System.Drawing.Size(477, 351);
|
||||
this.Controls.Add(this.groupBox2);
|
||||
this.Controls.Add(this.groupBox1);
|
||||
this.Controls.Add(this.Cancel);
|
||||
@@ -405,17 +488,17 @@
|
||||
private System.Windows.Forms.RadioButton tojpg;
|
||||
private System.Windows.Forms.RadioButton topng;
|
||||
private System.Windows.Forms.RadioButton tobmp;
|
||||
private System.Windows.Forms.RadioButton totga;
|
||||
private System.Windows.Forms.CheckBox convertAudio;
|
||||
private System.Windows.Forms.Panel panel1;
|
||||
private System.Windows.Forms.GroupBox groupBox2;
|
||||
private System.Windows.Forms.CheckBox flatInbetween;
|
||||
private System.Windows.Forms.NumericUpDown boneSize;
|
||||
private System.Windows.Forms.Label label2;
|
||||
private System.Windows.Forms.CheckBox skins;
|
||||
private System.Windows.Forms.CheckBox exportSkins;
|
||||
private System.Windows.Forms.Label label1;
|
||||
private System.Windows.Forms.NumericUpDown filterPrecision;
|
||||
private System.Windows.Forms.CheckBox allBones;
|
||||
private System.Windows.Forms.CheckBox allFrames;
|
||||
private System.Windows.Forms.CheckBox castToBone;
|
||||
private System.Windows.Forms.CheckBox exportAllNodes;
|
||||
private System.Windows.Forms.CheckBox eulerFilter;
|
||||
private System.Windows.Forms.Label label3;
|
||||
private System.Windows.Forms.ComboBox fbxVersion;
|
||||
@@ -423,5 +506,11 @@
|
||||
private System.Windows.Forms.Label label4;
|
||||
private System.Windows.Forms.NumericUpDown scaleFactor;
|
||||
private System.Windows.Forms.Label label5;
|
||||
private System.Windows.Forms.CheckBox exportBlendShape;
|
||||
private System.Windows.Forms.CheckBox exportAnimations;
|
||||
private System.Windows.Forms.ComboBox assetGroupOptions;
|
||||
private System.Windows.Forms.Label label6;
|
||||
private System.Windows.Forms.CheckBox restoreExtensionName;
|
||||
private System.Windows.Forms.CheckBox openAfterExport;
|
||||
}
|
||||
}
|
||||
@@ -15,9 +15,11 @@ namespace AssetStudioGUI
|
||||
public ExportOptions()
|
||||
{
|
||||
InitializeComponent();
|
||||
converttexture.Checked = (bool)Properties.Settings.Default["convertTexture"];
|
||||
convertAudio.Checked = (bool)Properties.Settings.Default["convertAudio"];
|
||||
var str = (string)Properties.Settings.Default["convertType"];
|
||||
assetGroupOptions.SelectedIndex = Properties.Settings.Default.assetGroupOption;
|
||||
restoreExtensionName.Checked = Properties.Settings.Default.restoreExtensionName;
|
||||
converttexture.Checked = Properties.Settings.Default.convertTexture;
|
||||
convertAudio.Checked = Properties.Settings.Default.convertAudio;
|
||||
var str = Properties.Settings.Default.convertType;
|
||||
foreach (Control c in panel1.Controls)
|
||||
{
|
||||
if (c.Text == str)
|
||||
@@ -26,46 +28,46 @@ namespace AssetStudioGUI
|
||||
break;
|
||||
}
|
||||
}
|
||||
eulerFilter.Checked = (bool)Properties.Settings.Default["eulerFilter"];
|
||||
filterPrecision.Value = (decimal)Properties.Settings.Default["filterPrecision"];
|
||||
allFrames.Checked = (bool)Properties.Settings.Default["allFrames"];
|
||||
allBones.Checked = (bool)Properties.Settings.Default["allBones"];
|
||||
skins.Checked = (bool)Properties.Settings.Default["skins"];
|
||||
boneSize.Value = (decimal)Properties.Settings.Default["boneSize"];
|
||||
scaleFactor.Value = (decimal)Properties.Settings.Default["scaleFactor"];
|
||||
flatInbetween.Checked = (bool)Properties.Settings.Default["flatInbetween"];
|
||||
fbxVersion.SelectedIndex = (int)Properties.Settings.Default["fbxVersion"];
|
||||
fbxFormat.SelectedIndex = (int)Properties.Settings.Default["fbxFormat"];
|
||||
openAfterExport.Checked = Properties.Settings.Default.openAfterExport;
|
||||
eulerFilter.Checked = Properties.Settings.Default.eulerFilter;
|
||||
filterPrecision.Value = Properties.Settings.Default.filterPrecision;
|
||||
exportAllNodes.Checked = Properties.Settings.Default.exportAllNodes;
|
||||
exportSkins.Checked = Properties.Settings.Default.exportSkins;
|
||||
exportAnimations.Checked = Properties.Settings.Default.exportAnimations;
|
||||
exportBlendShape.Checked = Properties.Settings.Default.exportBlendShape;
|
||||
castToBone.Checked = Properties.Settings.Default.castToBone;
|
||||
boneSize.Value = Properties.Settings.Default.boneSize;
|
||||
scaleFactor.Value = Properties.Settings.Default.scaleFactor;
|
||||
fbxVersion.SelectedIndex = Properties.Settings.Default.fbxVersion;
|
||||
fbxFormat.SelectedIndex = Properties.Settings.Default.fbxFormat;
|
||||
}
|
||||
|
||||
private void exportOpnions_CheckedChanged(object sender, EventArgs e)
|
||||
private void OKbutton_Click(object sender, EventArgs e)
|
||||
{
|
||||
Properties.Settings.Default[((CheckBox)sender).Name] = ((CheckBox)sender).Checked;
|
||||
Properties.Settings.Default.Save();
|
||||
}
|
||||
|
||||
private void fbxOKbutton_Click(object sender, EventArgs e)
|
||||
{
|
||||
Properties.Settings.Default["convertTexture"] = converttexture.Checked;
|
||||
Properties.Settings.Default["convertAudio"] = convertAudio.Checked;
|
||||
Properties.Settings.Default.assetGroupOption = assetGroupOptions.SelectedIndex;
|
||||
Properties.Settings.Default.restoreExtensionName = restoreExtensionName.Checked;
|
||||
Properties.Settings.Default.convertTexture = converttexture.Checked;
|
||||
Properties.Settings.Default.convertAudio = convertAudio.Checked;
|
||||
foreach (Control c in panel1.Controls)
|
||||
{
|
||||
if (((RadioButton)c).Checked)
|
||||
{
|
||||
Properties.Settings.Default["convertType"] = c.Text;
|
||||
Properties.Settings.Default.convertType = c.Text;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Properties.Settings.Default["eulerFilter"] = eulerFilter.Checked;
|
||||
Properties.Settings.Default["filterPrecision"] = filterPrecision.Value;
|
||||
Properties.Settings.Default["allFrames"] = allFrames.Checked;
|
||||
Properties.Settings.Default["allBones"] = allBones.Checked;
|
||||
Properties.Settings.Default["skins"] = skins.Checked;
|
||||
Properties.Settings.Default["boneSize"] = boneSize.Value;
|
||||
Properties.Settings.Default["scaleFactor"] = scaleFactor.Value;
|
||||
Properties.Settings.Default["flatInbetween"] = flatInbetween.Checked;
|
||||
Properties.Settings.Default["fbxVersion"] = fbxVersion.SelectedIndex;
|
||||
Properties.Settings.Default["fbxFormat"] = fbxFormat.SelectedIndex;
|
||||
Properties.Settings.Default.openAfterExport = openAfterExport.Checked;
|
||||
Properties.Settings.Default.eulerFilter = eulerFilter.Checked;
|
||||
Properties.Settings.Default.filterPrecision = filterPrecision.Value;
|
||||
Properties.Settings.Default.exportAllNodes = exportAllNodes.Checked;
|
||||
Properties.Settings.Default.exportSkins = exportSkins.Checked;
|
||||
Properties.Settings.Default.exportAnimations = exportAnimations.Checked;
|
||||
Properties.Settings.Default.exportBlendShape = exportBlendShape.Checked;
|
||||
Properties.Settings.Default.castToBone = castToBone.Checked;
|
||||
Properties.Settings.Default.boneSize = boneSize.Value;
|
||||
Properties.Settings.Default.scaleFactor = scaleFactor.Value;
|
||||
Properties.Settings.Default.fbxVersion = fbxVersion.SelectedIndex;
|
||||
Properties.Settings.Default.fbxFormat = fbxFormat.SelectedIndex;
|
||||
Properties.Settings.Default.Save();
|
||||
DialogResult = DialogResult.OK;
|
||||
Close();
|
||||
|
||||
+200
-102
@@ -4,22 +4,24 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using AssetStudio;
|
||||
using Newtonsoft.Json;
|
||||
using TGASharpLib;
|
||||
|
||||
namespace AssetStudioGUI
|
||||
{
|
||||
internal static class Exporter
|
||||
{
|
||||
public static bool ExportTexture2D(AssetItem item, string exportPathName)
|
||||
public static bool ExportTexture2D(AssetItem item, string exportPath)
|
||||
{
|
||||
var converter = new Texture2DConverter((Texture2D)item.Asset);
|
||||
var convertTexture = (bool)Properties.Settings.Default["convertTexture"];
|
||||
if (convertTexture)
|
||||
var m_Texture2D = (Texture2D)item.Asset;
|
||||
if (Properties.Settings.Default.convertTexture)
|
||||
{
|
||||
var bitmap = converter.ConvertToBitmap(true);
|
||||
var bitmap = m_Texture2D.ConvertToBitmap(true);
|
||||
if (bitmap == null)
|
||||
return false;
|
||||
ImageFormat format = null;
|
||||
var ext = (string)Properties.Settings.Default["convertType"];
|
||||
var ext = Properties.Settings.Default.convertType;
|
||||
bool tga = false;
|
||||
switch (ext)
|
||||
{
|
||||
case "BMP":
|
||||
@@ -31,20 +33,29 @@ namespace AssetStudioGUI
|
||||
case "JPEG":
|
||||
format = ImageFormat.Jpeg;
|
||||
break;
|
||||
case "TGA":
|
||||
tga = true;
|
||||
break;
|
||||
}
|
||||
var exportFullName = exportPathName + item.Text + "." + ext.ToLower();
|
||||
if (ExportFileExists(exportFullName))
|
||||
if (!TryExportFile(exportPath, item, "." + ext.ToLower(), out var exportFullPath))
|
||||
return false;
|
||||
bitmap.Save(exportFullName, format);
|
||||
if (tga)
|
||||
{
|
||||
var file = new TGA(bitmap);
|
||||
file.Save(exportFullPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
bitmap.Save(exportFullPath, format);
|
||||
}
|
||||
bitmap.Dispose();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
var exportFullName = exportPathName + item.Text + converter.GetExtensionName();
|
||||
if (ExportFileExists(exportFullName))
|
||||
if (!TryExportFile(exportPath, item, ".tex", out var exportFullPath))
|
||||
return false;
|
||||
File.WriteAllBytes(exportFullName, converter.ConvertToContainer());
|
||||
File.WriteAllBytes(exportFullPath, m_Texture2D.image_data.GetData());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -52,72 +63,68 @@ namespace AssetStudioGUI
|
||||
public static bool ExportAudioClip(AssetItem item, string exportPath)
|
||||
{
|
||||
var m_AudioClip = (AudioClip)item.Asset;
|
||||
var m_AudioData = m_AudioClip.m_AudioData.Value;
|
||||
var m_AudioData = m_AudioClip.m_AudioData.GetData();
|
||||
if (m_AudioData == null || m_AudioData.Length == 0)
|
||||
return false;
|
||||
var convertAudio = (bool)Properties.Settings.Default["convertAudio"];
|
||||
var converter = new AudioClipConverter(m_AudioClip);
|
||||
if (convertAudio && converter.IsFMODSupport)
|
||||
if (Properties.Settings.Default.convertAudio && converter.IsSupport)
|
||||
{
|
||||
var exportFullName = exportPath + item.Text + ".wav";
|
||||
if (ExportFileExists(exportFullName))
|
||||
if (!TryExportFile(exportPath, item, ".wav", out var exportFullPath))
|
||||
return false;
|
||||
var buffer = converter.ConvertToWav();
|
||||
if (buffer == null)
|
||||
return false;
|
||||
File.WriteAllBytes(exportFullName, buffer);
|
||||
File.WriteAllBytes(exportFullPath, buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
var exportFullName = exportPath + item.Text + converter.GetExtensionName();
|
||||
if (ExportFileExists(exportFullName))
|
||||
if (!TryExportFile(exportPath, item, converter.GetExtensionName(), out var exportFullPath))
|
||||
return false;
|
||||
File.WriteAllBytes(exportFullName, m_AudioData);
|
||||
File.WriteAllBytes(exportFullPath, m_AudioData);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool ExportShader(AssetItem item, string exportPath)
|
||||
{
|
||||
var exportFullName = exportPath + item.Text + ".shader";
|
||||
if (ExportFileExists(exportFullName))
|
||||
if (!TryExportFile(exportPath, item, ".shader", out var exportFullPath))
|
||||
return false;
|
||||
var m_Shader = (Shader) item.Asset;
|
||||
if (m_Shader.compressedBlob != null) //5.5 and up
|
||||
{
|
||||
var strs = ShaderConverter.ConvertMultiple(m_Shader);
|
||||
for (int i = 0; i < strs.Length; i++)
|
||||
{
|
||||
var platformName = ShaderConverter.GetPlatformString(m_Shader.platforms[i]);
|
||||
File.WriteAllText($"{exportPath}{item.Text}_{platformName}.shader", strs[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var str = ShaderConverter.Convert(m_Shader);
|
||||
File.WriteAllText(exportFullName, str);
|
||||
}
|
||||
var m_Shader = (Shader)item.Asset;
|
||||
var str = m_Shader.Convert();
|
||||
File.WriteAllText(exportFullPath, str);
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool ExportTextAsset(AssetItem item, string exportPath)
|
||||
{
|
||||
var m_TextAsset = (TextAsset)(item.Asset);
|
||||
var exportFullName = exportPath + item.Text + (item.Extension ?? ".txt");
|
||||
if (ExportFileExists(exportFullName))
|
||||
var extension = ".txt";
|
||||
if (Properties.Settings.Default.restoreExtensionName)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(item.Container))
|
||||
{
|
||||
extension = Path.GetExtension(item.Container);
|
||||
}
|
||||
}
|
||||
if (!TryExportFile(exportPath, item, extension, out var exportFullPath))
|
||||
return false;
|
||||
File.WriteAllBytes(exportFullName, m_TextAsset.m_Script);
|
||||
File.WriteAllBytes(exportFullPath, m_TextAsset.m_Script);
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool ExportMonoBehaviour(AssetItem item, string exportPath)
|
||||
{
|
||||
var exportFullName = exportPath + item.Text + ".txt";
|
||||
if (ExportFileExists(exportFullName))
|
||||
if (!TryExportFile(exportPath, item, ".json", out var exportFullPath))
|
||||
return false;
|
||||
var m_MonoBehaviour = (MonoBehaviour)item.Asset;
|
||||
var str = m_MonoBehaviour.Dump() ?? Studio.GetScriptString(item.Asset.reader);
|
||||
File.WriteAllText(exportFullName, str);
|
||||
var type = m_MonoBehaviour.ToType();
|
||||
if (type == null)
|
||||
{
|
||||
var nodes = Studio.MonoBehaviourToTypeTreeNodes(m_MonoBehaviour);
|
||||
type = m_MonoBehaviour.ToType(nodes);
|
||||
}
|
||||
var str = JsonConvert.SerializeObject(type, Formatting.Indented);
|
||||
File.WriteAllText(exportFullPath, str);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -131,10 +138,9 @@ namespace AssetStudioGUI
|
||||
{
|
||||
extension = ".otf";
|
||||
}
|
||||
var exportFullName = exportPath + item.Text + extension;
|
||||
if (ExportFileExists(exportFullName))
|
||||
if (!TryExportFile(exportPath, item, extension, out var exportFullPath))
|
||||
return false;
|
||||
File.WriteAllBytes(exportFullName, m_Font.m_FontData);
|
||||
File.WriteAllBytes(exportFullPath, m_Font.m_FontData);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -145,8 +151,7 @@ namespace AssetStudioGUI
|
||||
var m_Mesh = (Mesh)item.Asset;
|
||||
if (m_Mesh.m_VertexCount <= 0)
|
||||
return false;
|
||||
var exportFullName = exportPath + item.Text + ".obj";
|
||||
if (ExportFileExists(exportFullName))
|
||||
if (!TryExportFile(exportPath, item, ".obj", out var exportFullPath))
|
||||
return false;
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine("g " + m_Mesh.m_Name);
|
||||
@@ -167,24 +172,25 @@ namespace AssetStudioGUI
|
||||
#endregion
|
||||
|
||||
#region UV
|
||||
if (m_Mesh.m_UV0 != null && m_Mesh.m_UV0.Length == m_Mesh.m_VertexCount * 2)
|
||||
if (m_Mesh.m_UV0?.Length > 0)
|
||||
{
|
||||
for (int v = 0; v < m_Mesh.m_VertexCount; v++)
|
||||
if (m_Mesh.m_UV0.Length == m_Mesh.m_VertexCount * 2)
|
||||
{
|
||||
sb.AppendFormat("vt {0} {1}\r\n", m_Mesh.m_UV0[v * 2], m_Mesh.m_UV0[v * 2 + 1]);
|
||||
c = 2;
|
||||
}
|
||||
else if (m_Mesh.m_UV0.Length == m_Mesh.m_VertexCount * 3)
|
||||
{
|
||||
c = 3;
|
||||
}
|
||||
}
|
||||
else if (m_Mesh.m_UV1 != null && m_Mesh.m_UV1.Length == m_Mesh.m_VertexCount * 2)
|
||||
{
|
||||
for (int v = 0; v < m_Mesh.m_VertexCount; v++)
|
||||
{
|
||||
sb.AppendFormat("vt {0} {1}\r\n", m_Mesh.m_UV1[v * 2], m_Mesh.m_UV1[v * 2 + 1]);
|
||||
sb.AppendFormat("vt {0} {1}\r\n", m_Mesh.m_UV0[v * c], m_Mesh.m_UV0[v * c + 1]);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Normals
|
||||
if (m_Mesh.m_Normals != null && m_Mesh.m_Normals.Length > 0)
|
||||
if (m_Mesh.m_Normals?.Length > 0)
|
||||
{
|
||||
if (m_Mesh.m_Normals.Length == m_Mesh.m_VertexCount * 3)
|
||||
{
|
||||
@@ -217,20 +223,19 @@ namespace AssetStudioGUI
|
||||
#endregion
|
||||
|
||||
sb.Replace("NaN", "0");
|
||||
File.WriteAllText(exportFullName, sb.ToString());
|
||||
File.WriteAllText(exportFullPath, sb.ToString());
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool ExportVideoClip(AssetItem item, string exportPath)
|
||||
{
|
||||
var m_VideoClip = (VideoClip)item.Asset;
|
||||
var m_VideoData = m_VideoClip.m_VideoData.Value;
|
||||
var m_VideoData = m_VideoClip.m_VideoData.GetData();
|
||||
if (m_VideoData != null && m_VideoData.Length != 0)
|
||||
{
|
||||
var exportFullName = exportPath + item.Text + Path.GetExtension(m_VideoClip.m_OriginalPath);
|
||||
if (ExportFileExists(exportFullName))
|
||||
if (!TryExportFile(exportPath, item, Path.GetExtension(m_VideoClip.m_OriginalPath), out var exportFullPath))
|
||||
return false;
|
||||
File.WriteAllBytes(exportFullName, m_VideoData);
|
||||
File.WriteAllBytes(exportFullPath, m_VideoData);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -239,17 +244,17 @@ namespace AssetStudioGUI
|
||||
public static bool ExportMovieTexture(AssetItem item, string exportPath)
|
||||
{
|
||||
var m_MovieTexture = (MovieTexture)item.Asset;
|
||||
var exportFullName = exportPath + item.Text + ".ogv";
|
||||
if (ExportFileExists(exportFullName))
|
||||
if (!TryExportFile(exportPath, item, ".ogv", out var exportFullPath))
|
||||
return false;
|
||||
File.WriteAllBytes(exportFullName, m_MovieTexture.m_MovieData);
|
||||
File.WriteAllBytes(exportFullPath, m_MovieTexture.m_MovieData);
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool ExportSprite(AssetItem item, string exportPath)
|
||||
{
|
||||
ImageFormat format = null;
|
||||
var type = (string)Properties.Settings.Default["convertType"];
|
||||
var type = Properties.Settings.Default.convertType;
|
||||
bool tga = false;
|
||||
switch (type)
|
||||
{
|
||||
case "BMP":
|
||||
@@ -261,14 +266,24 @@ namespace AssetStudioGUI
|
||||
case "JPEG":
|
||||
format = ImageFormat.Jpeg;
|
||||
break;
|
||||
case "TGA":
|
||||
tga = true;
|
||||
break;
|
||||
}
|
||||
var exportFullName = exportPath + item.Text + "." + type.ToLower();
|
||||
if (ExportFileExists(exportFullName))
|
||||
if (!TryExportFile(exportPath, item, "." + type.ToLower(), out var exportFullPath))
|
||||
return false;
|
||||
var bitmap = SpriteHelper.GetImageFromSprite((Sprite)item.Asset);
|
||||
var bitmap = ((Sprite)item.Asset).GetImage();
|
||||
if (bitmap != null)
|
||||
{
|
||||
bitmap.Save(exportFullName, format);
|
||||
if (tga)
|
||||
{
|
||||
var file = new TGA(bitmap);
|
||||
file.Save(exportFullPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
bitmap.Save(exportFullPath, format);
|
||||
}
|
||||
bitmap.Dispose();
|
||||
return true;
|
||||
}
|
||||
@@ -277,52 +292,135 @@ namespace AssetStudioGUI
|
||||
|
||||
public static bool ExportRawFile(AssetItem item, string exportPath)
|
||||
{
|
||||
var exportFullName = exportPath + item.Text + ".dat";
|
||||
if (ExportFileExists(exportFullName))
|
||||
if (!TryExportFile(exportPath, item, ".dat", out var exportFullPath))
|
||||
return false;
|
||||
File.WriteAllBytes(exportFullName, item.Asset.GetRawData());
|
||||
File.WriteAllBytes(exportFullPath, item.Asset.GetRawData());
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool ExportFileExists(string filename)
|
||||
private static bool TryExportFile(string dir, AssetItem item, string extension, out string fullPath)
|
||||
{
|
||||
if (File.Exists(filename))
|
||||
var fileName = FixFileName(item.Text);
|
||||
fullPath = Path.Combine(dir, fileName + extension);
|
||||
if (!File.Exists(fullPath))
|
||||
{
|
||||
Directory.CreateDirectory(dir);
|
||||
return true;
|
||||
}
|
||||
fullPath = Path.Combine(dir, fileName + item.UniqueID + extension);
|
||||
if (!File.Exists(fullPath))
|
||||
{
|
||||
Directory.CreateDirectory(dir);
|
||||
return true;
|
||||
}
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(filename));
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool ExportAnimator(AssetItem item, string exportPath, List<AssetItem> animationList = null)
|
||||
{
|
||||
var exportFullPath = Path.Combine(exportPath, item.Text, item.Text + ".fbx");
|
||||
if (File.Exists(exportFullPath))
|
||||
{
|
||||
exportFullPath = Path.Combine(exportPath, item.Text + item.UniqueID, item.Text + ".fbx");
|
||||
}
|
||||
var m_Animator = (Animator)item.Asset;
|
||||
var convert = animationList != null ? new ModelConverter(m_Animator, animationList.Select(x => (AnimationClip)x.Asset).ToArray()) : new ModelConverter(m_Animator);
|
||||
exportPath = $"{exportPath}{item.Text}\\{item.Text}.fbx";
|
||||
return ExportFbx(convert, exportPath);
|
||||
}
|
||||
|
||||
public static bool ExportGameObject(GameObject gameObject, string exportPath, List<AssetItem> animationList = null)
|
||||
{
|
||||
var convert = animationList != null ? new ModelConverter(gameObject, animationList.Select(x => (AnimationClip)x.Asset).ToArray()) : new ModelConverter(gameObject);
|
||||
exportPath = exportPath + Studio.FixFileName(gameObject.m_Name) + ".fbx";
|
||||
return ExportFbx(convert, exportPath);
|
||||
}
|
||||
|
||||
private static bool ExportFbx(IImported convert, string exportPath)
|
||||
{
|
||||
var eulerFilter = (bool)Properties.Settings.Default["eulerFilter"];
|
||||
var filterPrecision = (float)(decimal)Properties.Settings.Default["filterPrecision"];
|
||||
var allFrames = (bool)Properties.Settings.Default["allFrames"];
|
||||
var allBones = (bool)Properties.Settings.Default["allBones"];
|
||||
var skins = (bool)Properties.Settings.Default["skins"];
|
||||
var boneSize = (int)(decimal)Properties.Settings.Default["boneSize"];
|
||||
var scaleFactor = (float)(decimal)Properties.Settings.Default["scaleFactor"];
|
||||
var flatInbetween = (bool)Properties.Settings.Default["flatInbetween"];
|
||||
var fbxVersion = (int)Properties.Settings.Default["fbxVersion"];
|
||||
var fbxFormat = (int)Properties.Settings.Default["fbxFormat"];
|
||||
ModelExporter.ExportFbx(exportPath, convert, eulerFilter, filterPrecision, allFrames, allBones, skins, boneSize, scaleFactor, flatInbetween, fbxVersion, fbxFormat == 1);
|
||||
var convert = animationList != null
|
||||
? new ModelConverter(m_Animator, Properties.Settings.Default.convertType, animationList.Select(x => (AnimationClip)x.Asset).ToArray())
|
||||
: new ModelConverter(m_Animator, Properties.Settings.Default.convertType);
|
||||
ExportFbx(convert, exportFullPath);
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void ExportGameObject(GameObject gameObject, string exportPath, List<AssetItem> animationList = null)
|
||||
{
|
||||
var convert = animationList != null
|
||||
? new ModelConverter(gameObject, Properties.Settings.Default.convertType, animationList.Select(x => (AnimationClip)x.Asset).ToArray())
|
||||
: new ModelConverter(gameObject, Properties.Settings.Default.convertType);
|
||||
exportPath = exportPath + FixFileName(gameObject.m_Name) + ".fbx";
|
||||
ExportFbx(convert, exportPath);
|
||||
}
|
||||
|
||||
public static void ExportGameObjectMerge(List<GameObject> gameObject, string exportPath, List<AssetItem> animationList = null)
|
||||
{
|
||||
var rootName = Path.GetFileNameWithoutExtension(exportPath);
|
||||
var convert = animationList != null
|
||||
? new ModelConverter(rootName, gameObject, Properties.Settings.Default.convertType, animationList.Select(x => (AnimationClip)x.Asset).ToArray())
|
||||
: new ModelConverter(rootName, gameObject, Properties.Settings.Default.convertType);
|
||||
ExportFbx(convert, exportPath);
|
||||
}
|
||||
|
||||
private static void ExportFbx(IImported convert, string exportPath)
|
||||
{
|
||||
var eulerFilter = Properties.Settings.Default.eulerFilter;
|
||||
var filterPrecision = (float)Properties.Settings.Default.filterPrecision;
|
||||
var exportAllNodes = Properties.Settings.Default.exportAllNodes;
|
||||
var exportSkins = Properties.Settings.Default.exportSkins;
|
||||
var exportAnimations = Properties.Settings.Default.exportAnimations;
|
||||
var exportBlendShape = Properties.Settings.Default.exportBlendShape;
|
||||
var castToBone = Properties.Settings.Default.castToBone;
|
||||
var boneSize = (int)Properties.Settings.Default.boneSize;
|
||||
var scaleFactor = (float)Properties.Settings.Default.scaleFactor;
|
||||
var fbxVersion = Properties.Settings.Default.fbxVersion;
|
||||
var fbxFormat = Properties.Settings.Default.fbxFormat;
|
||||
ModelExporter.ExportFbx(exportPath, convert, eulerFilter, filterPrecision,
|
||||
exportAllNodes, exportSkins, exportAnimations, exportBlendShape, castToBone, boneSize, scaleFactor, fbxVersion, fbxFormat == 1);
|
||||
}
|
||||
|
||||
public static bool ExportDumpFile(AssetItem item, string exportPath)
|
||||
{
|
||||
if (!TryExportFile(exportPath, item, ".txt", out var exportFullPath))
|
||||
return false;
|
||||
var str = item.Asset.Dump();
|
||||
if (str == null && item.Asset is MonoBehaviour m_MonoBehaviour)
|
||||
{
|
||||
var nodes = Studio.MonoBehaviourToTypeTreeNodes(m_MonoBehaviour);
|
||||
str = m_MonoBehaviour.Dump(nodes);
|
||||
}
|
||||
if (str != null)
|
||||
{
|
||||
File.WriteAllText(exportFullPath, str);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool ExportConvertFile(AssetItem item, string exportPath)
|
||||
{
|
||||
switch (item.Type)
|
||||
{
|
||||
case ClassIDType.Texture2D:
|
||||
return ExportTexture2D(item, exportPath);
|
||||
case ClassIDType.AudioClip:
|
||||
return ExportAudioClip(item, exportPath);
|
||||
case ClassIDType.Shader:
|
||||
return ExportShader(item, exportPath);
|
||||
case ClassIDType.TextAsset:
|
||||
return ExportTextAsset(item, exportPath);
|
||||
case ClassIDType.MonoBehaviour:
|
||||
return ExportMonoBehaviour(item, exportPath);
|
||||
case ClassIDType.Font:
|
||||
return ExportFont(item, exportPath);
|
||||
case ClassIDType.Mesh:
|
||||
return ExportMesh(item, exportPath);
|
||||
case ClassIDType.VideoClip:
|
||||
return ExportVideoClip(item, exportPath);
|
||||
case ClassIDType.MovieTexture:
|
||||
return ExportMovieTexture(item, exportPath);
|
||||
case ClassIDType.Sprite:
|
||||
return ExportSprite(item, exportPath);
|
||||
case ClassIDType.Animator:
|
||||
return ExportAnimator(item, exportPath);
|
||||
case ClassIDType.AnimationClip:
|
||||
return false;
|
||||
default:
|
||||
return ExportRawFile(item, exportPath);
|
||||
}
|
||||
}
|
||||
|
||||
public static string FixFileName(string str)
|
||||
{
|
||||
if (str.Length >= 260) return Path.GetRandomFileName();
|
||||
return Path.GetInvalidFileNameChars().Aggregate(str, (current, c) => current.Replace(c, '_'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using AssetStudio;
|
||||
using AssetStudio;
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace AssetStudioGUI
|
||||
{
|
||||
@@ -17,7 +15,16 @@ namespace AssetStudioGUI
|
||||
|
||||
public void Log(LoggerEvent loggerEvent, string message)
|
||||
{
|
||||
action(message);
|
||||
switch (loggerEvent)
|
||||
{
|
||||
case LoggerEvent.Error:
|
||||
MessageBox.Show(message);
|
||||
break;
|
||||
default:
|
||||
action(message);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,151 +0,0 @@
|
||||
FMOD, FMOD Ex, FMOD Designer and FMOD Studio are
|
||||
Copyright © 2005-2016 Firelight Technologies Pty, Ltd.
|
||||
|
||||
GRANT OF LICENSE
|
||||
----------------
|
||||
THIS END USER LICENSE AGREEMENT GRANTS THE USER, THE RIGHT TO USE FMOD,
|
||||
IN ITS LIBRARY AND TOOL FORM, IN THEIR OWN PRODUCTS, BE THEY FOR PERSONAL,
|
||||
EDUCATIONAL OR COMMERCIAL USE.
|
||||
THE USER MUST ADHERE TO THE LICENSING MODEL PROVIDED BY FIRELIGHT
|
||||
TECHNOLOGIES, AND MUST APPLY FOR A LICENSE IF NECESSARY. THE FOLLOWING
|
||||
LICENSES ARE AVAILABLE.
|
||||
|
||||
FMOD NON-COMMERCIAL LICENSE
|
||||
------------------------------------
|
||||
IF YOUR PRODUCT IS NOT INTENDED FOR COMMERCIAL GAIN AND DOES NOT
|
||||
INCLUDE THE FMOD LIBRARY FOR RESALE, LICENSE OR OTHER COMMERCIAL
|
||||
DISTRIBUTION, THEN USE OF FMOD IS FREE OF CHARGE. THERE ARE NO
|
||||
LICENSE FEES FOR NON-COMMERCIAL APPLICATIONS.
|
||||
THE USER MAY USE THIS EULA AS EVIDENCE OF THEIR LICENSE WITHOUT
|
||||
CONTACTING FIRELIGHT TECHNOLOGIES.
|
||||
|
||||
CONDITIONS/LIMITATIONS:
|
||||
- WHEN USING THIS LICENSE, THE FMOD LIBRARY CANNOT BE USED FOR
|
||||
RESALE OR OTHER COMMERCIAL DISTRIBUTION
|
||||
- THIS LICENSE CANNOT BE USED FOR PRODUCTS WHICH DO NOT MAKE
|
||||
PROFIT BUT ARE STILL COMMERCIALLY RELEASED
|
||||
- THIS LICENSE CANNOT BE USED FOR COMMERCIAL SERVICES, WHERE THE
|
||||
EXECUTABLE CONTAINING FMOD IS NOT SOLD, BUT THE DATA IS.
|
||||
- WHEN USING FMOD, A CREDIT LINE IS REQUIRED IN EITHER DOCUMENTATION,
|
||||
OR 'ON SCREEN' FORMAT (IF POSSIBLE). IT SHOULD CONTAIN AT LEAST
|
||||
THE WORDS "FMOD" (OR "FMOD STUDIO" IF APPLICABLE) AND
|
||||
"FIRELIGHT TECHNOLOGIES."
|
||||
LOGOS ARE AVAILABLE FOR BOX OR MANUAL ART, BUT ARE NOT MANDATORY.
|
||||
AN EXAMPLE CREDIT COULD BE:
|
||||
|
||||
FMOD Sound System, copyright © Firelight Technologies Pty, Ltd., 1994-2016.
|
||||
OR
|
||||
FMOD Studio, copyright © Firelight Technologies Pty, Ltd., 1994-2016.
|
||||
OR
|
||||
Audio Engine supplied by FMOD by Firelight Technologies.
|
||||
|
||||
NOTE THIS IN ADVANCE, AS IT MUST BE DONE BEFORE SHIPPING YOUR
|
||||
PRODUCT WITH FMOD.
|
||||
|
||||
FMOD FREE FOR INDIES LICENSE (FMOD STUDIO ONLY)
|
||||
------------------------------------------------
|
||||
INDIE DEVELOPERS ARE CONSIDERED BY OUR LICENSING MODEL, DEVELOPERS THAT DEVELOP
|
||||
A TITLE FOR UNDER $100K USD (TYPICALLY CONSIDERED AN 'INDIE' TITLE) TOTAL
|
||||
BUDGET, MEANING YOUR TOTAL COSTS ARE LESS THAN $100K USD AT TIME OF SHIPPING,
|
||||
YOU CAN USE FMOD FOR FREE.
|
||||
|
||||
CONDITIONS/LIMITATIONS
|
||||
- PLEASE WRITE TO SALES@FMOD.COM WITH THE NAME OF YOUR TITLE, RELEASE DATE
|
||||
AND PLATFORMS SO WE CAN REGISTER YOU IN OUR SYSTEM.
|
||||
- THERE IS NO RESTRICTION ON PLATFORM, ANY PLATFORM COMBINATION MAY BE USED.
|
||||
- INCOME IS NOT RELEVANT TO THE BUDGET LEVEL, IT MUST BE EXPENSE RELATED.
|
||||
- WHEN USING FMOD, A CREDIT LINE IS REQUIRED IN EITHER DOCUMENTATION,
|
||||
OR 'ON SCREEN' FORMAT (IF POSSIBLE). IT SHOULD CONTAIN AT LEAST
|
||||
THE WORDS FMOD STUDIO AND FIRELIGHT TECHNOLOGIES.
|
||||
LOGOS ARE AVAILABLE FOR BOX OR MANUAL ART, BUT ARE NOT MANDATORY.
|
||||
AN EXAMPLE CREDIT COULD BE:
|
||||
|
||||
FMOD STUDIO, COPYRIGHT © FIRELIGHT TECHNOLOGIES PTY, LTD., 1994-2016.
|
||||
|
||||
COMMERCIAL USAGE (FMOD EX AND FMOD STUDIO)
|
||||
------------------------------------------
|
||||
IF THE PRODUCT THAT USES FMOD IS INTENDED TO GENERATE INCOME, VIA DIRECT SALES
|
||||
OR INDIRECT REVENUE (SUCH AS ADVERTISING, DONATIONS, CONTRACT FEE) THEN THE
|
||||
DEVELOPER MUST APPLY TO FIRELIGHT TECHNOLOGIES FOR A COMMERCIAL LICENSE (UNLESS
|
||||
THE USER QUALIFIES FOR AN FMOD STUDIO 'INDIE LICENSE').
|
||||
TO APPLY FOR THIS LICENSE WRITE TO SALES@FMOD.COM WITH THE RELEVANT DETAILS.
|
||||
|
||||
REDISTRIBUTION LICENSE (FMOD EX AND FMOD STUDIO)
|
||||
------------------------------------------------
|
||||
IF THE USER WISHES TO REDISTRIBUTE FMOD AS PART OF AN ENGINE OR TOOL SOLUTION,
|
||||
THE USER MUST APPLY TO FIRELIGHT TECHNOLOGIES TO BE GRANTED A 'REDISTRIBUTION
|
||||
LICENSE'.
|
||||
TO APPLY FOR THIS LICENSE WRITE TO SALES@FMOD.COM WITH THE RELEVANT DETAILS.
|
||||
|
||||
WARRANTY AND LIMITATION OF LIABILITY
|
||||
------------------------------------
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
FMOD Uses Ogg Vorbis codec. BSD license.
|
||||
-----------------------------------------
|
||||
Copyright (c) 2002, Xiph.org Foundation
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
- Neither the name of the Xiph.org Foundation nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
For Android platform code.
|
||||
--------------------------
|
||||
Copyright (C) 2010 The Android Open Source Project
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
Binary file not shown.
Binary file not shown.
@@ -1,19 +0,0 @@
|
||||
Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
@@ -1,22 +0,0 @@
|
||||
crunch/crnlib uses the ZLIB license:
|
||||
http://opensource.org/licenses/Zlib
|
||||
|
||||
Copyright (c) 2010-2016 Richard Geldreich, Jr. and Binomial LLC
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
@@ -1,13 +0,0 @@
|
||||
Copyright (c) 2015 Harm Hanemaaijer <fgenfb@yahoo.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user