Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1766dcbdeb | |||
| ef38471ff1 | |||
| 217a7993e9 | |||
| 0a41615763 | |||
| 9d34f668d5 | |||
| 9269a36725 | |||
| 813e8b10a6 | |||
| 84c75fadf5 | |||
| c76e41b1ab | |||
| fefeea5f35 | |||
| 4a81c461e8 | |||
| b10d03d50d | |||
| da98a0c5b8 | |||
| 76d17bacf5 | |||
| 6678ce082b | |||
| 07074b3deb | |||
| df5d9f90d4 | |||
| 4f2d30552a | |||
| d259c7a5cd | |||
| c71ceb7ea6 | |||
| 85cf134a49 | |||
| 687b1d3a0d |
@@ -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,123 @@
|
|||||||
|
using System;
|
||||||
|
using System.ComponentModel;
|
||||||
|
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 = new Uri(typeof(DllLoader).Assembly.CodeBase).LocalPath;
|
||||||
|
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;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
+106
-36
@@ -5,62 +5,132 @@ VisualStudioVersion = 16.0.29920.165
|
|||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AssetStudio", "AssetStudio\AssetStudio.csproj", "{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AssetStudio", "AssetStudio\AssetStudio.csproj", "{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AssetStudioFBX", "AssetStudioFBX\AssetStudioFBX.vcxproj", "{B82DD1BA-4EEC-4F29-A686-03D7F0DF39B8}"
|
|
||||||
EndProject
|
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Texture2DDecoder", "Texture2DDecoder\Texture2DDecoder.vcxproj", "{BEC7B5E6-0A7B-4824-97A7-EEA04D9EBA29}"
|
|
||||||
EndProject
|
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AssetStudioUtility", "AssetStudioUtility\AssetStudioUtility.csproj", "{80AEC261-21EE-4E4F-A93B-7A744DC84888}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AssetStudioUtility", "AssetStudioUtility\AssetStudioUtility.csproj", "{80AEC261-21EE-4E4F-A93B-7A744DC84888}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AssetStudioGUI", "AssetStudioGUI\AssetStudioGUI.csproj", "{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AssetStudioGUI", "AssetStudioGUI\AssetStudioGUI.csproj", "{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}"
|
||||||
EndProject
|
EndProject
|
||||||
|
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
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
Debug|x64 = Debug|x64
|
Debug|x64 = Debug|x64
|
||||||
Debug|x86 = Debug|x86
|
Debug|x86 = Debug|x86
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
Release|x64 = Release|x64
|
Release|x64 = Release|x64
|
||||||
Release|x86 = Release|x86
|
Release|x86 = Release|x86
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{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.ActiveCfg = Debug|Any CPU
|
||||||
{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}.Debug|x64.Build.0 = 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.ActiveCfg = Debug|Any CPU
|
||||||
{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}.Debug|x86.Build.0 = 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.ActiveCfg = Release|Any CPU
|
||||||
{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}.Release|x64.Build.0 = 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.ActiveCfg = Release|Any CPU
|
||||||
{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}.Release|x86.Build.0 = Release|Any CPU
|
{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}.Release|x86.Build.0 = Release|Any CPU
|
||||||
{B82DD1BA-4EEC-4F29-A686-03D7F0DF39B8}.Debug|x64.ActiveCfg = Debug|x64
|
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{B82DD1BA-4EEC-4F29-A686-03D7F0DF39B8}.Debug|x64.Build.0 = Debug|x64
|
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{B82DD1BA-4EEC-4F29-A686-03D7F0DF39B8}.Debug|x86.ActiveCfg = Debug|Win32
|
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
{B82DD1BA-4EEC-4F29-A686-03D7F0DF39B8}.Debug|x86.Build.0 = Debug|Win32
|
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
{B82DD1BA-4EEC-4F29-A686-03D7F0DF39B8}.Release|x64.ActiveCfg = Release|x64
|
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
{B82DD1BA-4EEC-4F29-A686-03D7F0DF39B8}.Release|x64.Build.0 = Release|x64
|
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
{B82DD1BA-4EEC-4F29-A686-03D7F0DF39B8}.Release|x86.ActiveCfg = Release|Win32
|
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{B82DD1BA-4EEC-4F29-A686-03D7F0DF39B8}.Release|x86.Build.0 = Release|Win32
|
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{BEC7B5E6-0A7B-4824-97A7-EEA04D9EBA29}.Debug|x64.ActiveCfg = Debug|x64
|
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
{BEC7B5E6-0A7B-4824-97A7-EEA04D9EBA29}.Debug|x64.Build.0 = Debug|x64
|
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Release|x64.Build.0 = Release|Any CPU
|
||||||
{BEC7B5E6-0A7B-4824-97A7-EEA04D9EBA29}.Debug|x86.ActiveCfg = Debug|Win32
|
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
{BEC7B5E6-0A7B-4824-97A7-EEA04D9EBA29}.Debug|x86.Build.0 = Debug|Win32
|
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Release|x86.Build.0 = Release|Any CPU
|
||||||
{BEC7B5E6-0A7B-4824-97A7-EEA04D9EBA29}.Release|x64.ActiveCfg = Release|x64
|
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{BEC7B5E6-0A7B-4824-97A7-EEA04D9EBA29}.Release|x64.Build.0 = Release|x64
|
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{BEC7B5E6-0A7B-4824-97A7-EEA04D9EBA29}.Release|x86.ActiveCfg = Release|Win32
|
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
{BEC7B5E6-0A7B-4824-97A7-EEA04D9EBA29}.Release|x86.Build.0 = Release|Win32
|
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Debug|x64.ActiveCfg = Debug|x64
|
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Debug|x64.Build.0 = Debug|x64
|
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Debug|x86.ActiveCfg = Debug|x86
|
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Debug|x86.Build.0 = Debug|x86
|
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Release|x64.ActiveCfg = Release|x64
|
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Release|x64.Build.0 = Release|x64
|
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Release|x64.Build.0 = Release|Any CPU
|
||||||
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Release|x86.ActiveCfg = Release|x86
|
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Release|x86.Build.0 = Release|x86
|
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Release|x86.Build.0 = Release|Any CPU
|
||||||
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Debug|x64.ActiveCfg = Debug|x64
|
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||||
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Debug|x64.Build.0 = Debug|x64
|
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Debug|Any CPU.Build.0 = Debug|Win32
|
||||||
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Debug|x86.ActiveCfg = Debug|x86
|
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Debug|x86.Build.0 = Debug|x86
|
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Debug|x64.Build.0 = Debug|x64
|
||||||
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Release|x64.ActiveCfg = Release|x64
|
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Release|x64.Build.0 = Release|x64
|
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Debug|x86.Build.0 = Debug|Win32
|
||||||
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Release|x86.ActiveCfg = Release|x86
|
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||||
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Release|x86.Build.0 = Release|x86
|
{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
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|||||||
@@ -144,6 +144,7 @@
|
|||||||
<Compile Include="SerializedFileHeader.cs" />
|
<Compile Include="SerializedFileHeader.cs" />
|
||||||
<Compile Include="SerializedType.cs" />
|
<Compile Include="SerializedType.cs" />
|
||||||
<Compile Include="SevenZipHelper.cs" />
|
<Compile Include="SevenZipHelper.cs" />
|
||||||
|
<Compile Include="StreamFile.cs" />
|
||||||
<Compile Include="TypeTreeHelper.cs" />
|
<Compile Include="TypeTreeHelper.cs" />
|
||||||
<Compile Include="TypeTreeNode.cs" />
|
<Compile Include="TypeTreeNode.cs" />
|
||||||
<Compile Include="UType.cs" />
|
<Compile Include="UType.cs" />
|
||||||
|
|||||||
@@ -157,7 +157,7 @@ namespace AssetStudio
|
|||||||
if (SerializedFile.IsSerializedFile(subReader))
|
if (SerializedFile.IsSerializedFile(subReader))
|
||||||
{
|
{
|
||||||
var dummyPath = Path.GetDirectoryName(fullName) + Path.DirectorySeparatorChar + file.fileName;
|
var dummyPath = Path.GetDirectoryName(fullName) + Path.DirectorySeparatorChar + file.fileName;
|
||||||
LoadAssetsFromMemory(dummyPath, subReader, parentPath ?? fullName, bundleFile.versionEngine);
|
LoadAssetsFromMemory(dummyPath, subReader, parentPath ?? fullName, bundleFile.m_Header.unityRevision);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
+255
-197
@@ -1,248 +1,306 @@
|
|||||||
using System.Collections.Generic;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Lz4;
|
using Lz4;
|
||||||
|
|
||||||
namespace AssetStudio
|
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
|
public class BundleFile
|
||||||
{
|
{
|
||||||
private string path;
|
public class Header
|
||||||
public string versionPlayer;
|
|
||||||
public string versionEngine;
|
|
||||||
public List<StreamFile> fileList = new List<StreamFile>();
|
|
||||||
|
|
||||||
public BundleFile(EndianBinaryReader bundleReader, string path)
|
|
||||||
{
|
{
|
||||||
this.path = path;
|
public string signature;
|
||||||
var signature = bundleReader.ReadStringToNull();
|
public uint version;
|
||||||
switch (signature)
|
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();
|
||||||
|
switch (m_Header.signature)
|
||||||
{
|
{
|
||||||
|
case "UnityArchive":
|
||||||
|
break; //TODO
|
||||||
case "UnityWeb":
|
case "UnityWeb":
|
||||||
case "UnityRaw":
|
case "UnityRaw":
|
||||||
case "\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA":
|
ReadHeaderAndBlocksInfo(reader);
|
||||||
|
using (var blocksStream = CreateBlocksStream(path))
|
||||||
{
|
{
|
||||||
var format = bundleReader.ReadInt32();
|
ReadBlocksAndDirectory(reader, blocksStream);
|
||||||
versionPlayer = bundleReader.ReadStringToNull();
|
ReadFiles(blocksStream, path);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
case "UnityFS":
|
case "UnityFS":
|
||||||
|
ReadHeader(reader);
|
||||||
|
ReadBlocksInfoAndDirectory(reader);
|
||||||
|
using (var blocksStream = CreateBlocksStream(path))
|
||||||
{
|
{
|
||||||
var format = bundleReader.ReadInt32();
|
ReadBlocks(reader, blocksStream);
|
||||||
versionPlayer = bundleReader.ReadStringToNull();
|
ReadFiles(blocksStream, path);
|
||||||
versionEngine = bundleReader.ReadStringToNull();
|
|
||||||
if (format == 6)
|
|
||||||
{
|
|
||||||
ReadFormat6(bundleReader);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GetAssetsFiles(EndianBinaryReader reader, int offset)
|
private void ReadHeaderAndBlocksInfo(EndianBinaryReader reader)
|
||||||
{
|
{
|
||||||
int fileCount = reader.ReadInt32();
|
var isCompressed = m_Header.signature == "UnityWeb";
|
||||||
for (int i = 0; i < fileCount; i++)
|
m_Header.version = reader.ReadUInt32();
|
||||||
|
m_Header.unityVersion = reader.ReadStringToNull();
|
||||||
|
m_Header.unityRevision = reader.ReadStringToNull();
|
||||||
|
if (m_Header.version >= 4)
|
||||||
{
|
{
|
||||||
var file = new StreamFile();
|
var hash = reader.ReadBytes(16);
|
||||||
file.fileName = Path.GetFileName(reader.ReadStringToNull());
|
var crc = reader.ReadUInt32();
|
||||||
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 minimumStreamedBytes = reader.ReadUInt32();
|
||||||
|
var headerSize = 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 = headerSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ReadFormat6(EndianBinaryReader bundleReader, bool padding = false)
|
private Stream CreateBlocksStream(string path)
|
||||||
{
|
{
|
||||||
var bundleSize = bundleReader.ReadInt64();
|
Stream blocksStream;
|
||||||
int compressedSize = bundleReader.ReadInt32();
|
var uncompressedSizeSum = m_BlocksInfo.Sum(x => x.uncompressedSize);
|
||||||
int uncompressedSize = bundleReader.ReadInt32();
|
if (uncompressedSizeSum >= int.MaxValue)
|
||||||
int flag = bundleReader.ReadInt32();
|
|
||||||
if (padding)
|
|
||||||
bundleReader.ReadByte();
|
|
||||||
byte[] blocksInfoBytes;
|
|
||||||
if ((flag & 0x80) != 0)//at end of file
|
|
||||||
{
|
{
|
||||||
var position = bundleReader.Position;
|
/*var memoryMappedFile = MemoryMappedFile.CreateNew(Path.GetFileName(path), uncompressedSizeSum);
|
||||||
bundleReader.Position = bundleReader.BaseStream.Length - compressedSize;
|
assetsDataStream = memoryMappedFile.CreateViewStream();*/
|
||||||
blocksInfoBytes = bundleReader.ReadBytes(compressedSize);
|
blocksStream = new FileStream(path + ".temp", FileMode.Create, FileAccess.ReadWrite, FileShare.None, 4096, FileOptions.DeleteOnClose);
|
||||||
bundleReader.Position = position;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
blocksInfoBytes = bundleReader.ReadBytes(compressedSize);
|
blocksStream = new MemoryStream((int)uncompressedSizeSum);
|
||||||
}
|
}
|
||||||
var blocksInfoCompressedStream = new MemoryStream(blocksInfoBytes);
|
return blocksStream;
|
||||||
MemoryStream blocksInfoDecompressedStream;
|
}
|
||||||
switch (flag & 0x3F)
|
|
||||||
|
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))
|
||||||
{
|
{
|
||||||
blocksInfoDecompressedStream = blocksInfoCompressedStream;
|
using (var decompressStream = SevenZipHelper.StreamDecompress(memoryStream))
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 1://LZMA
|
|
||||||
{
|
|
||||||
blocksInfoDecompressedStream = SevenZipHelper.StreamDecompress(blocksInfoCompressedStream);
|
|
||||||
blocksInfoCompressedStream.Close();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 2://LZ4
|
|
||||||
case 3://LZ4HC
|
|
||||||
{
|
|
||||||
byte[] uncompressedBytes = new byte[uncompressedSize];
|
|
||||||
using (var decoder = new Lz4DecoderStream(blocksInfoCompressedStream))
|
|
||||||
{
|
{
|
||||||
decoder.Read(uncompressedBytes, 0, uncompressedSize);
|
uncompressedBytes = decompressStream.ToArray();
|
||||||
}
|
}
|
||||||
blocksInfoDecompressedStream = new MemoryStream(uncompressedBytes);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
//case 4:LZHAM?
|
|
||||||
}
|
|
||||||
using (var blocksInfoReader = new EndianBinaryReader(blocksInfoDecompressedStream))
|
|
||||||
{
|
|
||||||
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;
|
blocksStream.Write(uncompressedBytes, 0, uncompressedBytes.Length);
|
||||||
var uncompressedSizeSum = blockInfos.Sum(x => x.uncompressedSize);
|
}
|
||||||
if (uncompressedSizeSum > int.MaxValue)
|
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);
|
path = blocksReader.ReadStringToNull(),
|
||||||
assetsDataStream = memoryMappedFile.CreateViewStream();*/
|
offset = blocksReader.ReadUInt32(),
|
||||||
dataStream = new FileStream(path + ".temp", FileMode.Create, FileAccess.ReadWrite, FileShare.None, 4096, FileOptions.DeleteOnClose);
|
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.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 = File.Create(extractPath + file.fileName);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
dataStream = new MemoryStream((int)uncompressedSizeSum);
|
file.stream = new MemoryStream((int)node.size);
|
||||||
}
|
}
|
||||||
foreach (var blockInfo in blockInfos)
|
blocksStream.Position = node.offset;
|
||||||
|
blocksStream.CopyTo(file.stream, node.size);
|
||||||
|
file.stream.Position = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ReadHeader(EndianBinaryReader reader)
|
||||||
|
{
|
||||||
|
m_Header.version = reader.ReadUInt32();
|
||||||
|
m_Header.unityVersion = reader.ReadStringToNull();
|
||||||
|
m_Header.unityRevision = reader.ReadStringToNull();
|
||||||
|
m_Header.size = reader.ReadInt64();
|
||||||
|
m_Header.compressedBlocksInfoSize = reader.ReadUInt32();
|
||||||
|
m_Header.uncompressedBlocksInfoSize = reader.ReadUInt32();
|
||||||
|
m_Header.flags = reader.ReadUInt32();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ReadBlocksInfoAndDirectory(EndianBinaryReader reader)
|
||||||
|
{
|
||||||
|
byte[] blocksInfoBytes;
|
||||||
|
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
|
||||||
|
{
|
||||||
|
if (m_Header.version >= 7)
|
||||||
{
|
{
|
||||||
switch (blockInfo.flag & 0x3F)
|
reader.AlignStream(16);
|
||||||
{
|
|
||||||
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?
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
dataStream.Position = 0;
|
blocksInfoBytes = reader.ReadBytes((int)m_Header.compressedBlocksInfoSize);
|
||||||
using (dataStream)
|
}
|
||||||
{
|
var blocksInfoCompressedStream = new MemoryStream(blocksInfoBytes);
|
||||||
var entryinfo_count = blocksInfoReader.ReadInt32();
|
MemoryStream blocksInfoUncompresseddStream;
|
||||||
for (int i = 0; i < entryinfo_count; i++)
|
switch (m_Header.flags & 0x3F) //kArchiveCompressionTypeMask
|
||||||
|
{
|
||||||
|
default: //None
|
||||||
{
|
{
|
||||||
var file = new StreamFile();
|
blocksInfoUncompresseddStream = blocksInfoCompressedStream;
|
||||||
var entryinfo_offset = blocksInfoReader.ReadInt64();
|
break;
|
||||||
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((int)entryinfo_size);
|
|
||||||
}
|
|
||||||
dataStream.Position = entryinfo_offset;
|
|
||||||
dataStream.CopyTo(file.stream, entryinfo_size);
|
|
||||||
file.stream.Position = 0;
|
|
||||||
fileList.Add(file);
|
|
||||||
}
|
}
|
||||||
|
case 1: //LZMA
|
||||||
|
{
|
||||||
|
blocksInfoUncompresseddStream = SevenZipHelper.StreamDecompress(blocksInfoCompressedStream);
|
||||||
|
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()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
var nodesCount = blocksInfoReader.ReadInt32();
|
||||||
|
m_DirectoryInfo = new Node[nodesCount];
|
||||||
|
for (int i = 0; i < nodesCount; i++)
|
||||||
|
{
|
||||||
|
m_DirectoryInfo[i] = new Node
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+93
-36
@@ -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 class SubMesh
|
||||||
{
|
{
|
||||||
public uint firstByte;
|
public uint firstByte;
|
||||||
public uint indexCount;
|
public uint indexCount;
|
||||||
public int topology;
|
public GfxPrimitiveType topology;
|
||||||
public uint triangleCount;
|
public uint triangleCount;
|
||||||
public uint baseVertex;
|
public uint baseVertex;
|
||||||
public uint firstVertex;
|
public uint firstVertex;
|
||||||
@@ -413,7 +423,7 @@ namespace AssetStudio
|
|||||||
|
|
||||||
firstByte = reader.ReadUInt32();
|
firstByte = reader.ReadUInt32();
|
||||||
indexCount = reader.ReadUInt32();
|
indexCount = reader.ReadUInt32();
|
||||||
topology = reader.ReadInt32();
|
topology = (GfxPrimitiveType)reader.ReadInt32();
|
||||||
|
|
||||||
if (version[0] < 4) //4.0 down
|
if (version[0] < 4) //4.0 down
|
||||||
{
|
{
|
||||||
@@ -460,7 +470,7 @@ namespace AssetStudio
|
|||||||
private CompressedMesh m_CompressedMesh;
|
private CompressedMesh m_CompressedMesh;
|
||||||
private StreamingInfo m_StreamData;
|
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)
|
public Mesh(ObjectReader reader) : base(reader)
|
||||||
{
|
{
|
||||||
@@ -684,7 +694,7 @@ namespace AssetStudio
|
|||||||
DecompressCompressedMesh();
|
DecompressCompressedMesh();
|
||||||
}
|
}
|
||||||
|
|
||||||
BuildFaces();
|
GetTriangles();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ReadVertexData()
|
private void ReadVertexData()
|
||||||
@@ -1037,7 +1047,7 @@ namespace AssetStudio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void BuildFaces()
|
private void GetTriangles()
|
||||||
{
|
{
|
||||||
foreach (var m_SubMesh in m_SubMeshes)
|
foreach (var m_SubMesh in m_SubMeshes)
|
||||||
{
|
{
|
||||||
@@ -1046,43 +1056,65 @@ namespace AssetStudio
|
|||||||
{
|
{
|
||||||
firstIndex /= 2;
|
firstIndex /= 2;
|
||||||
}
|
}
|
||||||
|
var indexCount = m_SubMesh.indexCount;
|
||||||
if (m_SubMesh.topology == 0)
|
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]);
|
||||||
m_Indices.Add(m_IndexBuffer[firstIndex + i * 3 + 1]);
|
m_Indices.Add(m_IndexBuffer[firstIndex + i + 1]);
|
||||||
m_Indices.Add(m_IndexBuffer[firstIndex + i * 3 + 2]);
|
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
|
else
|
||||||
{
|
{
|
||||||
uint j = 0;
|
throw new NotSupportedException("Failed getting triangles. Submesh topology is lines or points.");
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1128,6 +1160,31 @@ namespace AssetStudio
|
|||||||
throw new ArgumentOutOfRangeException();
|
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 class MeshHelper
|
||||||
|
|||||||
@@ -112,7 +112,8 @@ namespace AssetStudio
|
|||||||
{1083, "BoundsInt"},
|
{1083, "BoundsInt"},
|
||||||
{1093, "m_CorrespondingSourceObject"},
|
{1093, "m_CorrespondingSourceObject"},
|
||||||
{1121, "m_PrefabInstance"},
|
{1121, "m_PrefabInstance"},
|
||||||
{1138, "m_PrefabAsset"}
|
{1138, "m_PrefabAsset"},
|
||||||
|
{1152, "FileSize"}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ namespace AssetStudio
|
|||||||
public List<ImportedSubmesh> SubmeshList { get; set; }
|
public List<ImportedSubmesh> SubmeshList { get; set; }
|
||||||
public List<ImportedBone> BoneList { get; set; }
|
public List<ImportedBone> BoneList { get; set; }
|
||||||
public bool hasNormal { get; set; }
|
public bool hasNormal { get; set; }
|
||||||
public bool hasUV { get; set; }
|
public bool[] hasUV { get; set; }
|
||||||
public bool hasTangent { get; set; }
|
public bool hasTangent { get; set; }
|
||||||
public bool hasColor { get; set; }
|
public bool hasColor { get; set; }
|
||||||
}
|
}
|
||||||
@@ -151,7 +151,7 @@ namespace AssetStudio
|
|||||||
{
|
{
|
||||||
public Vector3 Vertex { get; set; }
|
public Vector3 Vertex { get; set; }
|
||||||
public Vector3 Normal { get; set; }
|
public Vector3 Normal { get; set; }
|
||||||
public float[] UV { get; set; }
|
public float[][] UV { get; set; }
|
||||||
public Vector4 Tangent { get; set; }
|
public Vector4 Tangent { get; set; }
|
||||||
public Color Color { get; set; }
|
public Color Color { get; set; }
|
||||||
public float[] Weights { get; set; }
|
public float[] Weights { get; set; }
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ namespace AssetStudio
|
|||||||
{
|
{
|
||||||
case "UnityWeb":
|
case "UnityWeb":
|
||||||
case "UnityRaw":
|
case "UnityRaw":
|
||||||
case "\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA":
|
case "UnityArchive":
|
||||||
case "UnityFS":
|
case "UnityFS":
|
||||||
return FileType.BundleFile;
|
return FileType.BundleFile;
|
||||||
case "UnityWebData1.0":
|
case "UnityWebData1.0":
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ namespace AssetStudio
|
|||||||
public BuildTarget m_TargetPlatform = BuildTarget.UnknownPlatform;
|
public BuildTarget m_TargetPlatform = BuildTarget.UnknownPlatform;
|
||||||
private bool m_EnableTypeTree = true;
|
private bool m_EnableTypeTree = true;
|
||||||
public List<SerializedType> m_Types;
|
public List<SerializedType> m_Types;
|
||||||
|
public List<SerializedType> m_RefTypes;
|
||||||
public List<ObjectInfo> m_Objects;
|
public List<ObjectInfo> m_Objects;
|
||||||
private List<LocalSerializedObjectIdentifier> m_ScriptTypes;
|
private List<LocalSerializedObjectIdentifier> m_ScriptTypes;
|
||||||
public List<FileIdentifier> m_Externals;
|
public List<FileIdentifier> m_Externals;
|
||||||
@@ -93,9 +94,10 @@ namespace AssetStudio
|
|||||||
m_Types.Add(ReadSerializedType());
|
m_Types.Add(ReadSerializedType());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var bigIDEnabled = 0;
|
||||||
if (header.m_Version >= 7 && header.m_Version < 14)
|
if (header.m_Version >= 7 && header.m_Version < 14)
|
||||||
{
|
{
|
||||||
var bigIDEnabled = reader.ReadInt32();
|
bigIDEnabled = reader.ReadInt32();
|
||||||
}
|
}
|
||||||
|
|
||||||
//ReadObjects
|
//ReadObjects
|
||||||
@@ -106,7 +108,11 @@ namespace AssetStudio
|
|||||||
for (int i = 0; i < objectCount; i++)
|
for (int i = 0; i < objectCount; i++)
|
||||||
{
|
{
|
||||||
var objectInfo = new ObjectInfo();
|
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();
|
objectInfo.m_PathID = reader.ReadInt32();
|
||||||
}
|
}
|
||||||
@@ -128,7 +134,6 @@ namespace AssetStudio
|
|||||||
{
|
{
|
||||||
objectInfo.classID = reader.ReadUInt16();
|
objectInfo.classID = reader.ReadUInt16();
|
||||||
objectInfo.serializedType = m_Types.Find(x => x.classID == objectInfo.typeID);
|
objectInfo.serializedType = m_Types.Find(x => x.classID == objectInfo.typeID);
|
||||||
var isDestroyed = reader.ReadUInt16();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -136,6 +141,16 @@ namespace AssetStudio
|
|||||||
objectInfo.serializedType = type;
|
objectInfo.serializedType = type;
|
||||||
objectInfo.classID = type.classID;
|
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)
|
if (header.m_Version == 15 || header.m_Version == 16)
|
||||||
{
|
{
|
||||||
var stripped = reader.ReadByte();
|
var stripped = reader.ReadByte();
|
||||||
@@ -183,15 +198,22 @@ namespace AssetStudio
|
|||||||
m_Externals.Add(m_External);
|
m_Externals.Add(m_External);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (header.m_Version >= 5)
|
if (header.m_Version >= 20)
|
||||||
{
|
{
|
||||||
//var userInformation = reader.ReadStringToNull();
|
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 >= 21)
|
if (header.m_Version >= 5)
|
||||||
{
|
{
|
||||||
//var unknown = reader.ReadInt32();
|
var userInformation = reader.ReadStringToNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//reader.AlignStream(16);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetVersion(string stringVersion)
|
public void SetVersion(string stringVersion)
|
||||||
@@ -233,13 +255,18 @@ namespace AssetStudio
|
|||||||
var typeTree = new List<TypeTreeNode>();
|
var typeTree = new List<TypeTreeNode>();
|
||||||
if (header.m_Version >= 12 || header.m_Version == 10)
|
if (header.m_Version >= 12 || header.m_Version == 10)
|
||||||
{
|
{
|
||||||
ReadTypeTree5(typeTree);
|
TypeTreeBlobRead(typeTree);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ReadTypeTree(typeTree);
|
ReadTypeTree(typeTree);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (header.m_Version >= 21)
|
||||||
|
{
|
||||||
|
type.m_TypeDependencies = reader.ReadInt32Array();
|
||||||
|
}
|
||||||
|
|
||||||
type.m_Nodes = typeTree;
|
type.m_Nodes = typeTree;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -276,47 +303,39 @@ namespace AssetStudio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ReadTypeTree5(List<TypeTreeNode> typeTree)
|
private void TypeTreeBlobRead(List<TypeTreeNode> typeTree)
|
||||||
{
|
{
|
||||||
int numberOfNodes = reader.ReadInt32();
|
int numberOfNodes = reader.ReadInt32();
|
||||||
int stringBufferSize = reader.ReadInt32();
|
int stringBufferSize = reader.ReadInt32();
|
||||||
|
for (int i = 0; i < numberOfNodes; i++)
|
||||||
var nodeSize = 24;
|
|
||||||
if (header.m_Version > 17)
|
|
||||||
{
|
{
|
||||||
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;
|
var m_StringBuffer = reader.ReadBytes(stringBufferSize);
|
||||||
using (var stringBufferReader = new BinaryReader(new MemoryStream(reader.ReadBytes(stringBufferSize))))
|
|
||||||
|
using (var stringBufferReader = new BinaryReader(new MemoryStream(m_StringBuffer)))
|
||||||
{
|
{
|
||||||
reader.Position -= numberOfNodes * nodeSize + stringBufferSize;
|
|
||||||
for (int i = 0; i < numberOfNodes; i++)
|
for (int i = 0; i < numberOfNodes; i++)
|
||||||
{
|
{
|
||||||
var typeTreeNode = new TypeTreeNode();
|
var typeTreeNode = typeTree[i];
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
typeTreeNode.m_Type = ReadString(stringBufferReader, typeTreeNode.m_TypeStrOffset);
|
typeTreeNode.m_Type = ReadString(stringBufferReader, typeTreeNode.m_TypeStrOffset);
|
||||||
typeTreeNode.m_Name = ReadString(stringBufferReader, typeTreeNode.m_NameStrOffset);
|
typeTreeNode.m_Name = ReadString(stringBufferReader, typeTreeNode.m_NameStrOffset);
|
||||||
}
|
}
|
||||||
reader.Position += stringBufferSize;
|
|
||||||
}
|
|
||||||
if (header.m_Version >= 21)
|
|
||||||
{
|
|
||||||
reader.Position += 4;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
string ReadString(BinaryReader stringBufferReader, uint value)
|
string ReadString(BinaryReader stringBufferReader, uint value)
|
||||||
{
|
{
|
||||||
var isOffset = (value & 0x80000000) == 0;
|
var isOffset = (value & 0x80000000) == 0;
|
||||||
@@ -343,19 +362,31 @@ namespace AssetStudio
|
|||||||
public static bool IsSerializedFile(EndianBinaryReader reader)
|
public static bool IsSerializedFile(EndianBinaryReader reader)
|
||||||
{
|
{
|
||||||
var fileSize = reader.BaseStream.Length;
|
var fileSize = reader.BaseStream.Length;
|
||||||
if (fileSize < 16)
|
if (fileSize < 20)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
var m_MetadataSize = reader.ReadUInt32();
|
var m_MetadataSize = reader.ReadUInt32();
|
||||||
var m_FileSize = 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)
|
if (m_FileSize != fileSize)
|
||||||
{
|
{
|
||||||
reader.Position = 0;
|
reader.Position = 0;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
var m_Version = reader.ReadUInt32();
|
|
||||||
var m_DataOffset = reader.ReadUInt32();
|
|
||||||
if (m_DataOffset > fileSize)
|
if (m_DataOffset > fileSize)
|
||||||
{
|
{
|
||||||
reader.Position = 0;
|
reader.Position = 0;
|
||||||
|
|||||||
@@ -13,5 +13,6 @@ namespace AssetStudio
|
|||||||
public List<TypeTreeNode> m_Nodes;
|
public List<TypeTreeNode> m_Nodes;
|
||||||
public byte[] m_ScriptID; //Hash128
|
public byte[] m_ScriptID; //Hash128
|
||||||
public byte[] m_OldTypeHash; //Hash128
|
public byte[] m_OldTypeHash; //Hash128
|
||||||
|
public int[] m_TypeDependencies;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace AssetStudio
|
||||||
|
{
|
||||||
|
public class StreamFile
|
||||||
|
{
|
||||||
|
public string fileName;
|
||||||
|
public Stream stream;
|
||||||
|
}
|
||||||
|
}
|
||||||
+50
-188
@@ -31,6 +31,7 @@ namespace AssetStudio
|
|||||||
value = reader.ReadSByte();
|
value = reader.ReadSByte();
|
||||||
break;
|
break;
|
||||||
case "UInt8":
|
case "UInt8":
|
||||||
|
case "char":
|
||||||
value = reader.ReadByte();
|
value = reader.ReadByte();
|
||||||
break;
|
break;
|
||||||
case "short":
|
case "short":
|
||||||
@@ -56,6 +57,7 @@ namespace AssetStudio
|
|||||||
break;
|
break;
|
||||||
case "UInt64":
|
case "UInt64":
|
||||||
case "unsigned long long":
|
case "unsigned long long":
|
||||||
|
case "FileSize":
|
||||||
value = reader.ReadUInt64();
|
value = reader.ReadUInt64();
|
||||||
break;
|
break;
|
||||||
case "float":
|
case "float":
|
||||||
@@ -73,26 +75,6 @@ namespace AssetStudio
|
|||||||
sb.AppendFormat("{0}{1} {2} = \"{3}\"\r\n", (new string('\t', level)), varTypeStr, varNameStr, str);
|
sb.AppendFormat("{0}{1} {2} = \"{3}\"\r\n", (new string('\t', level)), varTypeStr, varNameStr, str);
|
||||||
i += 3;
|
i += 3;
|
||||||
break;
|
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":
|
case "map":
|
||||||
{
|
{
|
||||||
if ((members[i + 1].m_MetaFlag & 0x4000) != 0)
|
if ((members[i + 1].m_MetaFlag & 0x4000) != 0)
|
||||||
@@ -102,12 +84,11 @@ namespace AssetStudio
|
|||||||
sb.AppendFormat("{0}{1} {2}\r\n", (new string('\t', level + 1)), "Array", "Array");
|
sb.AppendFormat("{0}{1} {2}\r\n", (new string('\t', level + 1)), "Array", "Array");
|
||||||
var size = reader.ReadInt32();
|
var size = reader.ReadInt32();
|
||||||
sb.AppendFormat("{0}{1} {2} = {3}\r\n", (new string('\t', level + 1)), "int", "size", size);
|
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;
|
i += map.Count - 1;
|
||||||
map.RemoveRange(0, 4);
|
var first = GetMembers(map, 4);
|
||||||
var first = GetMembers(map, map[0].m_Level, 0);
|
var next = 4 + first.Count;
|
||||||
map.RemoveRange(0, first.Count);
|
var second = GetMembers(map, next);
|
||||||
var second = map;
|
|
||||||
for (int j = 0; j < size; j++)
|
for (int j = 0; j < size; j++)
|
||||||
{
|
{
|
||||||
sb.AppendFormat("{0}[{1}]\r\n", (new string('\t', level + 2)), j);
|
sb.AppendFormat("{0}[{1}]\r\n", (new string('\t', level + 2)), j);
|
||||||
@@ -131,20 +112,37 @@ namespace AssetStudio
|
|||||||
}
|
}
|
||||||
default:
|
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;
|
else //Class
|
||||||
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++)
|
|
||||||
{
|
{
|
||||||
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)
|
if (append)
|
||||||
@@ -168,7 +166,6 @@ namespace AssetStudio
|
|||||||
private static object ReadValue(List<TypeTreeNode> members, BinaryReader reader, ref int i)
|
private static object ReadValue(List<TypeTreeNode> members, BinaryReader reader, ref int i)
|
||||||
{
|
{
|
||||||
var member = members[i];
|
var member = members[i];
|
||||||
var level = member.m_Level;
|
|
||||||
var varTypeStr = member.m_Type;
|
var varTypeStr = member.m_Type;
|
||||||
object value;
|
object value;
|
||||||
var align = (member.m_MetaFlag & 0x4000) != 0;
|
var align = (member.m_MetaFlag & 0x4000) != 0;
|
||||||
@@ -178,6 +175,7 @@ namespace AssetStudio
|
|||||||
value = reader.ReadSByte();
|
value = reader.ReadSByte();
|
||||||
break;
|
break;
|
||||||
case "UInt8":
|
case "UInt8":
|
||||||
|
case "char":
|
||||||
value = reader.ReadByte();
|
value = reader.ReadByte();
|
||||||
break;
|
break;
|
||||||
case "short":
|
case "short":
|
||||||
@@ -203,6 +201,7 @@ namespace AssetStudio
|
|||||||
break;
|
break;
|
||||||
case "UInt64":
|
case "UInt64":
|
||||||
case "unsigned long long":
|
case "unsigned long long":
|
||||||
|
case "FileSize":
|
||||||
value = reader.ReadUInt64();
|
value = reader.ReadUInt64();
|
||||||
break;
|
break;
|
||||||
case "float":
|
case "float":
|
||||||
@@ -222,14 +221,13 @@ namespace AssetStudio
|
|||||||
{
|
{
|
||||||
if ((members[i + 1].m_MetaFlag & 0x4000) != 0)
|
if ((members[i + 1].m_MetaFlag & 0x4000) != 0)
|
||||||
align = true;
|
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 size = reader.ReadInt32();
|
||||||
var dic = new List<KeyValuePair<object, object>>(size);
|
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++)
|
for (int j = 0; j < size; j++)
|
||||||
{
|
{
|
||||||
int tmp1 = 0;
|
int tmp1 = 0;
|
||||||
@@ -248,18 +246,17 @@ namespace AssetStudio
|
|||||||
}
|
}
|
||||||
default:
|
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)
|
if ((members[i + 1].m_MetaFlag & 0x4000) != 0)
|
||||||
align = true;
|
align = true;
|
||||||
|
var vector = GetMembers(members, i);
|
||||||
|
i += vector.Count - 1;
|
||||||
var size = reader.ReadInt32();
|
var size = reader.ReadInt32();
|
||||||
var list = new List<object>(size);
|
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++)
|
for (int j = 0; j < size; j++)
|
||||||
{
|
{
|
||||||
int tmp = 0;
|
int tmp = 3;
|
||||||
list.Add(ReadValue(vector, reader, ref tmp));
|
list.Add(ReadValue(vector, reader, ref tmp));
|
||||||
}
|
}
|
||||||
value = list;
|
value = list;
|
||||||
@@ -267,11 +264,10 @@ namespace AssetStudio
|
|||||||
}
|
}
|
||||||
else //Class
|
else //Class
|
||||||
{
|
{
|
||||||
var @class = GetMembers(members, level, i);
|
var @class = GetMembers(members, i);
|
||||||
@class.RemoveAt(0);
|
i += @class.Count - 1;
|
||||||
i += @class.Count;
|
|
||||||
var obj = new UType();
|
var obj = new UType();
|
||||||
for (int j = 0; j < @class.Count; j++)
|
for (int j = 1; j < @class.Count; j++)
|
||||||
{
|
{
|
||||||
var classmember = @class[j];
|
var classmember = @class[j];
|
||||||
var name = classmember.m_Name;
|
var name = classmember.m_Name;
|
||||||
@@ -287,10 +283,11 @@ namespace AssetStudio
|
|||||||
return value;
|
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>();
|
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++)
|
for (int i = index + 1; i < members.Count; i++)
|
||||||
{
|
{
|
||||||
var member = members[i];
|
var member = members[i];
|
||||||
@@ -303,140 +300,5 @@ namespace AssetStudio
|
|||||||
}
|
}
|
||||||
return member2;
|
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,12 @@ namespace AssetStudio
|
|||||||
public string m_Name;
|
public string m_Name;
|
||||||
public int m_ByteSize;
|
public int m_ByteSize;
|
||||||
public int m_Index;
|
public int m_Index;
|
||||||
public int m_IsArray;
|
public int m_IsArray; //m_TypeFlags
|
||||||
public int m_Version;
|
public int m_Version;
|
||||||
public int m_MetaFlag;
|
public int m_MetaFlag;
|
||||||
public int m_Level;
|
public int m_Level;
|
||||||
public uint m_TypeStrOffset;
|
public uint m_TypeStrOffset;
|
||||||
public uint m_NameStrOffset;
|
public uint m_NameStrOffset;
|
||||||
|
public ulong m_RefTypeHash;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+19
-66
@@ -9,73 +9,37 @@ namespace AssetStudio
|
|||||||
public class UType : IDictionary<string, object>
|
public class UType : IDictionary<string, object>
|
||||||
{
|
{
|
||||||
private List<string> keys;
|
private List<string> keys;
|
||||||
private List<object> values;
|
private IDictionary<string, object> values;
|
||||||
|
|
||||||
public UType()
|
public UType()
|
||||||
{
|
{
|
||||||
keys = new List<string>();
|
keys = new List<string>();
|
||||||
values = new List<object>();
|
values = new Dictionary<string, 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]
|
public object this[string key]
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
var index = GetValueIndex(key);
|
if (!values.ContainsKey(key))
|
||||||
if (index != -1)
|
|
||||||
{
|
|
||||||
return values[index];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
return values[key];
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
var index = GetValueIndex(key);
|
if (!values.ContainsKey(key))
|
||||||
if (index == -1)
|
|
||||||
{
|
{
|
||||||
keys.Add(key);
|
keys.Add(key);
|
||||||
values.Add(value);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
values[index] = value;
|
|
||||||
}
|
}
|
||||||
|
values[key] = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ICollection<string> Keys => keys;
|
public ICollection<string> Keys => keys;
|
||||||
|
|
||||||
public ICollection<object> Values => values;
|
public ICollection<object> Values => values.Values;
|
||||||
|
|
||||||
public int Count => keys.Count;
|
public int Count => keys.Count;
|
||||||
|
|
||||||
@@ -84,13 +48,13 @@ namespace AssetStudio
|
|||||||
public void Add(string key, object value)
|
public void Add(string key, object value)
|
||||||
{
|
{
|
||||||
keys.Add(key);
|
keys.Add(key);
|
||||||
values.Add(value);
|
values.Add(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Add(KeyValuePair<string, object> item)
|
public void Add(KeyValuePair<string, object> item)
|
||||||
{
|
{
|
||||||
keys.Add(item.Key);
|
keys.Add(item.Key);
|
||||||
values.Add(item.Value);
|
values.Add(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Clear()
|
public void Clear()
|
||||||
@@ -101,55 +65,44 @@ namespace AssetStudio
|
|||||||
|
|
||||||
public bool Contains(KeyValuePair<string, object> item)
|
public bool Contains(KeyValuePair<string, object> item)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
return values.Contains(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ContainsKey(string key)
|
public bool ContainsKey(string key)
|
||||||
{
|
{
|
||||||
return GetValueIndex(key) != -1;
|
return values.ContainsKey(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CopyTo(KeyValuePair<string, object>[] array, int arrayIndex)
|
public void CopyTo(KeyValuePair<string, object>[] array, int arrayIndex)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
values.CopyTo(array, arrayIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
|
public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
|
||||||
{
|
{
|
||||||
for (int i = 0, n = keys.Count; i < n; i++)
|
return values.GetEnumerator();
|
||||||
{
|
|
||||||
yield return new KeyValuePair<string, object>(keys[i], values[i]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Remove(string key)
|
public bool Remove(string key)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
keys.Remove(key);
|
||||||
|
return values.Remove(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Remove(KeyValuePair<string, object> item)
|
public bool Remove(KeyValuePair<string, object> item)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
keys.Remove(item.Key);
|
||||||
|
return values.Remove(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryGetValue(string key, out object value)
|
public bool TryGetValue(string key, out object value)
|
||||||
{
|
{
|
||||||
var index = GetValueIndex(key);
|
return values.TryGetValue(key, out value);
|
||||||
if (index != -1)
|
|
||||||
{
|
|
||||||
value = values[index];
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
value = null;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IEnumerator IEnumerable.GetEnumerator()
|
IEnumerator IEnumerable.GetEnumerator()
|
||||||
{
|
{
|
||||||
return GetEnumerator();
|
return values.GetEnumerator();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ namespace AssetStudio
|
|||||||
{
|
{
|
||||||
public static byte[] gzipMagic = { 0x1f, 0x8b };
|
public static byte[] gzipMagic = { 0x1f, 0x8b };
|
||||||
public static byte[] brotliMagic = { 0x62, 0x72, 0x6F, 0x74, 0x6C, 0x69 };
|
public static byte[] brotliMagic = { 0x62, 0x72, 0x6F, 0x74, 0x6C, 0x69 };
|
||||||
public List<StreamFile> fileList = new List<StreamFile>();
|
public StreamFile[] fileList;
|
||||||
|
|
||||||
private class WebData
|
private class WebData
|
||||||
{
|
{
|
||||||
@@ -78,14 +78,15 @@ namespace AssetStudio
|
|||||||
data.path = Encoding.UTF8.GetString(reader.ReadBytes(pathLength));
|
data.path = Encoding.UTF8.GetString(reader.ReadBytes(pathLength));
|
||||||
dataList.Add(data);
|
dataList.Add(data);
|
||||||
}
|
}
|
||||||
|
fileList = new StreamFile[dataList.Count];
|
||||||
foreach (var data in dataList)
|
for (int i = 0; i < dataList.Count; i++)
|
||||||
{
|
{
|
||||||
|
var data = dataList[i];
|
||||||
var file = new StreamFile();
|
var file = new StreamFile();
|
||||||
file.fileName = Path.GetFileName(data.path);
|
file.fileName = Path.GetFileName(data.path);
|
||||||
reader.BaseStream.Position = data.dataOffset;
|
reader.BaseStream.Position = data.dataOffset;
|
||||||
file.stream = new MemoryStream(reader.ReadBytes(data.dataLength));
|
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-2020")];
|
|
||||||
[assembly:AssemblyTrademarkAttribute(L"")];
|
|
||||||
[assembly:AssemblyCultureAttribute(L"")];
|
|
||||||
|
|
||||||
[assembly:AssemblyVersionAttribute("1.0.*")];
|
|
||||||
|
|
||||||
[assembly:ComVisible(false)];
|
|
||||||
|
|
||||||
[assembly:CLSCompliantAttribute(true)];
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
#include "AssetStudioFBX.h"
|
|
||||||
|
|
||||||
namespace AssetStudio
|
|
||||||
{
|
|
||||||
char* Fbx::StringToUTF8(String^ s)
|
|
||||||
{
|
|
||||||
auto bytes = Text::Encoding::UTF8->GetBytes(s);
|
|
||||||
auto chars = new char[bytes->Length + 1];
|
|
||||||
pin_ptr<unsigned char> ptr = &bytes[0];
|
|
||||||
memcpy(chars, ptr, bytes->Length);
|
|
||||||
chars[bytes->Length] = '\0';
|
|
||||||
return chars;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
#define WITH_MARSHALLED_STRING(name,str,block)\
|
|
||||||
{ \
|
|
||||||
char* name; \
|
|
||||||
try \
|
|
||||||
{ \
|
|
||||||
name = StringToUTF8(str); \
|
|
||||||
block \
|
|
||||||
} \
|
|
||||||
finally \
|
|
||||||
{ \
|
|
||||||
delete 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* StringToUTF8(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 allNodes, bool skins, bool animation, bool blendShape, bool castToBone, float boneSize, float scaleFactor, 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^ name, IImported^ imported, bool allNodes, bool skins, bool castToBone, 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^ iMesh);
|
|
||||||
FbxFileTexture* ExportTexture(ImportedTexture^ matTex);
|
|
||||||
void ExportAnimations(bool eulerFilter, float filterValue);
|
|
||||||
void ExportKeyframedAnimation(ImportedKeyframedAnimation^ parser, FbxString& kTakeName, FbxAnimCurveFilterUnroll* eulerFilter, float filterPrecision);
|
|
||||||
void ExportMorphs();
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,33 +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;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>
|
|
||||||
<ClInclude Include="AssetStudioFBX.h">
|
|
||||||
<Filter>头文件</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClCompile Include="AssemblyInfo.cpp">
|
|
||||||
<Filter>源文件</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="AssetStudioFBX.cpp">
|
|
||||||
<Filter>源文件</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="AssetStudioFBXExporter.cpp">
|
|
||||||
<Filter>源文件</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
|
||||||
@@ -1,894 +0,0 @@
|
|||||||
#include "AssetStudioFBX.h"
|
|
||||||
|
|
||||||
namespace AssetStudio
|
|
||||||
{
|
|
||||||
void Fbx::Exporter::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)
|
|
||||||
{
|
|
||||||
FileInfo^ file = gcnew FileInfo(path);
|
|
||||||
DirectoryInfo^ dir = file->Directory;
|
|
||||||
if (!dir->Exists)
|
|
||||||
{
|
|
||||||
dir->Create();
|
|
||||||
}
|
|
||||||
String^ currentDir = Directory::GetCurrentDirectory();
|
|
||||||
Directory::SetCurrentDirectory(dir->FullName);
|
|
||||||
auto name = Path::GetFileName(path);
|
|
||||||
Exporter^ exporter = gcnew Exporter(name, imported, allNodes, skins, castToBone, boneSize, scaleFactor, versionIndex, isAscii);
|
|
||||||
if (blendShape)
|
|
||||||
{
|
|
||||||
exporter->ExportMorphs();
|
|
||||||
}
|
|
||||||
if (animation)
|
|
||||||
{
|
|
||||||
exporter->ExportAnimations(eulerFilter, filterPrecision);
|
|
||||||
}
|
|
||||||
exporter->pExporter->Export(exporter->pScene);
|
|
||||||
delete exporter;
|
|
||||||
|
|
||||||
Directory::SetCurrentDirectory(currentDir);
|
|
||||||
}
|
|
||||||
|
|
||||||
Fbx::Exporter::Exporter(String^ name, IImported^ imported, bool allNodes, bool skins, bool castToBone, 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));
|
|
||||||
|
|
||||||
if (imported->AnimationList->Count > 0)
|
|
||||||
{
|
|
||||||
auto ani = imported->AnimationList[0];
|
|
||||||
if (ani->SampleRate == 60.0f)
|
|
||||||
{
|
|
||||||
globalSettings.SetTimeMode(FbxTime::eFrames60);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cDest = StringToUTF8(name);
|
|
||||||
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 (!allNodes)
|
|
||||||
{
|
|
||||||
framePaths = SearchHierarchy();
|
|
||||||
if (!framePaths)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pBindPose = FbxPose::Create(pScene, "BindPose");
|
|
||||||
pScene->AddPose(pBindPose);
|
|
||||||
|
|
||||||
frameToNode = gcnew Dictionary<ImportedFrame^, size_t>();
|
|
||||||
meshFrames = imported->MeshList != nullptr ? gcnew List<ImportedFrame^>() : nullptr;
|
|
||||||
ExportFrame(pScene->GetRootNode(), imported->RootFrame);
|
|
||||||
|
|
||||||
if (imported->MeshList != nullptr)
|
|
||||||
{
|
|
||||||
SetJointsFromImportedMeshes(castToBone);
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
delete cDest;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Fbx::Exporter::SetJointsNode(ImportedFrame^ frame, HashSet<String^>^ bonePaths, bool castToBone)
|
|
||||||
{
|
|
||||||
size_t pointer;
|
|
||||||
if (frameToNode->TryGetValue(frame, pointer))
|
|
||||||
{
|
|
||||||
auto pNode = (FbxNode*)pointer;
|
|
||||||
if (castToBone)
|
|
||||||
{
|
|
||||||
FbxSkeleton* pJoint = FbxSkeleton::Create(pScene, "");
|
|
||||||
pJoint->Size.Set(FbxDouble(boneSize));
|
|
||||||
pJoint->SetSkeletonType(FbxSkeleton::eLimbNode);
|
|
||||||
pNode->SetNodeAttribute(pJoint);
|
|
||||||
}
|
|
||||||
else if (bonePaths->Contains(frame->Path))
|
|
||||||
{
|
|
||||||
FbxSkeleton* pJoint = FbxSkeleton::Create(pScene, "");
|
|
||||||
pJoint->Size.Set(FbxDouble(boneSize));
|
|
||||||
pJoint->SetSkeletonType(FbxSkeleton::eLimbNode);
|
|
||||||
pNode->SetNodeAttribute(pJoint);
|
|
||||||
|
|
||||||
pJoint = FbxSkeleton::Create(pScene, "");
|
|
||||||
pJoint->Size.Set(FbxDouble(boneSize));
|
|
||||||
pJoint->SetSkeletonType(FbxSkeleton::eLimbNode);
|
|
||||||
pNode->GetParent()->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, castToBone);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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 castToBone)
|
|
||||||
{
|
|
||||||
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, castToBone);
|
|
||||||
}
|
|
||||||
|
|
||||||
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^ iMesh)
|
|
||||||
{
|
|
||||||
List<ImportedBone^>^ boneList = iMesh->BoneList;
|
|
||||||
bool hasBones;
|
|
||||||
if (exportSkins && boneList != nullptr)
|
|
||||||
{
|
|
||||||
hasBones = boneList->Count > 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
hasBones = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
FbxArray<FbxCluster*>* pClusterArray = nullptr;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (hasBones)
|
|
||||||
{
|
|
||||||
pClusterArray = new FbxArray<FbxCluster*>(boneList->Count);
|
|
||||||
|
|
||||||
for (int i = 0; i < boneList->Count; i++)
|
|
||||||
{
|
|
||||||
auto bone = boneList[i];
|
|
||||||
if (bone->Path != nullptr)
|
|
||||||
{
|
|
||||||
auto frame = imported->RootFrame->FindFrameByPath(bone->Path);
|
|
||||||
auto boneNode = (FbxNode*)frameToNode[frame];
|
|
||||||
FbxString lClusterName = boneNode->GetNameOnly() + FbxString("Cluster");
|
|
||||||
FbxCluster* pCluster = FbxCluster::Create(pScene, lClusterName.Buffer());
|
|
||||||
pCluster->SetLink(boneNode);
|
|
||||||
pCluster->SetLinkMode(FbxCluster::eTotalOne);
|
|
||||||
pClusterArray->Add(pCluster);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pClusterArray->Add(NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
FbxMesh* pMesh = FbxMesh::Create(pScene, pFrameNode->GetName());
|
|
||||||
pFrameNode->SetNodeAttribute(pMesh);
|
|
||||||
|
|
||||||
int vertexCount = 0;
|
|
||||||
for (int i = 0; i < iMesh->SubmeshList->Count; i++)
|
|
||||||
{
|
|
||||||
vertexCount += iMesh->SubmeshList[i]->VertexList->Count;
|
|
||||||
}
|
|
||||||
|
|
||||||
pMesh->InitControlPoints(vertexCount);
|
|
||||||
FbxVector4* pControlPoints = pMesh->GetControlPoints();
|
|
||||||
|
|
||||||
FbxGeometryElementNormal* lGeometryElementNormal = NULL;
|
|
||||||
if (iMesh->hasNormal)
|
|
||||||
{
|
|
||||||
lGeometryElementNormal = pMesh->CreateElementNormal();
|
|
||||||
lGeometryElementNormal->SetMappingMode(FbxGeometryElement::eByControlPoint);
|
|
||||||
lGeometryElementNormal->SetReferenceMode(FbxGeometryElement::eDirect);
|
|
||||||
}
|
|
||||||
|
|
||||||
FbxGeometryElementUV* lGeometryElementUV = NULL;
|
|
||||||
if (iMesh->hasUV)
|
|
||||||
{
|
|
||||||
lGeometryElementUV = pMesh->CreateElementUV("UV0");
|
|
||||||
lGeometryElementUV->SetMappingMode(FbxGeometryElement::eByControlPoint);
|
|
||||||
lGeometryElementUV->SetReferenceMode(FbxGeometryElement::eDirect);
|
|
||||||
}
|
|
||||||
|
|
||||||
FbxGeometryElementTangent* lGeometryElementTangent = NULL;
|
|
||||||
if (iMesh->hasTangent)
|
|
||||||
{
|
|
||||||
lGeometryElementTangent = pMesh->CreateElementTangent();
|
|
||||||
lGeometryElementTangent->SetMappingMode(FbxGeometryElement::eByControlPoint);
|
|
||||||
lGeometryElementTangent->SetReferenceMode(FbxGeometryElement::eDirect);
|
|
||||||
}
|
|
||||||
|
|
||||||
FbxGeometryElementVertexColor* lGeometryElementVertexColor = NULL;
|
|
||||||
if (iMesh->hasColor)
|
|
||||||
{
|
|
||||||
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 < iMesh->SubmeshList->Count; i++)
|
|
||||||
{
|
|
||||||
ImportedSubmesh^ meshObj = iMesh->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 = StringToUTF8(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
|
|
||||||
{
|
|
||||||
delete pMatName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int j = 0; j < vertexList->Count; j++)
|
|
||||||
{
|
|
||||||
ImportedVertex^ iVertex = vertexList[j];
|
|
||||||
|
|
||||||
Vector3 vertex = iVertex->Vertex;
|
|
||||||
pControlPoints[j + firstVertex] = FbxVector4(vertex.X, vertex.Y, vertex.Z, 0);
|
|
||||||
|
|
||||||
if (iMesh->hasNormal)
|
|
||||||
{
|
|
||||||
Vector3 normal = iVertex->Normal;
|
|
||||||
lGeometryElementNormal->GetDirectArray().Add(FbxVector4(normal.X, normal.Y, normal.Z, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (iMesh->hasUV)
|
|
||||||
{
|
|
||||||
array<float>^ uv = iVertex->UV;
|
|
||||||
lGeometryElementUV->GetDirectArray().Add(FbxVector2(uv[0], uv[1]));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (iMesh->hasTangent)
|
|
||||||
{
|
|
||||||
Vector4 tangent = iVertex->Tangent;
|
|
||||||
lGeometryElementTangent->GetDirectArray().Add(FbxVector4(tangent.X, tangent.Y, tangent.Z, tangent.W));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (iMesh->hasColor)
|
|
||||||
{
|
|
||||||
auto color = iVertex->Color;
|
|
||||||
lGeometryElementVertexColor->GetDirectArray().Add(FbxColor(color.R, color.G, color.B, color.A));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasBones && iVertex->BoneIndices != nullptr)
|
|
||||||
{
|
|
||||||
auto boneIndices = iVertex->BoneIndices;
|
|
||||||
auto weights4 = iVertex->Weights;
|
|
||||||
for (int k = 0; k < 4; k++)
|
|
||||||
{
|
|
||||||
if (boneIndices[k] < boneList->Count && weights4[k] > 0)
|
|
||||||
{
|
|
||||||
FbxCluster* pCluster = pClusterArray->GetAt(boneIndices[k]);
|
|
||||||
if (pCluster)
|
|
||||||
{
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
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 (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 = StringToUTF8(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);
|
|
||||||
|
|
||||||
FileInfo^ file = gcnew FileInfo(matTex->Name);
|
|
||||||
BinaryWriter^ writer = gcnew BinaryWriter(file->Create());
|
|
||||||
writer->Write(matTex->Data);
|
|
||||||
writer->Close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
delete 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)
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Fbx::Exporter::ExportKeyframedAnimation(ImportedKeyframedAnimation^ parser, FbxString& kTakeName, FbxAnimCurveFilterUnroll* eulerFilter, float filterPrecision)
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
//BlendShape
|
|
||||||
if (keyframeList->BlendShape != nullptr)
|
|
||||||
{
|
|
||||||
FbxString channelName;
|
|
||||||
WITH_MARSHALLED_STRING
|
|
||||||
(
|
|
||||||
pClipName,
|
|
||||||
keyframeList->BlendShape->ChannelName,
|
|
||||||
channelName = FbxString(pClipName);
|
|
||||||
);
|
|
||||||
|
|
||||||
auto lGeometry = (FbxGeometry*)pNode->GetNodeAttribute();
|
|
||||||
int lBlendShapeDeformerCount = lGeometry->GetDeformerCount(FbxDeformer::eBlendShape);
|
|
||||||
if (lBlendShapeDeformerCount > 0)
|
|
||||||
{
|
|
||||||
FbxBlendShape* lBlendShape = (FbxBlendShape*)lGeometry->GetDeformer(0, FbxDeformer::eBlendShape);
|
|
||||||
int lBlendShapeChannelCount = lBlendShape->GetBlendShapeChannelCount();
|
|
||||||
for (int lChannelIndex = 0; lChannelIndex < lBlendShapeChannelCount; ++lChannelIndex)
|
|
||||||
{
|
|
||||||
FbxBlendShapeChannel* lChannel = lBlendShape->GetBlendShapeChannel(lChannelIndex);
|
|
||||||
FbxString lChannelName = lChannel->GetNameOnly();
|
|
||||||
if (lChannelName == channelName)
|
|
||||||
{
|
|
||||||
FbxAnimCurve* lAnimCurve = lGeometry->GetShapeChannel(0, lChannelIndex, lAnimLayer, true);
|
|
||||||
lAnimCurve->KeyModifyBegin();
|
|
||||||
|
|
||||||
for each (auto keyframe in keyframeList->BlendShape->Keyframes)
|
|
||||||
{
|
|
||||||
lTime.SetSecondDouble(keyframe->time);
|
|
||||||
int lKeyIndex = lAnimCurve->KeyAdd(lTime);
|
|
||||||
lAnimCurve->KeySetValue(lKeyIndex, keyframe->value);
|
|
||||||
lAnimCurve->KeySetInterpolation(lKeyIndex, FbxAnimCurveDef::eInterpolationCubic);
|
|
||||||
}
|
|
||||||
|
|
||||||
lAnimCurve->KeyModifyEnd();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Fbx::Exporter::ExportMorphs()
|
|
||||||
{
|
|
||||||
if (imported->MeshList == nullptr)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for each (ImportedMorph^ morph in imported->MorphList)
|
|
||||||
{
|
|
||||||
auto frame = imported->RootFrame->FindFrameByPath(morph->Path);
|
|
||||||
if (frame != nullptr)
|
|
||||||
{
|
|
||||||
FbxNode* pNode = (FbxNode*)frameToNode[frame];
|
|
||||||
FbxMesh* pMesh = pNode->GetMesh();
|
|
||||||
|
|
||||||
FbxBlendShape* lBlendShape = FbxBlendShape::Create(pScene, pMesh->GetNameOnly() + FbxString("BlendShape"));
|
|
||||||
pMesh->AddDeformer(lBlendShape);
|
|
||||||
|
|
||||||
for (int i = 0; i < morph->Channels->Count; i++)
|
|
||||||
{
|
|
||||||
auto channel = morph->Channels[i];
|
|
||||||
|
|
||||||
FbxBlendShapeChannel* lBlendShapeChannel;
|
|
||||||
WITH_MARSHALLED_STRING
|
|
||||||
(
|
|
||||||
pChannelName,
|
|
||||||
channel->Name,
|
|
||||||
lBlendShapeChannel = FbxBlendShapeChannel::Create(pScene, pChannelName);
|
|
||||||
);
|
|
||||||
lBlendShape->AddBlendShapeChannel(lBlendShapeChannel);
|
|
||||||
|
|
||||||
for each(ImportedMorphKeyframe^ keyframe in channel->KeyframeList)
|
|
||||||
{
|
|
||||||
FbxShape* lShape = FbxShape::Create(pScene, FbxString(keyframe->Weight));
|
|
||||||
lBlendShapeChannel->AddTargetShape(lShape, keyframe->Weight);
|
|
||||||
|
|
||||||
auto vectorCount = pMesh->GetControlPointsCount();
|
|
||||||
FbxVector4* orilVector4 = pMesh->GetControlPoints();
|
|
||||||
lShape->InitControlPoints(vectorCount);
|
|
||||||
FbxVector4* lVector4 = lShape->GetControlPoints();
|
|
||||||
|
|
||||||
for (int j = 0; j < vectorCount; j++)
|
|
||||||
{
|
|
||||||
auto vertex = orilVector4[j];
|
|
||||||
lVector4[j] = FbxVector4(vertex);
|
|
||||||
}
|
|
||||||
for (int j = 0; j < keyframe->VertexList->Count; j++)
|
|
||||||
{
|
|
||||||
auto index = keyframe->VertexList[j]->Index;
|
|
||||||
auto vertex = keyframe->VertexList[j]->Vertex->Vertex;
|
|
||||||
lVector4[index] = FbxVector4(vertex.X, vertex.Y, vertex.Z, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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
|
||||||
|
|
||||||
+92
-37
@@ -20,39 +20,36 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<PropertyGroup Label="Globals">
|
<PropertyGroup Label="Globals">
|
||||||
<VCProjectVersion>16.0</VCProjectVersion>
|
<VCProjectVersion>16.0</VCProjectVersion>
|
||||||
<ProjectGuid>{B82DD1BA-4EEC-4F29-A686-03D7F0DF39B8}</ProjectGuid>
|
<Keyword>Win32Proj</Keyword>
|
||||||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
<ProjectGuid>{11ea25a3-ed68-40ee-a9d0-7fde3b583027}</ProjectGuid>
|
||||||
<Keyword>ManagedCProj</Keyword>
|
<RootNamespace>AssetStudioFBXNative</RootNamespace>
|
||||||
<RootNamespace>AssetStudioFBX</RootNamespace>
|
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||||
<WindowsTargetPlatformVersion>10.0.18362.0</WindowsTargetPlatformVersion>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
<PlatformToolset>v141</PlatformToolset>
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
<CLRSupport>true</CLRSupport>
|
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
<PlatformToolset>v141</PlatformToolset>
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
<CLRSupport>true</CLRSupport>
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
<PlatformToolset>v141</PlatformToolset>
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
<CLRSupport>true</CLRSupport>
|
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
<PlatformToolset>v141</PlatformToolset>
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
<CLRSupport>true</CLRSupport>
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
@@ -73,14 +70,60 @@
|
|||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
<PropertyGroup Label="UserMacros" />
|
<PropertyGroup Label="UserMacros" />
|
||||||
<PropertyGroup />
|
<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'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<WarningLevel>Level3</WarningLevel>
|
<WarningLevel>Level3</WarningLevel>
|
||||||
<PreprocessorDefinitions>FBXSDK_SHARED;WIN32;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>_AS_DLL;FBXSDK_SHARED;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
<AdditionalIncludeDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.0.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.0.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<AdditionalDependencies>libfbxsdk.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)'=='Release|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>_AS_DLL;FBXSDK_SHARED;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
<AdditionalIncludeDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.0.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<AdditionalDependencies>libfbxsdk.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>libfbxsdk.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<AdditionalLibraryDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.0.1\lib\vs2017\x86\release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
<AdditionalLibraryDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.0.1\lib\vs2017\x86\release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
</Link>
|
</Link>
|
||||||
@@ -88,54 +131,66 @@
|
|||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<WarningLevel>Level3</WarningLevel>
|
<WarningLevel>Level3</WarningLevel>
|
||||||
<PreprocessorDefinitions>FBXSDK_SHARED;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>_AS_DLL;FBXSDK_SHARED;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
<AdditionalIncludeDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.0.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.0.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<AdditionalDependencies>libfbxsdk.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>libfbxsdk.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<AdditionalLibraryDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.0.1\lib\vs2017\x64\release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
<AdditionalLibraryDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.0.1\lib\vs2017\x64\release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
|
||||||
<ClCompile>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<PreprocessorDefinitions>FBXSDK_SHARED;WIN32;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<AdditionalIncludeDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.0.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<AdditionalDependencies>libfbxsdk.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)'=='Release|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<WarningLevel>Level3</WarningLevel>
|
<WarningLevel>Level3</WarningLevel>
|
||||||
<PreprocessorDefinitions>FBXSDK_SHARED;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>_AS_DLL;FBXSDK_SHARED;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
<AdditionalIncludeDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.0.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.0.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<AdditionalDependencies>libfbxsdk.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>libfbxsdk.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<AdditionalLibraryDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.0.1\lib\vs2017\x64\release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
<AdditionalLibraryDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.0.1\lib\vs2017\x64\release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="AssetStudioFBX.h" />
|
<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>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="AssemblyInfo.cpp" />
|
<ClInclude Include="api.h" />
|
||||||
<ClCompile Include="AssetStudioFBX.cpp" />
|
<ClInclude Include="asfbx_anim_context.h" />
|
||||||
<ClCompile Include="AssetStudioFBXExporter.cpp" />
|
<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>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="System" />
|
<None Include="cpp.hint" />
|
||||||
<Reference Include="System.Core" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\AssetStudio\AssetStudio.csproj">
|
<ResourceCompile Include="AssetStudioFBXNative.rc" />
|
||||||
<Project>{7662f8c2-7bfd-442e-a948-a43b4f7eb06e}</Project>
|
|
||||||
</ProjectReference>
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
|
<Target Name="AfterBuild">
|
||||||
|
<MSBuild Condition=" '$(Platform)' == 'Win32' " Projects="$(MSBuildProjectFile)" Properties="Platform=x64;PlatFormTarget=x64" RunEachTargetSeparately="true" />
|
||||||
|
</Target>
|
||||||
</Project>
|
</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,157 @@
|
|||||||
|
#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);
|
||||||
|
|
||||||
|
AS_API(void) AsFbxMorphCopyBlendShapeControlPoints(AsFbxMorphContext* pMorphContext);
|
||||||
|
|
||||||
|
AS_API(void) AsFbxMorphSetBlendShapeVertex(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;
|
||||||
|
|
||||||
|
lGeometry = 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;
|
||||||
|
|
||||||
|
FbxGeometry* lGeometry;
|
||||||
|
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,311 @@
|
|||||||
|
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);
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern void AsFbxMorphAddBlendShapeChannelShape(IntPtr pContext, IntPtr pMorphContext, float weight);
|
||||||
|
|
||||||
|
[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);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,636 @@
|
|||||||
|
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);
|
||||||
|
|
||||||
|
foreach (var keyframe in channel.KeyframeList)
|
||||||
|
{
|
||||||
|
AsFbxMorphAddBlendShapeChannelShape(_pContext, pMorphContext, keyframe.Weight);
|
||||||
|
|
||||||
|
AsFbxMorphCopyBlendShapeControlPoints(pMorphContext);
|
||||||
|
|
||||||
|
foreach (var vertex in keyframe.VertexList)
|
||||||
|
{
|
||||||
|
var v = vertex.Vertex.Vertex;
|
||||||
|
AsFbxMorphSetBlendShapeVertex(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")]
|
||||||
@@ -13,53 +13,31 @@
|
|||||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||||
<Deterministic>true</Deterministic>
|
<Deterministic>true</Deterministic>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
|
||||||
<DebugSymbols>true</DebugSymbols>
|
|
||||||
<OutputPath>bin\x64\Debug\</OutputPath>
|
|
||||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
|
||||||
<DebugType>full</DebugType>
|
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
|
||||||
<LangVersion>7.3</LangVersion>
|
|
||||||
<ErrorReport>prompt</ErrorReport>
|
|
||||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
|
||||||
<Prefer32Bit>true</Prefer32Bit>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
|
||||||
<OutputPath>bin\x64\Release\</OutputPath>
|
|
||||||
<DefineConstants>TRACE</DefineConstants>
|
|
||||||
<Optimize>true</Optimize>
|
|
||||||
<DebugType>pdbonly</DebugType>
|
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
|
||||||
<LangVersion>7.3</LangVersion>
|
|
||||||
<ErrorReport>prompt</ErrorReport>
|
|
||||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
|
||||||
<Prefer32Bit>true</Prefer32Bit>
|
|
||||||
</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>
|
|
||||||
<LangVersion>7.3</LangVersion>
|
|
||||||
<ErrorReport>prompt</ErrorReport>
|
|
||||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
|
||||||
<Prefer32Bit>true</Prefer32Bit>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
|
|
||||||
<OutputPath>bin\x86\Release\</OutputPath>
|
|
||||||
<DefineConstants>TRACE</DefineConstants>
|
|
||||||
<Optimize>true</Optimize>
|
|
||||||
<DebugType>pdbonly</DebugType>
|
|
||||||
<PlatformTarget>x86</PlatformTarget>
|
|
||||||
<LangVersion>7.3</LangVersion>
|
|
||||||
<ErrorReport>prompt</ErrorReport>
|
|
||||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
|
||||||
<Prefer32Bit>true</Prefer32Bit>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<ApplicationIcon>Resources\as.ico</ApplicationIcon>
|
<ApplicationIcon>Resources\as.ico</ApplicationIcon>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<OutputPath>bin\Debug\</OutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
|
<LangVersion>7.3</LangVersion>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||||
|
<Prefer32Bit>false</Prefer32Bit>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
|
||||||
|
<OutputPath>bin\Release\</OutputPath>
|
||||||
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
|
<LangVersion>7.3</LangVersion>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||||
|
<Prefer32Bit>false</Prefer32Bit>
|
||||||
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="OpenTK, Version=3.1.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
|
<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>
|
<HintPath>..\packages\OpenTK.3.1.0\lib\net20\OpenTK.dll</HintPath>
|
||||||
@@ -144,24 +122,22 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="Resources\as.ico" />
|
<None Include="Resources\as.ico" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup Condition="'$(Platform)' == 'x86'">
|
<ItemGroup>
|
||||||
<ContentWithTargetPath Include="Libraries\x86\fmod.dll">
|
<ContentWithTargetPath Include="Libraries\x86\fmod.dll">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
<TargetPath>fmod.dll</TargetPath>
|
<TargetPath>x86\fmod.dll</TargetPath>
|
||||||
</ContentWithTargetPath>
|
</ContentWithTargetPath>
|
||||||
<ContentWithTargetPath Include="Libraries\x86\libfbxsdk.dll">
|
<ContentWithTargetPath Include="Libraries\x86\libfbxsdk.dll">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
<TargetPath>libfbxsdk.dll</TargetPath>
|
<TargetPath>x86\libfbxsdk.dll</TargetPath>
|
||||||
</ContentWithTargetPath>
|
</ContentWithTargetPath>
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup Condition="'$(Platform)' == 'x64'">
|
|
||||||
<ContentWithTargetPath Include="Libraries\x64\fmod.dll">
|
<ContentWithTargetPath Include="Libraries\x64\fmod.dll">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
<TargetPath>fmod.dll</TargetPath>
|
<TargetPath>x64\fmod.dll</TargetPath>
|
||||||
</ContentWithTargetPath>
|
</ContentWithTargetPath>
|
||||||
<ContentWithTargetPath Include="Libraries\x64\libfbxsdk.dll">
|
<ContentWithTargetPath Include="Libraries\x64\libfbxsdk.dll">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
<TargetPath>libfbxsdk.dll</TargetPath>
|
<TargetPath>x64\libfbxsdk.dll</TargetPath>
|
||||||
</ContentWithTargetPath>
|
</ContentWithTargetPath>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -175,4 +151,10 @@
|
|||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
|
<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>
|
</Project>
|
||||||
+14
-2
@@ -111,6 +111,7 @@
|
|||||||
this.openFileDialog1 = new System.Windows.Forms.OpenFileDialog();
|
this.openFileDialog1 = new System.Windows.Forms.OpenFileDialog();
|
||||||
this.saveFileDialog1 = new System.Windows.Forms.SaveFileDialog();
|
this.saveFileDialog1 = new System.Windows.Forms.SaveFileDialog();
|
||||||
this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components);
|
this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components);
|
||||||
|
this.copyToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
this.exportSelectedAssetsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
this.exportSelectedAssetsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
this.exportAnimatorwithselectedAnimationClipMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
this.exportAnimatorwithselectedAnimationClipMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
this.goToSceneHierarchyToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
this.goToSceneHierarchyToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
@@ -545,7 +546,6 @@
|
|||||||
this.assetListView.FullRowSelect = true;
|
this.assetListView.FullRowSelect = true;
|
||||||
this.assetListView.GridLines = true;
|
this.assetListView.GridLines = true;
|
||||||
this.assetListView.HideSelection = false;
|
this.assetListView.HideSelection = false;
|
||||||
this.assetListView.LabelEdit = true;
|
|
||||||
this.assetListView.Location = new System.Drawing.Point(0, 21);
|
this.assetListView.Location = new System.Drawing.Point(0, 21);
|
||||||
this.assetListView.Name = "assetListView";
|
this.assetListView.Name = "assetListView";
|
||||||
this.assetListView.Size = new System.Drawing.Size(472, 587);
|
this.assetListView.Size = new System.Drawing.Size(472, 587);
|
||||||
@@ -910,12 +910,20 @@
|
|||||||
//
|
//
|
||||||
this.contextMenuStrip1.ImageScalingSize = new System.Drawing.Size(20, 20);
|
this.contextMenuStrip1.ImageScalingSize = new System.Drawing.Size(20, 20);
|
||||||
this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||||
|
this.copyToolStripMenuItem,
|
||||||
this.exportSelectedAssetsToolStripMenuItem,
|
this.exportSelectedAssetsToolStripMenuItem,
|
||||||
this.exportAnimatorwithselectedAnimationClipMenuItem,
|
this.exportAnimatorwithselectedAnimationClipMenuItem,
|
||||||
this.goToSceneHierarchyToolStripMenuItem,
|
this.goToSceneHierarchyToolStripMenuItem,
|
||||||
this.showOriginalFileToolStripMenuItem});
|
this.showOriginalFileToolStripMenuItem});
|
||||||
this.contextMenuStrip1.Name = "contextMenuStrip1";
|
this.contextMenuStrip1.Name = "contextMenuStrip1";
|
||||||
this.contextMenuStrip1.Size = new System.Drawing.Size(327, 92);
|
this.contextMenuStrip1.Size = new System.Drawing.Size(327, 114);
|
||||||
|
//
|
||||||
|
// copyToolStripMenuItem
|
||||||
|
//
|
||||||
|
this.copyToolStripMenuItem.Name = "copyToolStripMenuItem";
|
||||||
|
this.copyToolStripMenuItem.Size = new System.Drawing.Size(326, 22);
|
||||||
|
this.copyToolStripMenuItem.Text = "Copy";
|
||||||
|
this.copyToolStripMenuItem.Click += new System.EventHandler(this.copyToolStripMenuItem_Click);
|
||||||
//
|
//
|
||||||
// exportSelectedAssetsToolStripMenuItem
|
// exportSelectedAssetsToolStripMenuItem
|
||||||
//
|
//
|
||||||
@@ -950,6 +958,7 @@
|
|||||||
//
|
//
|
||||||
// AssetStudioGUIForm
|
// AssetStudioGUIForm
|
||||||
//
|
//
|
||||||
|
this.AllowDrop = true;
|
||||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
|
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
|
||||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
this.ClientSize = new System.Drawing.Size(1264, 681);
|
this.ClientSize = new System.Drawing.Size(1264, 681);
|
||||||
@@ -962,6 +971,8 @@
|
|||||||
this.Name = "AssetStudioGUIForm";
|
this.Name = "AssetStudioGUIForm";
|
||||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
||||||
this.Text = "AssetStudioGUI";
|
this.Text = "AssetStudioGUI";
|
||||||
|
this.DragDrop += new System.Windows.Forms.DragEventHandler(this.AssetStudioGUIForm_DragDrop);
|
||||||
|
this.DragEnter += new System.Windows.Forms.DragEventHandler(this.AssetStudioGUIForm_DragEnter);
|
||||||
this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.AssetStudioForm_KeyDown);
|
this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.AssetStudioForm_KeyDown);
|
||||||
this.menuStrip1.ResumeLayout(false);
|
this.menuStrip1.ResumeLayout(false);
|
||||||
this.menuStrip1.PerformLayout();
|
this.menuStrip1.PerformLayout();
|
||||||
@@ -1080,6 +1091,7 @@
|
|||||||
private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem9;
|
private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem9;
|
||||||
private System.Windows.Forms.ColumnHeader columnHeaderContainer;
|
private System.Windows.Forms.ColumnHeader columnHeaderContainer;
|
||||||
private System.Windows.Forms.ColumnHeader columnHeaderPathID;
|
private System.Windows.Forms.ColumnHeader columnHeaderPathID;
|
||||||
|
private System.Windows.Forms.ToolStripMenuItem copyToolStripMenuItem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ namespace AssetStudioGUI
|
|||||||
private AssetItem lastSelectedItem;
|
private AssetItem lastSelectedItem;
|
||||||
private AssetItem lastLoadedAsset;
|
private AssetItem lastLoadedAsset;
|
||||||
private Bitmap imageTexture;
|
private Bitmap imageTexture;
|
||||||
|
private string tempClipboard;
|
||||||
|
|
||||||
private FMOD.System system;
|
private FMOD.System system;
|
||||||
private FMOD.Sound sound;
|
private FMOD.Sound sound;
|
||||||
@@ -100,6 +101,34 @@ namespace AssetStudioGUI
|
|||||||
Studio.StatusStripUpdate = StatusStripUpdate;
|
Studio.StatusStripUpdate = StatusStripUpdate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void AssetStudioGUIForm_DragEnter(object sender, DragEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.Data.GetDataPresent(DataFormats.FileDrop))
|
||||||
|
{
|
||||||
|
e.Effect = DragDropEffects.Move;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void AssetStudioGUIForm_DragDrop(object sender, DragEventArgs e)
|
||||||
|
{
|
||||||
|
var paths = (string[])e.Data.GetData(DataFormats.FileDrop);
|
||||||
|
if (paths.Length > 0)
|
||||||
|
{
|
||||||
|
ResetForm();
|
||||||
|
|
||||||
|
if (paths.Length == 1 && Directory.Exists(paths[0]))
|
||||||
|
{
|
||||||
|
await Task.Run(() => assetsManager.LoadFolder(paths[0]));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await Task.Run(() => assetsManager.LoadFiles(paths));
|
||||||
|
}
|
||||||
|
|
||||||
|
BuildAssetStructures();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async void loadFile_Click(object sender, EventArgs e)
|
private async void loadFile_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
if (openFileDialog1.ShowDialog() == DialogResult.OK)
|
if (openFileDialog1.ShowDialog() == DialogResult.OK)
|
||||||
@@ -563,6 +592,15 @@ namespace AssetStudioGUI
|
|||||||
return reverseSort ? bsf.CompareTo(asf) : asf.CompareTo(bsf);
|
return reverseSort ? bsf.CompareTo(asf) : asf.CompareTo(bsf);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
else if (sortColumn == 3) // PathID
|
||||||
|
{
|
||||||
|
visibleAssets.Sort((x, y) =>
|
||||||
|
{
|
||||||
|
long pathID_X = x.m_PathID;
|
||||||
|
long pathID_Y = y.m_PathID;
|
||||||
|
return reverseSort ? pathID_Y.CompareTo(pathID_X) : pathID_X.CompareTo(pathID_Y);
|
||||||
|
});
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
visibleAssets.Sort((a, b) =>
|
visibleAssets.Sort((a, b) =>
|
||||||
@@ -1081,7 +1119,7 @@ namespace AssetStudioGUI
|
|||||||
|
|
||||||
private void PreviewSprite(AssetItem assetItem, Sprite m_Sprite)
|
private void PreviewSprite(AssetItem assetItem, Sprite m_Sprite)
|
||||||
{
|
{
|
||||||
var bitmap = SpriteHelper.GetImageFromSprite(m_Sprite);
|
var bitmap = m_Sprite.GetImage();
|
||||||
if (bitmap != null)
|
if (bitmap != null)
|
||||||
{
|
{
|
||||||
assetItem.InfoText = $"Width: {bitmap.Width}\nHeight: {bitmap.Height}\n";
|
assetItem.InfoText = $"Width: {bitmap.Width}\nHeight: {bitmap.Height}\n";
|
||||||
@@ -1198,10 +1236,16 @@ namespace AssetStudioGUI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tempClipboard = assetListView.HitTest(new Point(e.X, e.Y)).SubItem.Text;
|
||||||
contextMenuStrip1.Show(assetListView, e.X, e.Y);
|
contextMenuStrip1.Show(assetListView, e.X, e.Y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void copyToolStripMenuItem_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
Clipboard.SetDataObject(tempClipboard);
|
||||||
|
}
|
||||||
|
|
||||||
private void exportSelectedAssetsToolStripMenuItem_Click(object sender, EventArgs e)
|
private void exportSelectedAssetsToolStripMenuItem_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
ExportAssets(2, ExportType.Convert);
|
ExportAssets(2, ExportType.Convert);
|
||||||
|
|||||||
@@ -120,6 +120,9 @@
|
|||||||
<metadata name="menuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
<metadata name="menuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
<value>312, 17</value>
|
<value>312, 17</value>
|
||||||
</metadata>
|
</metadata>
|
||||||
|
<metadata name="statusStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
|
<value>432, 17</value>
|
||||||
|
</metadata>
|
||||||
<data name="fontPreviewBox.Text" xml:space="preserve">
|
<data name="fontPreviewBox.Text" xml:space="preserve">
|
||||||
<value>abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWYZ
|
<value>abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWYZ
|
||||||
1234567890.:,;'\"(!?)+-*/=
|
1234567890.:,;'\"(!?)+-*/=
|
||||||
@@ -138,9 +141,6 @@ The quick brown fox jumps over the lazy dog. 1234567890
|
|||||||
|
|
||||||
The quick brown fox jumps over the lazy dog. 1234567890</value>
|
The quick brown fox jumps over the lazy dog. 1234567890</value>
|
||||||
</data>
|
</data>
|
||||||
<metadata name="statusStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
|
||||||
<value>432, 17</value>
|
|
||||||
</metadata>
|
|
||||||
<metadata name="timer.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
<metadata name="timer.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
<value>553, 17</value>
|
<value>553, 17</value>
|
||||||
</metadata>
|
</metadata>
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ namespace AssetStudioGUI
|
|||||||
if (m_AudioData == null || m_AudioData.Length == 0)
|
if (m_AudioData == null || m_AudioData.Length == 0)
|
||||||
return false;
|
return false;
|
||||||
var converter = new AudioClipConverter(m_AudioClip);
|
var converter = new AudioClipConverter(m_AudioClip);
|
||||||
if (Properties.Settings.Default.convertAudio && converter.IsFMODSupport)
|
if (Properties.Settings.Default.convertAudio && converter.IsSupport)
|
||||||
{
|
{
|
||||||
var exportFullName = exportPath + item.Text + ".wav";
|
var exportFullName = exportPath + item.Text + ".wav";
|
||||||
if (ExportFileExists(exportFullName))
|
if (ExportFileExists(exportFullName))
|
||||||
@@ -287,7 +287,7 @@ namespace AssetStudioGUI
|
|||||||
var exportFullName = exportPath + item.Text + "." + type.ToLower();
|
var exportFullName = exportPath + item.Text + "." + type.ToLower();
|
||||||
if (ExportFileExists(exportFullName))
|
if (ExportFileExists(exportFullName))
|
||||||
return false;
|
return false;
|
||||||
var bitmap = SpriteHelper.GetImageFromSprite((Sprite)item.Asset);
|
var bitmap = ((Sprite)item.Asset).GetImage();
|
||||||
if (bitmap != null)
|
if (bitmap != null)
|
||||||
{
|
{
|
||||||
if (tga)
|
if (tga)
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ namespace AssetStudioGUI
|
|||||||
StatusStripUpdate($"Decompressing {Path.GetFileName(bundleFileName)} ...");
|
StatusStripUpdate($"Decompressing {Path.GetFileName(bundleFileName)} ...");
|
||||||
var bundleFile = new BundleFile(reader, bundleFileName);
|
var bundleFile = new BundleFile(reader, bundleFileName);
|
||||||
reader.Dispose();
|
reader.Dispose();
|
||||||
if (bundleFile.fileList.Count > 0)
|
if (bundleFile.fileList.Length > 0)
|
||||||
{
|
{
|
||||||
var extractPath = bundleFileName + "_unpacked\\";
|
var extractPath = bundleFileName + "_unpacked\\";
|
||||||
return ExtractStreamFile(extractPath, bundleFile.fileList);
|
return ExtractStreamFile(extractPath, bundleFile.fileList);
|
||||||
@@ -68,7 +68,7 @@ namespace AssetStudioGUI
|
|||||||
StatusStripUpdate($"Decompressing {Path.GetFileName(webFileName)} ...");
|
StatusStripUpdate($"Decompressing {Path.GetFileName(webFileName)} ...");
|
||||||
var webFile = new WebFile(reader);
|
var webFile = new WebFile(reader);
|
||||||
reader.Dispose();
|
reader.Dispose();
|
||||||
if (webFile.fileList.Count > 0)
|
if (webFile.fileList.Length > 0)
|
||||||
{
|
{
|
||||||
var extractPath = webFileName + "_unpacked\\";
|
var extractPath = webFileName + "_unpacked\\";
|
||||||
return ExtractStreamFile(extractPath, webFile.fileList);
|
return ExtractStreamFile(extractPath, webFile.fileList);
|
||||||
@@ -76,7 +76,7 @@ namespace AssetStudioGUI
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int ExtractStreamFile(string extractPath, List<StreamFile> fileList)
|
private static int ExtractStreamFile(string extractPath, StreamFile[] fileList)
|
||||||
{
|
{
|
||||||
int extractedCount = 0;
|
int extractedCount = 0;
|
||||||
foreach (var file in fileList)
|
foreach (var file in fileList)
|
||||||
@@ -174,7 +174,11 @@ namespace AssetStudioGUI
|
|||||||
productName = m_PlayerSettings.productName;
|
productName = m_PlayerSettings.productName;
|
||||||
break;
|
break;
|
||||||
case AssetBundle m_AssetBundle:
|
case AssetBundle m_AssetBundle:
|
||||||
containers = m_AssetBundle.m_Container.ToDictionary(x => x.Value.asset.m_PathID, x => x.Key);
|
containers = new Dictionary<long, string>();
|
||||||
|
foreach (var m_Container in m_AssetBundle.m_Container)
|
||||||
|
{
|
||||||
|
containers[m_Container.Value.asset.m_PathID] = m_Container.Key;
|
||||||
|
}
|
||||||
assetItem.Text = m_AssetBundle.m_Name;
|
assetItem.Text = m_AssetBundle.m_Name;
|
||||||
break;
|
break;
|
||||||
case NamedObject m_NamedObject:
|
case NamedObject m_NamedObject:
|
||||||
@@ -324,7 +328,7 @@ namespace AssetStudioGUI
|
|||||||
{
|
{
|
||||||
key = -1 - type.m_ScriptTypeIndex;
|
key = -1 - type.m_ScriptTypeIndex;
|
||||||
}
|
}
|
||||||
items.Add(key, new TypeTreeItem(key, type.m_Nodes));
|
items[key] = new TypeTreeItem(key, type.m_Nodes);
|
||||||
}
|
}
|
||||||
typeMap.Add(assetsFile.unityVersion, items);
|
typeMap.Add(assetsFile.unityVersion, items);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,42 +13,22 @@
|
|||||||
<FileAlignment>512</FileAlignment>
|
<FileAlignment>512</FileAlignment>
|
||||||
<Deterministic>true</Deterministic>
|
<Deterministic>true</Deterministic>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
|
||||||
<DebugSymbols>true</DebugSymbols>
|
<DebugSymbols>true</DebugSymbols>
|
||||||
<OutputPath>bin\x64\Debug\</OutputPath>
|
<OutputPath>bin\Debug\</OutputPath>
|
||||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
<DebugType>full</DebugType>
|
<DebugType>full</DebugType>
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
<LangVersion>7.3</LangVersion>
|
<LangVersion>7.3</LangVersion>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
|
||||||
<OutputPath>bin\x64\Release\</OutputPath>
|
<OutputPath>bin\Release\</OutputPath>
|
||||||
<DefineConstants>TRACE</DefineConstants>
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
<Optimize>true</Optimize>
|
<Optimize>true</Optimize>
|
||||||
<DebugType>pdbonly</DebugType>
|
<DebugType>pdbonly</DebugType>
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
<LangVersion>7.3</LangVersion>
|
|
||||||
<ErrorReport>prompt</ErrorReport>
|
|
||||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
|
||||||
</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>
|
|
||||||
<LangVersion>7.3</LangVersion>
|
|
||||||
<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>
|
|
||||||
<LangVersion>7.3</LangVersion>
|
<LangVersion>7.3</LangVersion>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||||
@@ -82,17 +62,21 @@
|
|||||||
<Compile Include="Texture2DExtensions.cs" />
|
<Compile Include="Texture2DExtensions.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\AssetStudioFBX\AssetStudioFBX.vcxproj">
|
<ProjectReference Include="..\AssetStudio.PInvoke\AssetStudio.PInvoke.csproj">
|
||||||
<Project>{b82dd1ba-4eec-4f29-a686-03d7f0df39b8}</Project>
|
<Project>{40c796b5-88ce-4adc-acd6-2f4862b7f136}</Project>
|
||||||
<Name>AssetStudioFBX</Name>
|
<Name>AssetStudio.PInvoke</Name>
|
||||||
|
</ProjectReference>
|
||||||
|
<ProjectReference Include="..\AssetStudioFBXWrapper\AssetStudioFBXWrapper.csproj">
|
||||||
|
<Project>{bd76e63f-1517-47fa-8233-33e853a3acee}</Project>
|
||||||
|
<Name>AssetStudioFBXWrapper</Name>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
<ProjectReference Include="..\AssetStudio\AssetStudio.csproj">
|
<ProjectReference Include="..\AssetStudio\AssetStudio.csproj">
|
||||||
<Project>{7662f8c2-7bfd-442e-a948-a43b4f7eb06e}</Project>
|
<Project>{7662f8c2-7bfd-442e-a948-a43b4f7eb06e}</Project>
|
||||||
<Name>AssetStudio</Name>
|
<Name>AssetStudio</Name>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
<ProjectReference Include="..\Texture2DDecoder\Texture2DDecoder.vcxproj">
|
<ProjectReference Include="..\Texture2DDecoderWrapper\Texture2DDecoderWrapper.csproj">
|
||||||
<Project>{bec7b5e6-0a7b-4824-97a7-eea04d9eba29}</Project>
|
<Project>{2afce830-b463-49b3-a026-877e5eafc0a4}</Project>
|
||||||
<Name>Texture2DDecoder</Name>
|
<Name>Texture2DDecoderWrapper</Name>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
|
|||||||
@@ -116,24 +116,24 @@ namespace AssetStudio
|
|||||||
case AudioCompressionFormat.MP3:
|
case AudioCompressionFormat.MP3:
|
||||||
return ".fsb";
|
return ".fsb";
|
||||||
case AudioCompressionFormat.VAG:
|
case AudioCompressionFormat.VAG:
|
||||||
return ".vag";
|
return ".fsb";
|
||||||
case AudioCompressionFormat.HEVAG:
|
case AudioCompressionFormat.HEVAG:
|
||||||
return ".vag";
|
return ".fsb";
|
||||||
case AudioCompressionFormat.XMA:
|
case AudioCompressionFormat.XMA:
|
||||||
return ".wav";
|
return ".fsb";
|
||||||
case AudioCompressionFormat.AAC:
|
case AudioCompressionFormat.AAC:
|
||||||
return ".m4a";
|
return ".m4a";
|
||||||
case AudioCompressionFormat.GCADPCM:
|
case AudioCompressionFormat.GCADPCM:
|
||||||
return ".fsb";
|
return ".fsb";
|
||||||
case AudioCompressionFormat.ATRAC9:
|
case AudioCompressionFormat.ATRAC9:
|
||||||
return ".at9";
|
return ".fsb";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ".AudioClip";
|
return ".AudioClip";
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsFMODSupport
|
public bool IsSupport
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
@@ -147,7 +147,6 @@ namespace AssetStudio
|
|||||||
case AudioType.S3M:
|
case AudioType.S3M:
|
||||||
case AudioType.XM:
|
case AudioType.XM:
|
||||||
case AudioType.XMA:
|
case AudioType.XMA:
|
||||||
case AudioType.VAG:
|
|
||||||
case AudioType.AUDIOQUEUE:
|
case AudioType.AUDIOQUEUE:
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
@@ -162,11 +161,7 @@ namespace AssetStudio
|
|||||||
case AudioCompressionFormat.Vorbis:
|
case AudioCompressionFormat.Vorbis:
|
||||||
case AudioCompressionFormat.ADPCM:
|
case AudioCompressionFormat.ADPCM:
|
||||||
case AudioCompressionFormat.MP3:
|
case AudioCompressionFormat.MP3:
|
||||||
case AudioCompressionFormat.VAG:
|
|
||||||
case AudioCompressionFormat.HEVAG:
|
|
||||||
case AudioCompressionFormat.XMA:
|
case AudioCompressionFormat.XMA:
|
||||||
case AudioCompressionFormat.GCADPCM:
|
|
||||||
case AudioCompressionFormat.ATRAC9:
|
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
using AssetStudio.PInvoke;
|
||||||
|
|
||||||
namespace FMOD
|
namespace FMOD
|
||||||
{
|
{
|
||||||
@@ -1587,6 +1588,12 @@ namespace FMOD
|
|||||||
*/
|
*/
|
||||||
public class Factory
|
public class Factory
|
||||||
{
|
{
|
||||||
|
|
||||||
|
static Factory()
|
||||||
|
{
|
||||||
|
DllLoader.PreloadDll(VERSION.dll);
|
||||||
|
}
|
||||||
|
|
||||||
public static RESULT System_Create(out System system)
|
public static RESULT System_Create(out System system)
|
||||||
{
|
{
|
||||||
system = null;
|
system = null;
|
||||||
|
|||||||
@@ -285,7 +285,11 @@ namespace AssetStudio
|
|||||||
}
|
}
|
||||||
|
|
||||||
iMesh.hasNormal = mesh.m_Normals?.Length > 0;
|
iMesh.hasNormal = mesh.m_Normals?.Length > 0;
|
||||||
iMesh.hasUV = mesh.m_UV0?.Length > 0;
|
iMesh.hasUV = new bool[8];
|
||||||
|
for (int uv = 0; uv < 8; uv++)
|
||||||
|
{
|
||||||
|
iMesh.hasUV[uv] = mesh.GetUV(uv)?.Length > 0;
|
||||||
|
}
|
||||||
iMesh.hasTangent = mesh.m_Tangents != null && mesh.m_Tangents.Length == mesh.m_VertexCount * 4;
|
iMesh.hasTangent = mesh.m_Tangents != null && mesh.m_Tangents.Length == mesh.m_VertexCount * 4;
|
||||||
iMesh.hasColor = mesh.m_Colors?.Length > 0;
|
iMesh.hasColor = mesh.m_Colors?.Length > 0;
|
||||||
|
|
||||||
@@ -335,17 +339,22 @@ namespace AssetStudio
|
|||||||
iVertex.Normal = new Vector3(-mesh.m_Normals[j * c], mesh.m_Normals[j * c + 1], mesh.m_Normals[j * c + 2]);
|
iVertex.Normal = new Vector3(-mesh.m_Normals[j * c], mesh.m_Normals[j * c + 1], mesh.m_Normals[j * c + 2]);
|
||||||
}
|
}
|
||||||
//UV
|
//UV
|
||||||
if (iMesh.hasUV)
|
iVertex.UV = new float[8][];
|
||||||
|
for (int uv = 0; uv < 8; uv++)
|
||||||
{
|
{
|
||||||
if (mesh.m_UV0.Length == mesh.m_VertexCount * 2)
|
if (iMesh.hasUV[uv])
|
||||||
{
|
{
|
||||||
c = 2;
|
var m_UV = mesh.GetUV(uv);
|
||||||
|
if (m_UV.Length == mesh.m_VertexCount * 2)
|
||||||
|
{
|
||||||
|
c = 2;
|
||||||
|
}
|
||||||
|
else if (m_UV.Length == mesh.m_VertexCount * 3)
|
||||||
|
{
|
||||||
|
c = 3;
|
||||||
|
}
|
||||||
|
iVertex.UV[uv] = new[] { m_UV[j * c], m_UV[j * c + 1] };
|
||||||
}
|
}
|
||||||
else if (mesh.m_UV0.Length == mesh.m_VertexCount * 3)
|
|
||||||
{
|
|
||||||
c = 3;
|
|
||||||
}
|
|
||||||
iVertex.UV = new[] { mesh.m_UV0[j * c], mesh.m_UV0[j * c + 1] };
|
|
||||||
}
|
}
|
||||||
//Tangent
|
//Tangent
|
||||||
if (iMesh.hasTangent)
|
if (iMesh.hasTangent)
|
||||||
|
|||||||
@@ -648,6 +648,15 @@ namespace AssetStudio
|
|||||||
}
|
}
|
||||||
sb.Append("}\n");
|
sb.Append("}\n");
|
||||||
}
|
}
|
||||||
|
if (m_LocalKeywords != null && m_LocalKeywords.Length > 0)
|
||||||
|
{
|
||||||
|
sb.Append("Local Keywords { ");
|
||||||
|
foreach (string keyword in m_LocalKeywords)
|
||||||
|
{
|
||||||
|
sb.Append($"\"{keyword}\" ");
|
||||||
|
}
|
||||||
|
sb.Append("}\n");
|
||||||
|
}
|
||||||
|
|
||||||
sb.Append("\"");
|
sb.Append("\"");
|
||||||
if (m_ProgramCode.Length > 0)
|
if (m_ProgramCode.Length > 0)
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ namespace AssetStudio
|
|||||||
{
|
{
|
||||||
public static class SpriteHelper
|
public static class SpriteHelper
|
||||||
{
|
{
|
||||||
public static Bitmap GetImageFromSprite(Sprite m_Sprite)
|
public static Bitmap GetImage(this Sprite m_Sprite)
|
||||||
{
|
{
|
||||||
if (m_Sprite.m_SpriteAtlas != null && m_Sprite.m_SpriteAtlas.TryGet(out var m_SpriteAtlas))
|
if (m_Sprite.m_SpriteAtlas != null && m_Sprite.m_SpriteAtlas.TryGet(out var m_SpriteAtlas))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -37,10 +37,10 @@ namespace AssetStudio
|
|||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
var handle = GCHandle.Alloc(buff, GCHandleType.Pinned);
|
var bitmap = new Bitmap(m_Width, m_Height, PixelFormat.Format32bppArgb);
|
||||||
var scan0 = handle.AddrOfPinnedObject();
|
var bmpData = bitmap.LockBits(new Rectangle(0, 0, m_Width, m_Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
|
||||||
var bitmap = new Bitmap(m_Width, m_Height, m_Width * 4, PixelFormat.Format32bppArgb, scan0);
|
Marshal.Copy(buff, 0, bmpData.Scan0, buff.Length);
|
||||||
handle.Free();
|
bitmap.UnlockBits(bmpData);
|
||||||
if (flip)
|
if (flip)
|
||||||
{
|
{
|
||||||
bitmap.RotateFlip(RotateFlipType.RotateNoneFlipY);
|
bitmap.RotateFlip(RotateFlipType.RotateNoneFlipY);
|
||||||
|
|||||||
@@ -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"Texture2DDecoder")];
|
|
||||||
[assembly:AssemblyDescriptionAttribute(L"")];
|
|
||||||
[assembly:AssemblyConfigurationAttribute(L"")];
|
|
||||||
[assembly:AssemblyCompanyAttribute(L"")];
|
|
||||||
[assembly:AssemblyProductAttribute(L"Texture2DDecoder")];
|
|
||||||
[assembly:AssemblyCopyrightAttribute(L"Copyright © Perfare 2020")];
|
|
||||||
[assembly:AssemblyTrademarkAttribute(L"")];
|
|
||||||
[assembly:AssemblyCultureAttribute(L"")];
|
|
||||||
|
|
||||||
[assembly:AssemblyVersionAttribute("1.0.*")];
|
|
||||||
|
|
||||||
[assembly:ComVisible(false)];
|
|
||||||
|
|
||||||
[assembly:CLSCompliantAttribute(true)];
|
|
||||||
@@ -1,148 +0,0 @@
|
|||||||
#include <string.h>
|
|
||||||
#include "Texture2DDecoder.h"
|
|
||||||
#include "bcn.h"
|
|
||||||
#include "pvrtc.h"
|
|
||||||
#include "etc.h"
|
|
||||||
#include "atc.h"
|
|
||||||
#include "astc.h"
|
|
||||||
#include "crunch.h"
|
|
||||||
#include "unitycrunch.h"
|
|
||||||
|
|
||||||
namespace Texture2DDecoder {
|
|
||||||
bool TextureDecoder::DecodeDXT1(array<Byte>^ data, long w, long h, array<Byte>^ image) {
|
|
||||||
pin_ptr<unsigned char> dataPin = &data[0];
|
|
||||||
pin_ptr<unsigned char> imagePin = &image[0];
|
|
||||||
return decode_bc1(dataPin, w, h, reinterpret_cast<uint32_t*>(imagePin));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TextureDecoder::DecodeDXT5(array<Byte>^ data, long w, long h, array<Byte>^ image) {
|
|
||||||
pin_ptr<unsigned char> dataPin = &data[0];
|
|
||||||
pin_ptr<unsigned char> imagePin = &image[0];
|
|
||||||
return decode_bc3(dataPin, w, h, reinterpret_cast<uint32_t*>(imagePin));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TextureDecoder::DecodePVRTC(array<Byte>^ data, long w, long h, array<Byte>^ image, bool is2bpp) {
|
|
||||||
pin_ptr<unsigned char> dataPin = &data[0];
|
|
||||||
pin_ptr<unsigned char> imagePin = &image[0];
|
|
||||||
return decode_pvrtc(dataPin, w, h, reinterpret_cast<uint32_t*>(imagePin), is2bpp ? 1 : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TextureDecoder::DecodeETC1(array<Byte>^ data, long w, long h, array<Byte>^ image) {
|
|
||||||
pin_ptr<unsigned char> dataPin = &data[0];
|
|
||||||
pin_ptr<unsigned char> imagePin = &image[0];
|
|
||||||
return decode_etc1(dataPin, w, h, reinterpret_cast<uint32_t*>(imagePin));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TextureDecoder::DecodeETC2(array<Byte>^ data, long w, long h, array<Byte>^ image) {
|
|
||||||
pin_ptr<unsigned char> dataPin = &data[0];
|
|
||||||
pin_ptr<unsigned char> imagePin = &image[0];
|
|
||||||
return decode_etc2(dataPin, w, h, reinterpret_cast<uint32_t*>(imagePin));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TextureDecoder::DecodeETC2A1(array<Byte>^ data, long w, long h, array<Byte>^ image) {
|
|
||||||
pin_ptr<unsigned char> dataPin = &data[0];
|
|
||||||
pin_ptr<unsigned char> imagePin = &image[0];
|
|
||||||
return decode_etc2a1(dataPin, w, h, reinterpret_cast<uint32_t*>(imagePin));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TextureDecoder::DecodeETC2A8(array<Byte>^ data, long w, long h, array<Byte>^ image) {
|
|
||||||
pin_ptr<unsigned char> dataPin = &data[0];
|
|
||||||
pin_ptr<unsigned char> imagePin = &image[0];
|
|
||||||
return decode_etc2a8(dataPin, w, h, reinterpret_cast<uint32_t*>(imagePin));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TextureDecoder::DecodeEACR(array<Byte>^ data, long w, long h, array<Byte>^ image) {
|
|
||||||
pin_ptr<unsigned char> dataPin = &data[0];
|
|
||||||
pin_ptr<unsigned char> imagePin = &image[0];
|
|
||||||
return decode_eacr(dataPin, w, h, reinterpret_cast<uint32_t*>(imagePin));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TextureDecoder::DecodeEACRSigned(array<Byte>^ data, long w, long h, array<Byte>^ image) {
|
|
||||||
pin_ptr<unsigned char> dataPin = &data[0];
|
|
||||||
pin_ptr<unsigned char> imagePin = &image[0];
|
|
||||||
return decode_eacr_signed(dataPin, w, h, reinterpret_cast<uint32_t*>(imagePin));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TextureDecoder::DecodeEACRG(array<Byte>^ data, long w, long h, array<Byte>^ image) {
|
|
||||||
pin_ptr<unsigned char> dataPin = &data[0];
|
|
||||||
pin_ptr<unsigned char> imagePin = &image[0];
|
|
||||||
return decode_eacrg(dataPin, w, h, reinterpret_cast<uint32_t*>(imagePin));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TextureDecoder::DecodeEACRGSigned(array<Byte>^ data, long w, long h, array<Byte>^ image) {
|
|
||||||
pin_ptr<unsigned char> dataPin = &data[0];
|
|
||||||
pin_ptr<unsigned char> imagePin = &image[0];
|
|
||||||
return decode_eacrg_signed(dataPin, w, h, reinterpret_cast<uint32_t*>(imagePin));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TextureDecoder::DecodeBC4(array<Byte>^ data, long w, long h, array<Byte>^ image) {
|
|
||||||
pin_ptr<unsigned char> dataPin = &data[0];
|
|
||||||
pin_ptr<unsigned char> imagePin = &image[0];
|
|
||||||
return decode_bc4(dataPin, w, h, reinterpret_cast<uint32_t*>(imagePin));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TextureDecoder::DecodeBC5(array<Byte>^ data, long w, long h, array<Byte>^ image) {
|
|
||||||
pin_ptr<unsigned char> dataPin = &data[0];
|
|
||||||
pin_ptr<unsigned char> imagePin = &image[0];
|
|
||||||
return decode_bc5(dataPin, w, h, reinterpret_cast<uint32_t*>(imagePin));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TextureDecoder::DecodeBC6(array<Byte>^ data, long w, long h, array<Byte>^ image) {
|
|
||||||
pin_ptr<unsigned char> dataPin = &data[0];
|
|
||||||
pin_ptr<unsigned char> imagePin = &image[0];
|
|
||||||
return decode_bc6(dataPin, w, h, reinterpret_cast<uint32_t*>(imagePin));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TextureDecoder::DecodeBC7(array<Byte>^ data, long w, long h, array<Byte>^ image) {
|
|
||||||
pin_ptr<unsigned char> dataPin = &data[0];
|
|
||||||
pin_ptr<unsigned char> imagePin = &image[0];
|
|
||||||
return decode_bc7(dataPin, w, h, reinterpret_cast<uint32_t*>(imagePin));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TextureDecoder::DecodeATCRGB4(array<Byte>^ data, long w, long h, array<Byte>^ image) {
|
|
||||||
pin_ptr<unsigned char> dataPin = &data[0];
|
|
||||||
pin_ptr<unsigned char> imagePin = &image[0];
|
|
||||||
return decode_atc_rgb4(dataPin, w, h, reinterpret_cast<uint32_t*>(imagePin));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TextureDecoder::DecodeATCRGBA8(array<Byte>^ data, long w, long h, array<Byte>^ image) {
|
|
||||||
pin_ptr<unsigned char> dataPin = &data[0];
|
|
||||||
pin_ptr<unsigned char> imagePin = &image[0];
|
|
||||||
return decode_atc_rgba8(dataPin, w, h, reinterpret_cast<uint32_t*>(imagePin));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TextureDecoder::DecodeASTC(array<Byte>^ data, long w, long h, int bw, int bh, array<Byte>^ image) {
|
|
||||||
pin_ptr<unsigned char> dataPin = &data[0];
|
|
||||||
pin_ptr<unsigned char> imagePin = &image[0];
|
|
||||||
return decode_astc(dataPin, w, h, bw, bh, reinterpret_cast<uint32_t*>(imagePin));
|
|
||||||
}
|
|
||||||
|
|
||||||
array<Byte>^ TextureDecoder::UnpackCrunch(array<Byte>^ data) {
|
|
||||||
pin_ptr<unsigned char> dataPin = &data[0];
|
|
||||||
void* ret;
|
|
||||||
uint32_t retSize;
|
|
||||||
if (!crunch_unpack_level(dataPin, data->Length, 0, &ret, &retSize)) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
auto buff = gcnew array<Byte>(retSize);
|
|
||||||
pin_ptr<unsigned char> buffPin = &buff[0];
|
|
||||||
memcpy(buffPin, ret, retSize);
|
|
||||||
delete ret;
|
|
||||||
return buff;
|
|
||||||
}
|
|
||||||
|
|
||||||
array<Byte>^ TextureDecoder::UnpackUnityCrunch(array<Byte>^ data) {
|
|
||||||
pin_ptr<unsigned char> dataPin = &data[0];
|
|
||||||
void* ret;
|
|
||||||
uint32_t retSize;
|
|
||||||
if (!unity_crunch_unpack_level(dataPin, data->Length, 0, &ret, &retSize)) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
auto buff = gcnew array<Byte>(retSize);
|
|
||||||
pin_ptr<unsigned char> buffPin = &buff[0];
|
|
||||||
memcpy(buffPin, ret, retSize);
|
|
||||||
delete ret;
|
|
||||||
return buff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
using namespace System;
|
|
||||||
|
|
||||||
namespace Texture2DDecoder {
|
|
||||||
public ref class TextureDecoder
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static bool DecodeDXT1(array<Byte>^ data, long w, long h, array<Byte>^ image);
|
|
||||||
static bool DecodeDXT5(array<Byte>^ data, long w, long h, array<Byte>^ image);
|
|
||||||
static bool DecodePVRTC(array<Byte>^ data, long w, long h, array<Byte>^ image, bool is2bpp);
|
|
||||||
static bool DecodeETC1(array<Byte>^ data, long w, long h, array<Byte>^ image);
|
|
||||||
static bool DecodeETC2(array<Byte>^ data, long w, long h, array<Byte>^ image);
|
|
||||||
static bool DecodeETC2A1(array<Byte>^ data, long w, long h, array<Byte>^ image);
|
|
||||||
static bool DecodeETC2A8(array<Byte>^ data, long w, long h, array<Byte>^ image);
|
|
||||||
static bool DecodeEACR(array<Byte>^ data, long w, long h, array<Byte>^ image);
|
|
||||||
static bool DecodeEACRSigned(array<Byte>^ data, long w, long h, array<Byte>^ image);
|
|
||||||
static bool DecodeEACRG(array<Byte>^ data, long w, long h, array<Byte>^ image);
|
|
||||||
static bool DecodeEACRGSigned(array<Byte>^ data, long w, long h, array<Byte>^ image);
|
|
||||||
static bool DecodeBC4(array<Byte>^ data, long w, long h, array<Byte>^ image);
|
|
||||||
static bool DecodeBC5(array<Byte>^ data, long w, long h, array<Byte>^ image);
|
|
||||||
static bool DecodeBC6(array<Byte>^ data, long w, long h, array<Byte>^ image);
|
|
||||||
static bool DecodeBC7(array<Byte>^ data, long w, long h, array<Byte>^ image);
|
|
||||||
static bool DecodeATCRGB4(array<Byte>^ data, long w, long h, array<Byte>^ image);
|
|
||||||
static bool DecodeATCRGBA8(array<Byte>^ data, long w, long h, array<Byte>^ image);
|
|
||||||
static bool DecodeASTC(array<Byte>^ data, long w, long h, int bw, int bh, array<Byte>^ image);
|
|
||||||
static array<Byte>^ UnpackCrunch(array<Byte>^ data);
|
|
||||||
static array<Byte>^ UnpackUnityCrunch(array<Byte>^ data);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -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", "Texture2DDecoderNative"
|
||||||
|
VALUE "FileVersion", "1.0.0.1"
|
||||||
|
VALUE "InternalName", "Texture2DDecoderNative.dll"
|
||||||
|
VALUE "LegalCopyright", "Copyright (C) Perfare 2020; Copyright (C) hozuki 2020"
|
||||||
|
VALUE "OriginalFilename", "Texture2DDecoderNative.dll"
|
||||||
|
VALUE "ProductName", "Texture2DDecoderNative"
|
||||||
|
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
|
||||||
|
|
||||||
+118
-60
@@ -18,41 +18,76 @@
|
|||||||
<Platform>x64</Platform>
|
<Platform>x64</Platform>
|
||||||
</ProjectConfiguration>
|
</ProjectConfiguration>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="astc.h" />
|
||||||
|
<ClInclude Include="atc.h" />
|
||||||
|
<ClInclude Include="bcn.h" />
|
||||||
|
<ClInclude Include="bool32_t.h" />
|
||||||
|
<ClInclude Include="color.h" />
|
||||||
|
<ClInclude Include="crunch.h" />
|
||||||
|
<ClInclude Include="crunch\crnlib.h" />
|
||||||
|
<ClInclude Include="crunch\crn_decomp.h" />
|
||||||
|
<ClInclude Include="dllexport.h" />
|
||||||
|
<ClInclude Include="endianness.h" />
|
||||||
|
<ClInclude Include="etc.h" />
|
||||||
|
<ClInclude Include="fp16.h" />
|
||||||
|
<ClInclude Include="fp16\bitcasts.h" />
|
||||||
|
<ClInclude Include="fp16\fp16.h" />
|
||||||
|
<ClInclude Include="pvrtc.h" />
|
||||||
|
<ClInclude Include="resource.h" />
|
||||||
|
<ClInclude Include="unitycrunch.h" />
|
||||||
|
<ClInclude Include="unitycrunch\crnlib.h" />
|
||||||
|
<ClInclude Include="unitycrunch\crn_decomp.h" />
|
||||||
|
<ClInclude Include="unitycrunch\crn_defs.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="astc.cpp" />
|
||||||
|
<ClCompile Include="atc.cpp" />
|
||||||
|
<ClCompile Include="bcn.cpp" />
|
||||||
|
<ClCompile Include="crunch.cpp" />
|
||||||
|
<ClCompile Include="dllmain.cpp" />
|
||||||
|
<ClCompile Include="etc.cpp" />
|
||||||
|
<ClCompile Include="pvrtc.cpp" />
|
||||||
|
<ClCompile Include="unitycrunch.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="cpp.hint" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ResourceCompile Include="Texture2DDecoderNative.rc" />
|
||||||
|
</ItemGroup>
|
||||||
<PropertyGroup Label="Globals">
|
<PropertyGroup Label="Globals">
|
||||||
<VCProjectVersion>16.0</VCProjectVersion>
|
<VCProjectVersion>16.0</VCProjectVersion>
|
||||||
<ProjectGuid>{BEC7B5E6-0A7B-4824-97A7-EEA04D9EBA29}</ProjectGuid>
|
<Keyword>Win32Proj</Keyword>
|
||||||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
<ProjectGuid>{29356642-c46e-4144-83d8-22dc09d0d7fd}</ProjectGuid>
|
||||||
<Keyword>ManagedCProj</Keyword>
|
<RootNamespace>Texture2DDecoderNative</RootNamespace>
|
||||||
<RootNamespace>Texture2DDecoder</RootNamespace>
|
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||||
<WindowsTargetPlatformVersion>10.0.18362.0</WindowsTargetPlatformVersion>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
<PlatformToolset>v141</PlatformToolset>
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
<CLRSupport>true</CLRSupport>
|
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
<PlatformToolset>v141</PlatformToolset>
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
<CLRSupport>true</CLRSupport>
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
<PlatformToolset>v141</PlatformToolset>
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
<CLRSupport>true</CLRSupport>
|
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
<PlatformToolset>v141</PlatformToolset>
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
<CLRSupport>true</CLRSupport>
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
@@ -73,75 +108,98 @@
|
|||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
<PropertyGroup Label="UserMacros" />
|
<PropertyGroup Label="UserMacros" />
|
||||||
<PropertyGroup />
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
<OutDir>bin\$(Platform)\$(Configuration)\</OutDir>
|
||||||
|
<IntDir>obj\$(Platform)\$(Configuration)\</IntDir>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
<OutDir>bin\$(Platform)\$(Configuration)\</OutDir>
|
||||||
|
<IntDir>obj\$(Platform)\$(Configuration)\</IntDir>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
<OutDir>bin\$(Platform)\$(Configuration)\</OutDir>
|
||||||
|
<IntDir>obj\$(Platform)\$(Configuration)\</IntDir>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
<OutDir>bin\$(Platform)\$(Configuration)\</OutDir>
|
||||||
|
<IntDir>obj\$(Platform)\$(Configuration)\</IntDir>
|
||||||
|
</PropertyGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<WarningLevel>Level3</WarningLevel>
|
<WarningLevel>Level3</WarningLevel>
|
||||||
<PreprocessorDefinitions>WIN32;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>_T2D_DLL;WIN32;_DEBUG;TEXTURE2DDECODERNATIVE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||||
|
<PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<AdditionalDependencies />
|
<SubSystem>Windows</SubSystem>
|
||||||
</Link>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
</ItemDefinitionGroup>
|
<EnableUAC>false</EnableUAC>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
|
||||||
<ClCompile>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<AdditionalDependencies />
|
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<WarningLevel>Level3</WarningLevel>
|
<WarningLevel>Level3</WarningLevel>
|
||||||
<PreprocessorDefinitions>WIN32;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>_T2D_DLL;WIN32;NDEBUG;TEXTURE2DDECODERNATIVE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||||
|
<PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<AdditionalDependencies />
|
<SubSystem>Windows</SubSystem>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<EnableUAC>false</EnableUAC>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>_T2D_DLL;_DEBUG;TEXTURE2DDECODERNATIVE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||||
|
<PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Windows</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<EnableUAC>false</EnableUAC>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<WarningLevel>Level3</WarningLevel>
|
<WarningLevel>Level3</WarningLevel>
|
||||||
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>_T2D_DLL;NDEBUG;TEXTURE2DDECODERNATIVE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||||
|
<PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<AdditionalDependencies />
|
<SubSystem>Windows</SubSystem>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<EnableUAC>false</EnableUAC>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
|
||||||
<ClInclude Include="astc.h" />
|
|
||||||
<ClInclude Include="atc.h" />
|
|
||||||
<ClInclude Include="bcn.h" />
|
|
||||||
<ClInclude Include="color.h" />
|
|
||||||
<ClInclude Include="crunch.h" />
|
|
||||||
<ClInclude Include="crunch\crnlib.h" />
|
|
||||||
<ClInclude Include="crunch\crn_decomp.h" />
|
|
||||||
<ClInclude Include="endianness.h" />
|
|
||||||
<ClInclude Include="etc.h" />
|
|
||||||
<ClInclude Include="fp16.h" />
|
|
||||||
<ClInclude Include="fp16\bitcasts.h" />
|
|
||||||
<ClInclude Include="fp16\fp16.h" />
|
|
||||||
<ClInclude Include="pvrtc.h" />
|
|
||||||
<ClInclude Include="Texture2DDecoder.h" />
|
|
||||||
<ClInclude Include="unitycrunch.h" />
|
|
||||||
<ClInclude Include="unitycrunch\crnlib.h" />
|
|
||||||
<ClInclude Include="unitycrunch\crn_decomp.h" />
|
|
||||||
<ClInclude Include="unitycrunch\crn_defs.h" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClCompile Include="AssemblyInfo.cpp" />
|
|
||||||
<ClCompile Include="astc.cpp" />
|
|
||||||
<ClCompile Include="atc.cpp" />
|
|
||||||
<ClCompile Include="bcn.cpp" />
|
|
||||||
<ClCompile Include="crunch.cpp" />
|
|
||||||
<ClCompile Include="etc.cpp" />
|
|
||||||
<ClCompile Include="pvrtc.cpp" />
|
|
||||||
<ClCompile Include="Texture2DDecoder.cpp" />
|
|
||||||
<ClCompile Include="unitycrunch.cpp" />
|
|
||||||
</ItemGroup>
|
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
|
<Target Name="AfterBuild">
|
||||||
|
<MSBuild Condition=" '$(Platform)' == 'Win32' " Projects="$(MSBuildProjectFile)" Properties="Platform=x64;PlatFormTarget=x64" RunEachTargetSeparately="true" />
|
||||||
|
</Target>
|
||||||
</Project>
|
</Project>
|
||||||
+40
-29
@@ -15,6 +15,33 @@
|
|||||||
</Filter>
|
</Filter>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClInclude Include="pvrtc.h">
|
||||||
|
<Filter>头文件</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="unitycrunch.h">
|
||||||
|
<Filter>头文件</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="crunch\crnlib.h">
|
||||||
|
<Filter>头文件</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="crunch\crn_decomp.h">
|
||||||
|
<Filter>头文件</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="fp16\bitcasts.h">
|
||||||
|
<Filter>头文件</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="fp16\fp16.h">
|
||||||
|
<Filter>头文件</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="unitycrunch\crnlib.h">
|
||||||
|
<Filter>头文件</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="unitycrunch\crn_decomp.h">
|
||||||
|
<Filter>头文件</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="unitycrunch\crn_defs.h">
|
||||||
|
<Filter>头文件</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="astc.h">
|
<ClInclude Include="astc.h">
|
||||||
<Filter>头文件</Filter>
|
<Filter>头文件</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
@@ -39,39 +66,18 @@
|
|||||||
<ClInclude Include="fp16.h">
|
<ClInclude Include="fp16.h">
|
||||||
<Filter>头文件</Filter>
|
<Filter>头文件</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="pvrtc.h">
|
<ClInclude Include="dllexport.h">
|
||||||
<Filter>头文件</Filter>
|
<Filter>头文件</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="Texture2DDecoder.h">
|
<ClInclude Include="bool32_t.h">
|
||||||
<Filter>头文件</Filter>
|
<Filter>头文件</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="unitycrunch.h">
|
<ClInclude Include="resource.h">
|
||||||
<Filter>头文件</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="crunch\crn_decomp.h">
|
|
||||||
<Filter>头文件</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="crunch\crnlib.h">
|
|
||||||
<Filter>头文件</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="fp16\bitcasts.h">
|
|
||||||
<Filter>头文件</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="fp16\fp16.h">
|
|
||||||
<Filter>头文件</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="unitycrunch\crn_decomp.h">
|
|
||||||
<Filter>头文件</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="unitycrunch\crn_defs.h">
|
|
||||||
<Filter>头文件</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="unitycrunch\crnlib.h">
|
|
||||||
<Filter>头文件</Filter>
|
<Filter>头文件</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="AssemblyInfo.cpp">
|
<ClCompile Include="unitycrunch.cpp">
|
||||||
<Filter>源文件</Filter>
|
<Filter>源文件</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="astc.cpp">
|
<ClCompile Include="astc.cpp">
|
||||||
@@ -92,11 +98,16 @@
|
|||||||
<ClCompile Include="pvrtc.cpp">
|
<ClCompile Include="pvrtc.cpp">
|
||||||
<Filter>源文件</Filter>
|
<Filter>源文件</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="Texture2DDecoder.cpp">
|
<ClCompile Include="dllmain.cpp">
|
||||||
<Filter>源文件</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="unitycrunch.cpp">
|
|
||||||
<Filter>源文件</Filter>
|
<Filter>源文件</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="cpp.hint" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ResourceCompile Include="Texture2DDecoderNative.rc">
|
||||||
|
<Filter>资源文件</Filter>
|
||||||
|
</ResourceCompile>
|
||||||
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
typedef uint32_t bool32_t;
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
#define T2D_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 _T2D_DLL
|
||||||
|
#ifdef __GNUC__
|
||||||
|
#define _T2D_EXPORT __attribute__ ((dllexport))
|
||||||
|
#else
|
||||||
|
#define _T2D_EXPORT __declspec(dllexport)
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#ifdef __GNUC__
|
||||||
|
#define _T2D_EXPORT __attribute__ ((dllimport))
|
||||||
|
#else
|
||||||
|
#define _T2D_EXPORT __declspec(dllimport)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#define _T2D_LOCAL
|
||||||
|
#else
|
||||||
|
#if __GNUC__ >= 4
|
||||||
|
#define _T2D_EXPORT __attribute__ ((visibility ("default")))
|
||||||
|
#define _T2D_LOCAL __attribute__ ((visibility ("hidden")))
|
||||||
|
#else
|
||||||
|
#define _T2D_EXPORT
|
||||||
|
#define _T2D_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 _T2D_CALL
|
||||||
|
#if defined(WIN32) || defined(_WIN32)
|
||||||
|
#define _T2D_CALL __stdcall
|
||||||
|
#else
|
||||||
|
#define _T2D_CALL /* __cdecl */
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#define T2D_API(ret_type) _EXTERN_C_STMT _T2D_EXPORT ret_type _T2D_CALL
|
||||||
|
#else
|
||||||
|
#define T2D_API(ret_type) _EXTERN_C_STMT _T2D_EXPORT _T2D_CALL ret_type
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,174 @@
|
|||||||
|
#include "dllexport.h"
|
||||||
|
#include "bool32_t.h"
|
||||||
|
|
||||||
|
#include "bcn.h"
|
||||||
|
#include "pvrtc.h"
|
||||||
|
#include "etc.h"
|
||||||
|
#include "atc.h"
|
||||||
|
#include "astc.h"
|
||||||
|
#include "crunch.h"
|
||||||
|
#include "unitycrunch.h"
|
||||||
|
|
||||||
|
T2D_API(bool32_t) DecodeDXT1(const void* data, int32_t width, int32_t height, void* image)
|
||||||
|
{
|
||||||
|
return decode_bc1(static_cast<const uint8_t*>(data), width, height, static_cast<uint32_t*>(image));
|
||||||
|
}
|
||||||
|
|
||||||
|
T2D_API(bool32_t) DecodeDXT5(const void* data, int32_t width, int32_t height, void* image)
|
||||||
|
{
|
||||||
|
return decode_bc3(static_cast<const uint8_t*>(data), width, height, static_cast<uint32_t*>(image));
|
||||||
|
}
|
||||||
|
|
||||||
|
T2D_API(bool32_t) DecodePVRTC(const void* data, int32_t width, int32_t height, void* image, bool32_t is2bpp)
|
||||||
|
{
|
||||||
|
return decode_pvrtc(static_cast<const uint8_t*>(data), width, height, static_cast<uint32_t*>(image), is2bpp ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
T2D_API(bool32_t) DecodeETC1(const void* data, int32_t width, int32_t height, void* image)
|
||||||
|
{
|
||||||
|
return decode_etc1(static_cast<const uint8_t*>(data), width, height, static_cast<uint32_t*>(image));
|
||||||
|
}
|
||||||
|
|
||||||
|
T2D_API(bool32_t) DecodeETC2(const void* data, int32_t width, int32_t height, void* image)
|
||||||
|
{
|
||||||
|
return decode_etc2(static_cast<const uint8_t*>(data), width, height, static_cast<uint32_t*>(image));
|
||||||
|
}
|
||||||
|
|
||||||
|
T2D_API(bool32_t) DecodeETC2A1(const void* data, int32_t width, int32_t height, void* image)
|
||||||
|
{
|
||||||
|
return decode_etc2a1(static_cast<const uint8_t*>(data), width, height, static_cast<uint32_t*>(image));
|
||||||
|
}
|
||||||
|
|
||||||
|
T2D_API(bool32_t) DecodeETC2A8(const void* data, int32_t width, int32_t height, void* image)
|
||||||
|
{
|
||||||
|
return decode_etc2a8(static_cast<const uint8_t*>(data), width, height, static_cast<uint32_t*>(image));
|
||||||
|
}
|
||||||
|
|
||||||
|
T2D_API(bool32_t) DecodeEACR(const void* data, int32_t width, int32_t height, void* image)
|
||||||
|
{
|
||||||
|
return decode_eacr(static_cast<const uint8_t*>(data), width, height, static_cast<uint32_t*>(image));
|
||||||
|
}
|
||||||
|
|
||||||
|
T2D_API(bool32_t) DecodeEACRSigned(const void* data, int32_t width, int32_t height, void* image)
|
||||||
|
{
|
||||||
|
return decode_eacr_signed(static_cast<const uint8_t*>(data), width, height, static_cast<uint32_t*>(image));
|
||||||
|
}
|
||||||
|
|
||||||
|
T2D_API(bool32_t) DecodeEACRG(const void* data, int32_t width, int32_t height, void* image)
|
||||||
|
{
|
||||||
|
return decode_eacrg(static_cast<const uint8_t*>(data), width, height, static_cast<uint32_t*>(image));
|
||||||
|
}
|
||||||
|
|
||||||
|
T2D_API(bool32_t) DecodeEACRGSigned(const void* data, int32_t width, int32_t height, void* image)
|
||||||
|
{
|
||||||
|
return decode_eacrg_signed(static_cast<const uint8_t*>(data), width, height, static_cast<uint32_t*>(image));
|
||||||
|
}
|
||||||
|
|
||||||
|
T2D_API(bool32_t) DecodeBC4(const void* data, int32_t width, int32_t height, void* image)
|
||||||
|
{
|
||||||
|
return decode_bc4(static_cast<const uint8_t*>(data), width, height, static_cast<uint32_t*>(image));
|
||||||
|
}
|
||||||
|
|
||||||
|
T2D_API(bool32_t) DecodeBC5(const void* data, int32_t width, int32_t height, void* image)
|
||||||
|
{
|
||||||
|
return decode_bc5(static_cast<const uint8_t*>(data), width, height, static_cast<uint32_t*>(image));
|
||||||
|
}
|
||||||
|
|
||||||
|
T2D_API(bool32_t) DecodeBC6(const void* data, int32_t width, int32_t height, void* image)
|
||||||
|
{
|
||||||
|
return decode_bc6(static_cast<const uint8_t*>(data), width, height, static_cast<uint32_t*>(image));
|
||||||
|
}
|
||||||
|
|
||||||
|
T2D_API(bool32_t) DecodeBC7(const void* data, int32_t width, int32_t height, void* image)
|
||||||
|
{
|
||||||
|
return decode_bc7(static_cast<const uint8_t*>(data), width, height, static_cast<uint32_t*>(image));
|
||||||
|
}
|
||||||
|
|
||||||
|
T2D_API(bool32_t) DecodeATCRGB4(const void* data, int32_t width, int32_t height, void* image)
|
||||||
|
{
|
||||||
|
return decode_atc_rgb4(static_cast<const uint8_t*>(data), width, height, static_cast<uint32_t*>(image));
|
||||||
|
}
|
||||||
|
|
||||||
|
T2D_API(bool32_t) DecodeATCRGBA8(const void* data, int32_t width, int32_t height, void* image)
|
||||||
|
{
|
||||||
|
return decode_atc_rgba8(static_cast<const uint8_t*>(data), width, height, static_cast<uint32_t*>(image));
|
||||||
|
}
|
||||||
|
|
||||||
|
T2D_API(bool32_t) DecodeASTC(const void* data, int32_t width, int32_t height, int32_t blockWidth, int32_t blockHeight, void* image)
|
||||||
|
{
|
||||||
|
return decode_astc(static_cast<const uint8_t*>(data), width, height, blockWidth, blockHeight, static_cast<uint32_t*>(image));
|
||||||
|
}
|
||||||
|
|
||||||
|
T2D_API(void) DisposeBuffer(void** ppBuffer)
|
||||||
|
{
|
||||||
|
if (ppBuffer == nullptr)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ppTypedBuffer = reinterpret_cast<uint8_t**>(ppBuffer);
|
||||||
|
|
||||||
|
delete[](*ppTypedBuffer);
|
||||||
|
|
||||||
|
*ppBuffer = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
T2D_API(void) UnpackCrunch(const void* data, uint32_t dataSize, void** ppResult, uint32_t* pResultSize)
|
||||||
|
{
|
||||||
|
void* result;
|
||||||
|
uint32_t resultSize;
|
||||||
|
|
||||||
|
if (ppResult != nullptr)
|
||||||
|
{
|
||||||
|
*ppResult = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pResultSize != nullptr)
|
||||||
|
{
|
||||||
|
*pResultSize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!crunch_unpack_level(static_cast<const uint8_t*>(data), dataSize, 0, &result, &resultSize)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ppResult != nullptr)
|
||||||
|
{
|
||||||
|
*ppResult = result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pResultSize != nullptr)
|
||||||
|
{
|
||||||
|
*pResultSize = resultSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
T2D_API(void) UnpackUnityCrunch(const void* data, uint32_t dataSize, void** ppResult, uint32_t* pResultSize)
|
||||||
|
{
|
||||||
|
void* result;
|
||||||
|
uint32_t resultSize;
|
||||||
|
|
||||||
|
if (ppResult != nullptr)
|
||||||
|
{
|
||||||
|
*ppResult = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pResultSize != nullptr)
|
||||||
|
{
|
||||||
|
*pResultSize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!unity_crunch_unpack_level(static_cast<const uint8_t*>(data), dataSize, 0, &result, &resultSize)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ppResult != nullptr)
|
||||||
|
{
|
||||||
|
*ppResult = result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pResultSize != nullptr)
|
||||||
|
{
|
||||||
|
*pResultSize = resultSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
//{{NO_DEPENDENCIES}}
|
||||||
|
// Microsoft Visual C++ generated include file.
|
||||||
|
// Used by Texture2DDecoderNative.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,19 @@
|
|||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
[assembly: AssemblyTitle("Texture2DDecoder")]
|
||||||
|
[assembly: AssemblyDescription("")]
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("")]
|
||||||
|
[assembly: AssemblyProduct("Texture2DDecoder")]
|
||||||
|
[assembly: AssemblyCopyright("Copyright © Perfare 2020; Copyright © hozuki 2020")]
|
||||||
|
[assembly: AssemblyTrademark("")]
|
||||||
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
||||||
|
[assembly: ComVisible(false)]
|
||||||
|
|
||||||
|
[assembly: Guid("2afce830-b463-49b3-a026-877e5eafc0a4")]
|
||||||
|
|
||||||
|
[assembly: AssemblyVersion("1.0.0.0")]
|
||||||
|
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user