Compare commits
26 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6d3875cb2c | ||
|
|
be4ced77ea | ||
|
|
2bd762e8f4 | ||
|
|
a926644ff6 | ||
|
|
a4cdff5934 | ||
|
|
2e10e627b0 | ||
|
|
e216abd6be | ||
|
|
93c7e617d8 | ||
|
|
000916913e | ||
|
|
28f9744497 | ||
|
|
c3f99216b6 | ||
|
|
19c4835ea3 | ||
|
|
6b321da695 | ||
|
|
7cca301f7a | ||
|
|
5ac597c935 | ||
|
|
171962e61f | ||
|
|
c8a21838c9 | ||
|
|
cf67815d53 | ||
|
|
94c8b355fe | ||
|
|
4e41caf203 | ||
|
|
74a8555514 | ||
|
|
e1d883adf6 | ||
|
|
9784df0e16 | ||
|
|
4d919a2bfe | ||
|
|
6701f467b7 | ||
|
|
50f5da5554 |
@@ -3,7 +3,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>net472;net6.0;net6.0-windows;net7.0;net7.0-windows</TargetFrameworks>
|
<TargetFrameworks>net472;net6.0;net6.0-windows;net7.0;net7.0-windows</TargetFrameworks>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<Version>0.17.1.0</Version>
|
<Version>0.17.3.0</Version>
|
||||||
<Copyright>Copyright © Perfare 2020-2022; Copyright © hozuki 2020</Copyright>
|
<Copyright>Copyright © Perfare 2020-2022; Copyright © hozuki 2020</Copyright>
|
||||||
<DebugType>embedded</DebugType>
|
<DebugType>embedded</DebugType>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|||||||
@@ -2,13 +2,13 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>net472;net6.0;net6.0-windows;net7.0;net7.0-windows</TargetFrameworks>
|
<TargetFrameworks>net472;net6.0;net6.0-windows;net7.0;net7.0-windows</TargetFrameworks>
|
||||||
<Version>0.17.1.0</Version>
|
<Version>0.17.3.0</Version>
|
||||||
<Copyright>Copyright © Perfare 2018-2022</Copyright>
|
<Copyright>Copyright © Perfare 2018-2022; Copyright © aelurum 2023</Copyright>
|
||||||
<DebugType>embedded</DebugType>
|
<DebugType>embedded</DebugType>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup Condition=" '$(TargetFramework)' != 'net472' ">
|
<ItemGroup Condition=" '$(TargetFramework)' != 'net472' ">
|
||||||
<PackageReference Include="K4os.Compression.LZ4" Version="1.3.5" />
|
<PackageReference Include="K4os.Compression.LZ4" Version="1.3.6" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup Condition=" '$(TargetFramework)' == 'net472' ">
|
<ItemGroup Condition=" '$(TargetFramework)' == 'net472' ">
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ namespace AssetStudio
|
|||||||
{
|
{
|
||||||
public string SpecifyUnityVersion;
|
public string SpecifyUnityVersion;
|
||||||
public List<SerializedFile> assetsFileList = new List<SerializedFile>();
|
public List<SerializedFile> assetsFileList = new List<SerializedFile>();
|
||||||
private List<ClassIDType> filteredAssetTypesList = new List<ClassIDType>();
|
private HashSet<ClassIDType> filteredAssetTypesList = new HashSet<ClassIDType>();
|
||||||
|
|
||||||
internal Dictionary<string, int> assetsFileIndexCache = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
|
internal Dictionary<string, int> assetsFileIndexCache = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
|
||||||
internal Dictionary<string, BinaryReader> resourceFileReaders = new Dictionary<string, BinaryReader>(StringComparer.OrdinalIgnoreCase);
|
internal Dictionary<string, BinaryReader> resourceFileReaders = new Dictionary<string, BinaryReader>(StringComparer.OrdinalIgnoreCase);
|
||||||
@@ -22,35 +22,32 @@ namespace AssetStudio
|
|||||||
private HashSet<string> noexistFiles = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
private HashSet<string> noexistFiles = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||||
private HashSet<string> assetsFileListHash = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
private HashSet<string> assetsFileListHash = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
public void SetAssetFilter(ClassIDType classIDType)
|
public void SetAssetFilter(params ClassIDType[] classIDTypes)
|
||||||
{
|
{
|
||||||
if (filteredAssetTypesList.Count == 0)
|
if (filteredAssetTypesList.Count == 0)
|
||||||
{
|
{
|
||||||
filteredAssetTypesList.AddRange(new List<ClassIDType>
|
filteredAssetTypesList.UnionWith(new HashSet<ClassIDType>
|
||||||
{
|
{
|
||||||
ClassIDType.AssetBundle,
|
ClassIDType.AssetBundle,
|
||||||
ClassIDType.ResourceManager,
|
ClassIDType.ResourceManager,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (classIDType == ClassIDType.MonoBehaviour)
|
if (classIDTypes.Contains(ClassIDType.MonoBehaviour))
|
||||||
{
|
{
|
||||||
filteredAssetTypesList.AddRange(new List<ClassIDType>
|
filteredAssetTypesList.Add(ClassIDType.MonoScript);
|
||||||
{
|
|
||||||
ClassIDType.MonoScript,
|
|
||||||
ClassIDType.MonoBehaviour
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
else
|
if (classIDTypes.Contains(ClassIDType.Sprite))
|
||||||
{
|
{
|
||||||
filteredAssetTypesList.Add(classIDType);
|
filteredAssetTypesList.Add(ClassIDType.Texture2D);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
filteredAssetTypesList.UnionWith(classIDTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetAssetFilter(List<ClassIDType> classIDTypeList)
|
public void SetAssetFilter(List<ClassIDType> classIDTypeList)
|
||||||
{
|
{
|
||||||
foreach (ClassIDType classIDType in classIDTypeList)
|
SetAssetFilter(classIDTypeList.ToArray());
|
||||||
SetAssetFilter(classIDType);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LoadFilesAndFolders(params string[] path)
|
public void LoadFilesAndFolders(params string[] path)
|
||||||
|
|||||||
@@ -91,7 +91,14 @@ namespace AssetStudio
|
|||||||
}
|
}
|
||||||
if (version[0] > 2019 || (version[0] == 2019 && version[1] >= 3)) //2019.3 and up
|
if (version[0] > 2019 || (version[0] == 2019 && version[1] >= 3)) //2019.3 and up
|
||||||
{
|
{
|
||||||
var m_IgnoreMasterTextureLimit = reader.ReadBoolean();
|
if (version[0] > 2022 || (version[0] == 2022 && version[1] >= 2)) //2022.2 and up
|
||||||
|
{
|
||||||
|
var m_IgnoreMipmapLimit = reader.ReadBoolean();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var m_IgnoreMasterTextureLimit = reader.ReadBoolean();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (version[0] >= 3) //3.0.0 - 5.4
|
if (version[0] >= 3) //3.0.0 - 5.4
|
||||||
{
|
{
|
||||||
@@ -100,6 +107,11 @@ namespace AssetStudio
|
|||||||
var m_ReadAllowed = reader.ReadBoolean();
|
var m_ReadAllowed = reader.ReadBoolean();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (version[0] > 2022 || (version[0] == 2022 && version[1] >= 2)) //2022.2 and up
|
||||||
|
{
|
||||||
|
var m_MipmapLimitGroupName = reader.ReadAlignedString();
|
||||||
|
reader.AlignStream();
|
||||||
|
}
|
||||||
if (version[0] > 2018 || (version[0] == 2018 && version[1] >= 2)) //2018.2 and up
|
if (version[0] > 2018 || (version[0] == 2018 && version[1] >= 2)) //2018.2 and up
|
||||||
{
|
{
|
||||||
var m_StreamingMipmaps = reader.ReadBoolean();
|
var m_StreamingMipmaps = reader.ReadBoolean();
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<TargetFrameworks>net472;net6.0;net7.0</TargetFrameworks>
|
<TargetFrameworks>net472;net6.0;net7.0</TargetFrameworks>
|
||||||
<AssemblyTitle>AssetStudioMod by aelurum</AssemblyTitle>
|
<AssemblyTitle>AssetStudioMod by aelurum</AssemblyTitle>
|
||||||
<AssemblyName>AssetStudioModCLI</AssemblyName>
|
<AssemblyName>AssetStudioModCLI</AssemblyName>
|
||||||
<Version>0.17.1.0</Version>
|
<Version>0.17.3.0</Version>
|
||||||
<Copyright>Copyright © Perfare; Copyright © aelurum 2023</Copyright>
|
<Copyright>Copyright © Perfare; Copyright © aelurum 2023</Copyright>
|
||||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
<DebugType>embedded</DebugType>
|
<DebugType>embedded</DebugType>
|
||||||
@@ -24,6 +24,8 @@
|
|||||||
|
|
||||||
<Target Name="CopyExtraFilesPortable" AfterTargets="AfterBuild" Condition=" '$(RuntimeIdentifier)' == '' ">
|
<Target Name="CopyExtraFilesPortable" AfterTargets="AfterBuild" Condition=" '$(RuntimeIdentifier)' == '' ">
|
||||||
<Message Text="Copying windows extra files for $(TargetFramework)... " Importance="high" />
|
<Message Text="Copying windows extra files for $(TargetFramework)... " Importance="high" />
|
||||||
|
<Copy SourceFiles="$(SolutionDir)AssetStudioFBXNative\bin\Win32\$(Configuration)\AssetStudioFBXNative.dll" DestinationFolder="$(TargetDir)runtimes\win-x86\native" ContinueOnError="false" />
|
||||||
|
<Copy SourceFiles="$(SolutionDir)AssetStudioFBXNative\bin\x64\$(Configuration)\AssetStudioFBXNative.dll" DestinationFolder="$(TargetDir)runtimes\win-x64\native" ContinueOnError="false" />
|
||||||
<Copy SourceFiles="$(SolutionDir)Texture2DDecoderNative\bin\Win32\$(Configuration)\Texture2DDecoderNative.dll" DestinationFolder="$(TargetDir)runtimes\win-x86\native" ContinueOnError="false" />
|
<Copy SourceFiles="$(SolutionDir)Texture2DDecoderNative\bin\Win32\$(Configuration)\Texture2DDecoderNative.dll" DestinationFolder="$(TargetDir)runtimes\win-x86\native" ContinueOnError="false" />
|
||||||
<Copy SourceFiles="$(SolutionDir)Texture2DDecoderNative\bin\x64\$(Configuration)\Texture2DDecoderNative.dll" DestinationFolder="$(TargetDir)runtimes\win-x64\native" ContinueOnError="false" />
|
<Copy SourceFiles="$(SolutionDir)Texture2DDecoderNative\bin\x64\$(Configuration)\Texture2DDecoderNative.dll" DestinationFolder="$(TargetDir)runtimes\win-x64\native" ContinueOnError="false" />
|
||||||
<Copy SourceFiles="$(ProjectDir)Libraries\win-x86\fmod.dll" DestinationFolder="$(TargetDir)runtimes\win-x86\native" ContinueOnError="false" />
|
<Copy SourceFiles="$(ProjectDir)Libraries\win-x86\fmod.dll" DestinationFolder="$(TargetDir)runtimes\win-x86\native" ContinueOnError="false" />
|
||||||
@@ -32,6 +34,9 @@
|
|||||||
|
|
||||||
<Target Name="CopyExtraFilesPortableNet" AfterTargets="AfterBuild" Condition=" '$(RuntimeIdentifier)' == '' AND '$(TargetFramework)' != 'net472' ">
|
<Target Name="CopyExtraFilesPortableNet" AfterTargets="AfterBuild" Condition=" '$(RuntimeIdentifier)' == '' AND '$(TargetFramework)' != 'net472' ">
|
||||||
<Message Text="Copying other platforms extra files for $(TargetFramework)... " Importance="high" />
|
<Message Text="Copying other platforms extra files for $(TargetFramework)... " Importance="high" />
|
||||||
|
<Copy SourceFiles="$(ProjectDir)Libraries\linux-x64\libAssetStudioFBXNative.so" DestinationFolder="$(TargetDir)runtimes\linux-x64\native" ContinueOnError="false" />
|
||||||
|
<Copy SourceFiles="$(ProjectDir)Libraries\osx-x64\libAssetStudioFBXNative.dylib" DestinationFolder="$(TargetDir)runtimes\osx-x64\native" ContinueOnError="false" />
|
||||||
|
<Copy SourceFiles="$(ProjectDir)Libraries\osx-arm64\libAssetStudioFBXNative.dylib" DestinationFolder="$(TargetDir)runtimes\osx-arm64\native" ContinueOnError="false" />
|
||||||
<Copy SourceFiles="$(ProjectDir)Libraries\linux-x86\libfmod.so" DestinationFolder="$(TargetDir)runtimes\linux-x86\native" ContinueOnError="false" />
|
<Copy SourceFiles="$(ProjectDir)Libraries\linux-x86\libfmod.so" DestinationFolder="$(TargetDir)runtimes\linux-x86\native" ContinueOnError="false" />
|
||||||
<Copy SourceFiles="$(ProjectDir)Libraries\linux-x64\libfmod.so" DestinationFolder="$(TargetDir)runtimes\linux-x64\native" ContinueOnError="false" />
|
<Copy SourceFiles="$(ProjectDir)Libraries\linux-x64\libfmod.so" DestinationFolder="$(TargetDir)runtimes\linux-x64\native" ContinueOnError="false" />
|
||||||
<Copy SourceFiles="$(ProjectDir)Libraries\osx-x64\libfmod.dylib" DestinationFolder="$(TargetDir)runtimes\osx-x64\native" ContinueOnError="false" />
|
<Copy SourceFiles="$(ProjectDir)Libraries\osx-x64\libfmod.dylib" DestinationFolder="$(TargetDir)runtimes\osx-x64\native" ContinueOnError="false" />
|
||||||
@@ -42,6 +47,8 @@
|
|||||||
The dll is cross-platform while the executable isn't -->
|
The dll is cross-platform while the executable isn't -->
|
||||||
<Target Name="PublishExtraFilesPortable" AfterTargets="Publish" Condition=" '$(RuntimeIdentifier)' == '' ">
|
<Target Name="PublishExtraFilesPortable" AfterTargets="Publish" Condition=" '$(RuntimeIdentifier)' == '' ">
|
||||||
<Message Text="Publishing windows extra files for Portable build ($(TargetFramework))... " Importance="high" />
|
<Message Text="Publishing windows extra files for Portable build ($(TargetFramework))... " Importance="high" />
|
||||||
|
<Copy SourceFiles="$(TargetDir)runtimes\win-x86\native\AssetStudioFBXNative.dll" DestinationFolder="$(PublishDir)runtimes\win-x86\native" ContinueOnError="false" />
|
||||||
|
<Copy SourceFiles="$(TargetDir)runtimes\win-x64\native\AssetStudioFBXNative.dll" DestinationFolder="$(PublishDir)runtimes\win-x64\native" ContinueOnError="false" />
|
||||||
<Copy SourceFiles="$(TargetDir)runtimes\win-x86\native\Texture2DDecoderNative.dll" DestinationFolder="$(PublishDir)runtimes\win-x86\native" ContinueOnError="false" />
|
<Copy SourceFiles="$(TargetDir)runtimes\win-x86\native\Texture2DDecoderNative.dll" DestinationFolder="$(PublishDir)runtimes\win-x86\native" ContinueOnError="false" />
|
||||||
<Copy SourceFiles="$(TargetDir)runtimes\win-x64\native\Texture2DDecoderNative.dll" DestinationFolder="$(PublishDir)runtimes\win-x64\native" ContinueOnError="false" />
|
<Copy SourceFiles="$(TargetDir)runtimes\win-x64\native\Texture2DDecoderNative.dll" DestinationFolder="$(PublishDir)runtimes\win-x64\native" ContinueOnError="false" />
|
||||||
<Copy SourceFiles="$(TargetDir)runtimes\win-x86\native\fmod.dll" DestinationFolder="$(PublishDir)runtimes\win-x86\native" ContinueOnError="false" />
|
<Copy SourceFiles="$(TargetDir)runtimes\win-x86\native\fmod.dll" DestinationFolder="$(PublishDir)runtimes\win-x86\native" ContinueOnError="false" />
|
||||||
@@ -50,6 +57,9 @@
|
|||||||
|
|
||||||
<Target Name="PublishExtraFilesPortableNet" AfterTargets="Publish" Condition=" '$(RuntimeIdentifier)' == '' AND '$(TargetFramework)' != 'net472' ">
|
<Target Name="PublishExtraFilesPortableNet" AfterTargets="Publish" Condition=" '$(RuntimeIdentifier)' == '' AND '$(TargetFramework)' != 'net472' ">
|
||||||
<Message Text="Publishing other platforms extra files for Portable build ($(TargetFramework))... " Importance="high" />
|
<Message Text="Publishing other platforms extra files for Portable build ($(TargetFramework))... " Importance="high" />
|
||||||
|
<Copy SourceFiles="$(TargetDir)runtimes\linux-x64\native\libAssetStudioFBXNative.so" DestinationFolder="$(PublishDir)runtimes\linux-x64\native" ContinueOnError="false" />
|
||||||
|
<Copy SourceFiles="$(TargetDir)runtimes\osx-x64\native\libAssetStudioFBXNative.dylib" DestinationFolder="$(PublishDir)runtimes\osx-x64\native" ContinueOnError="false" />
|
||||||
|
<Copy SourceFiles="$(TargetDir)runtimes\osx-arm64\native\libAssetStudioFBXNative.dylib" DestinationFolder="$(PublishDir)runtimes\osx-arm64\native" ContinueOnError="false" />
|
||||||
<Copy SourceFiles="$(TargetDir)runtimes\linux-x86\native\libfmod.so" DestinationFolder="$(PublishDir)runtimes\linux-x86\native" ContinueOnError="false" />
|
<Copy SourceFiles="$(TargetDir)runtimes\linux-x86\native\libfmod.so" DestinationFolder="$(PublishDir)runtimes\linux-x86\native" ContinueOnError="false" />
|
||||||
<Copy SourceFiles="$(TargetDir)runtimes\linux-x64\native\libfmod.so" DestinationFolder="$(PublishDir)runtimes\linux-x64\native" ContinueOnError="false" />
|
<Copy SourceFiles="$(TargetDir)runtimes\linux-x64\native\libfmod.so" DestinationFolder="$(PublishDir)runtimes\linux-x64\native" ContinueOnError="false" />
|
||||||
<Copy SourceFiles="$(TargetDir)runtimes\osx-x64\native\libfmod.dylib" DestinationFolder="$(PublishDir)runtimes\osx-x64\native" ContinueOnError="false" />
|
<Copy SourceFiles="$(TargetDir)runtimes\osx-x64\native\libfmod.dylib" DestinationFolder="$(PublishDir)runtimes\osx-x64\native" ContinueOnError="false" />
|
||||||
@@ -58,39 +68,46 @@
|
|||||||
|
|
||||||
<Target Name="CopyExtraFilesWin86" AfterTargets="AfterBuild" Condition=" '$(RuntimeIdentifier)' == 'win-x86' ">
|
<Target Name="CopyExtraFilesWin86" AfterTargets="AfterBuild" Condition=" '$(RuntimeIdentifier)' == 'win-x86' ">
|
||||||
<Message Text="Copying extra files for $(RuntimeIdentifier)($(TargetFramework))... " Importance="high" />
|
<Message Text="Copying extra files for $(RuntimeIdentifier)($(TargetFramework))... " Importance="high" />
|
||||||
|
<Copy SourceFiles="$(SolutionDir)AssetStudioFBXNative\bin\Win32\$(Configuration)\AssetStudioFBXNative.dll" DestinationFolder="$(TargetDir)" ContinueOnError="false" />
|
||||||
<Copy SourceFiles="$(SolutionDir)Texture2DDecoderNative\bin\Win32\$(Configuration)\Texture2DDecoderNative.dll" DestinationFolder="$(TargetDir)" ContinueOnError="false" />
|
<Copy SourceFiles="$(SolutionDir)Texture2DDecoderNative\bin\Win32\$(Configuration)\Texture2DDecoderNative.dll" DestinationFolder="$(TargetDir)" ContinueOnError="false" />
|
||||||
<Copy SourceFiles="$(ProjectDir)Libraries\win-x86\fmod.dll" DestinationFolder="$(TargetDir)" ContinueOnError="false" />
|
<Copy SourceFiles="$(ProjectDir)Libraries\win-x86\fmod.dll" DestinationFolder="$(TargetDir)" ContinueOnError="false" />
|
||||||
</Target>
|
</Target>
|
||||||
|
|
||||||
<Target Name="CopyExtraFilesWin64" AfterTargets="AfterBuild" Condition=" '$(RuntimeIdentifier)' == 'win-x64' ">
|
<Target Name="CopyExtraFilesWin64" AfterTargets="AfterBuild" Condition=" '$(RuntimeIdentifier)' == 'win-x64' ">
|
||||||
<Message Text="Copying extra files for $(RuntimeIdentifier)($(TargetFramework))... " Importance="high" />
|
<Message Text="Copying extra files for $(RuntimeIdentifier)($(TargetFramework))... " Importance="high" />
|
||||||
|
<Copy SourceFiles="$(SolutionDir)AssetStudioFBXNative\bin\x64\$(Configuration)\AssetStudioFBXNative.dll" DestinationFolder="$(TargetDir)" ContinueOnError="false" />
|
||||||
<Copy SourceFiles="$(SolutionDir)Texture2DDecoderNative\bin\x64\$(Configuration)\Texture2DDecoderNative.dll" DestinationFolder="$(TargetDir)" ContinueOnError="false" />
|
<Copy SourceFiles="$(SolutionDir)Texture2DDecoderNative\bin\x64\$(Configuration)\Texture2DDecoderNative.dll" DestinationFolder="$(TargetDir)" ContinueOnError="false" />
|
||||||
<Copy SourceFiles="$(ProjectDir)Libraries\win-x64\fmod.dll" DestinationFolder="$(TargetDir)" ContinueOnError="false" />
|
<Copy SourceFiles="$(ProjectDir)Libraries\win-x64\fmod.dll" DestinationFolder="$(TargetDir)" ContinueOnError="false" />
|
||||||
</Target>
|
</Target>
|
||||||
|
|
||||||
<Target Name="PublishExtraFilesWin" AfterTargets="Publish" Condition=" $(RuntimeIdentifier.Contains('win-x')) ">
|
<Target Name="PublishExtraFilesWin" AfterTargets="Publish" Condition=" $(RuntimeIdentifier.Contains('win-x')) ">
|
||||||
<Message Text="Publishing extra files for $(RuntimeIdentifier)($(TargetFramework))... " Importance="high" />
|
<Message Text="Publishing extra files for $(RuntimeIdentifier)($(TargetFramework))... " Importance="high" />
|
||||||
|
<Copy SourceFiles="$(TargetDir)\AssetStudioFBXNative.dll" DestinationFolder="$(PublishDir)" ContinueOnError="false" />
|
||||||
<Copy SourceFiles="$(TargetDir)\Texture2DDecoderNative.dll" DestinationFolder="$(PublishDir)" ContinueOnError="false" />
|
<Copy SourceFiles="$(TargetDir)\Texture2DDecoderNative.dll" DestinationFolder="$(PublishDir)" ContinueOnError="false" />
|
||||||
<Copy SourceFiles="$(TargetDir)\fmod.dll" DestinationFolder="$(PublishDir)" ContinueOnError="false" />
|
<Copy SourceFiles="$(TargetDir)\fmod.dll" DestinationFolder="$(PublishDir)" ContinueOnError="false" />
|
||||||
</Target>
|
</Target>
|
||||||
|
|
||||||
<Target Name="CopyExtraFilesLinux64" AfterTargets="AfterBuild" Condition=" '$(RuntimeIdentifier)' == 'linux-x64' ">
|
<Target Name="CopyExtraFilesLinux64" AfterTargets="AfterBuild" Condition=" '$(RuntimeIdentifier)' == 'linux-x64' ">
|
||||||
<Message Text="Copying extra files for $(RuntimeIdentifier)($(TargetFramework))... " Importance="high" />
|
<Message Text="Copying extra files for $(RuntimeIdentifier)($(TargetFramework))... " Importance="high" />
|
||||||
|
<Copy SourceFiles="$(ProjectDir)Libraries\linux-x64\libAssetStudioFBXNative.so" DestinationFolder="$(TargetDir)" ContinueOnError="false" />
|
||||||
<Copy SourceFiles="$(ProjectDir)Libraries\linux-x64\libfmod.so" DestinationFolder="$(TargetDir)" ContinueOnError="false" />
|
<Copy SourceFiles="$(ProjectDir)Libraries\linux-x64\libfmod.so" DestinationFolder="$(TargetDir)" ContinueOnError="false" />
|
||||||
</Target>
|
</Target>
|
||||||
|
|
||||||
<Target Name="PublishExtraFilesLinux64" AfterTargets="Publish" Condition=" '$(RuntimeIdentifier)' == 'linux-x64' ">
|
<Target Name="PublishExtraFilesLinux64" AfterTargets="Publish" Condition=" '$(RuntimeIdentifier)' == 'linux-x64' ">
|
||||||
<Message Text="Publishing extra files for $(RuntimeIdentifier)($(TargetFramework))... " Importance="high" />
|
<Message Text="Publishing extra files for $(RuntimeIdentifier)($(TargetFramework))... " Importance="high" />
|
||||||
|
<Copy SourceFiles="$(TargetDir)\libAssetStudioFBXNative.so" DestinationFolder="$(PublishDir)" ContinueOnError="false" />
|
||||||
<Copy SourceFiles="$(TargetDir)\libfmod.so" DestinationFolder="$(PublishDir)" ContinueOnError="false" />
|
<Copy SourceFiles="$(TargetDir)\libfmod.so" DestinationFolder="$(PublishDir)" ContinueOnError="false" />
|
||||||
</Target>
|
</Target>
|
||||||
|
|
||||||
<Target Name="CopyExtraFilesMac" AfterTargets="AfterBuild" Condition=" $(RuntimeIdentifier.Contains('osx-')) ">
|
<Target Name="CopyExtraFilesMac" AfterTargets="AfterBuild" Condition=" $(RuntimeIdentifier.Contains('osx-')) ">
|
||||||
<Message Text="Copying extra files for $(RuntimeIdentifier)($(TargetFramework))... " Importance="high" />
|
<Message Text="Copying extra files for $(RuntimeIdentifier)($(TargetFramework))... " Importance="high" />
|
||||||
|
<Copy SourceFiles="$(ProjectDir)Libraries\$(RuntimeIdentifier)\libAssetStudioFBXNative.dylib" DestinationFolder="$(TargetDir)" ContinueOnError="false" />
|
||||||
<Copy SourceFiles="$(ProjectDir)Libraries\$(RuntimeIdentifier)\libfmod.dylib" DestinationFolder="$(TargetDir)" ContinueOnError="false" />
|
<Copy SourceFiles="$(ProjectDir)Libraries\$(RuntimeIdentifier)\libfmod.dylib" DestinationFolder="$(TargetDir)" ContinueOnError="false" />
|
||||||
</Target>
|
</Target>
|
||||||
|
|
||||||
<Target Name="PublishExtraFilesMac" AfterTargets="Publish" Condition=" $(RuntimeIdentifier.Contains('osx-')) ">
|
<Target Name="PublishExtraFilesMac" AfterTargets="Publish" Condition=" $(RuntimeIdentifier.Contains('osx-')) ">
|
||||||
<Message Text="Publishing extra files for $(RuntimeIdentifier)($(TargetFramework))... " Importance="high" />
|
<Message Text="Publishing extra files for $(RuntimeIdentifier)($(TargetFramework))... " Importance="high" />
|
||||||
|
<Copy SourceFiles="$(TargetDir)\libAssetStudioFBXNative.dylib" DestinationFolder="$(PublishDir)" ContinueOnError="false" />
|
||||||
<Copy SourceFiles="$(TargetDir)\libfmod.dylib" DestinationFolder="$(PublishDir)" ContinueOnError="false" />
|
<Copy SourceFiles="$(TargetDir)\libfmod.dylib" DestinationFolder="$(PublishDir)" ContinueOnError="false" />
|
||||||
</Target>
|
</Target>
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
using AssetStudio;
|
using AssetStudio;
|
||||||
|
using AssetStudioCLI.Options;
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using AssetStudioCLI.Options;
|
|
||||||
|
|
||||||
namespace AssetStudioCLI
|
namespace AssetStudioCLI
|
||||||
{
|
{
|
||||||
@@ -21,16 +21,17 @@ namespace AssetStudioCLI
|
|||||||
public string LogName;
|
public string LogName;
|
||||||
public string LogPath;
|
public string LogPath;
|
||||||
|
|
||||||
public CLILogger(CLIOptions options)
|
public CLILogger()
|
||||||
{
|
{
|
||||||
logOutput = options.o_logOutput.Value;
|
logOutput = CLIOptions.o_logOutput.Value;
|
||||||
logMinLevel = options.o_logLevel.Value;
|
logMinLevel = CLIOptions.o_logLevel.Value;
|
||||||
LogName = $"AssetStudioCLI_{DateTime.Now:yyyy-MM-dd_HH-mm-ss}.log";
|
var appAssembly = typeof(Program).Assembly.GetName();
|
||||||
|
LogName = $"{appAssembly.Name}_{DateTime.Now:yyyy-MM-dd_HH-mm-ss}.log";
|
||||||
LogPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, LogName);
|
LogPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, LogName);
|
||||||
|
var arch = Environment.Is64BitProcess ? "x64" : "x32";
|
||||||
|
|
||||||
var ver = typeof(Program).Assembly.GetName().Version;
|
LogToFile(LoggerEvent.Verbose, $"---{appAssembly.Name} v{appAssembly.Version} [{arch}] | Logger launched---\n" +
|
||||||
LogToFile(LoggerEvent.Verbose, $"---AssetStudioCLI v{ver} | Logger launched---\n" +
|
$"CMD Args: {string.Join(" ", CLIOptions.cliArgs)}");
|
||||||
$"CMD Args: {string.Join(" ", options.cliArgs)}");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string ColorLogLevel(LoggerEvent logLevel)
|
private static string ColorLogLevel(LoggerEvent logLevel)
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ namespace AssetStudioCLI
|
|||||||
public ClassIDType Type;
|
public ClassIDType Type;
|
||||||
public string Text;
|
public string Text;
|
||||||
public string UniqueID;
|
public string UniqueID;
|
||||||
|
public GameObjectNode Node;
|
||||||
|
|
||||||
public AssetItem(Object asset)
|
public AssetItem(Object asset)
|
||||||
{
|
{
|
||||||
|
|||||||
16
AssetStudioCLI/Components/BaseNode.cs
Normal file
16
AssetStudioCLI/Components/BaseNode.cs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
using AssetStudio;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace AssetStudioCLI
|
||||||
|
{
|
||||||
|
internal class BaseNode
|
||||||
|
{
|
||||||
|
public List<BaseNode> nodes = new List<BaseNode>();
|
||||||
|
|
||||||
|
public BaseNode()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
16
AssetStudioCLI/Components/GameObjectNode.cs
Normal file
16
AssetStudioCLI/Components/GameObjectNode.cs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
using AssetStudio;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace AssetStudioCLI
|
||||||
|
{
|
||||||
|
internal class GameObjectNode : BaseNode
|
||||||
|
{
|
||||||
|
public GameObject gameObject;
|
||||||
|
|
||||||
|
public GameObjectNode(GameObject gameObject)
|
||||||
|
{
|
||||||
|
this.gameObject = gameObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
using AssetStudio;
|
using AssetStudio;
|
||||||
using AssetStudioCLI.Options;
|
using AssetStudioCLI.Options;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
@@ -9,14 +10,38 @@ namespace AssetStudioCLI
|
|||||||
{
|
{
|
||||||
internal static class Exporter
|
internal static class Exporter
|
||||||
{
|
{
|
||||||
public static bool ExportTexture2D(AssetItem item, string exportPath, CLIOptions options)
|
public static bool ExportTexture2D(AssetItem item, string exportPath)
|
||||||
{
|
{
|
||||||
var m_Texture2D = (Texture2D)item.Asset;
|
var m_Texture2D = (Texture2D)item.Asset;
|
||||||
if (options.convertTexture)
|
if (CLIOptions.convertTexture)
|
||||||
{
|
{
|
||||||
var type = options.o_imageFormat.Value;
|
var type = CLIOptions.o_imageFormat.Value;
|
||||||
if (!TryExportFile(exportPath, item, "." + type.ToString().ToLower(), out var exportFullPath))
|
if (!TryExportFile(exportPath, item, "." + type.ToString().ToLower(), out var exportFullPath))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (CLIOptions.o_logLevel.Value <= LoggerEvent.Debug)
|
||||||
|
{
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
sb.AppendLine($"Converting \"{m_Texture2D.m_Name}\" to {type}..");
|
||||||
|
sb.AppendLine($"Width: {m_Texture2D.m_Width}");
|
||||||
|
sb.AppendLine($"Height: {m_Texture2D.m_Height}");
|
||||||
|
sb.AppendLine($"Format: {m_Texture2D.m_TextureFormat}");
|
||||||
|
switch (m_Texture2D.m_TextureSettings.m_FilterMode)
|
||||||
|
{
|
||||||
|
case 0: sb.AppendLine("Filter Mode: Point "); break;
|
||||||
|
case 1: sb.AppendLine("Filter Mode: Bilinear "); break;
|
||||||
|
case 2: sb.AppendLine("Filter Mode: Trilinear "); break;
|
||||||
|
}
|
||||||
|
sb.AppendLine($"Anisotropic level: {m_Texture2D.m_TextureSettings.m_Aniso}");
|
||||||
|
sb.AppendLine($"Mip map bias: {m_Texture2D.m_TextureSettings.m_MipBias}");
|
||||||
|
switch (m_Texture2D.m_TextureSettings.m_WrapMode)
|
||||||
|
{
|
||||||
|
case 0: sb.AppendLine($"Wrap mode: Repeat"); break;
|
||||||
|
case 1: sb.AppendLine($"Wrap mode: Clamp"); break;
|
||||||
|
}
|
||||||
|
Logger.Debug(sb.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
var image = m_Texture2D.ConvertToImage(flip: true);
|
var image = m_Texture2D.ConvertToImage(flip: true);
|
||||||
if (image == null)
|
if (image == null)
|
||||||
{
|
{
|
||||||
@@ -29,7 +54,7 @@ namespace AssetStudioCLI
|
|||||||
{
|
{
|
||||||
image.WriteToStream(file, type);
|
image.WriteToStream(file, type);
|
||||||
}
|
}
|
||||||
Logger.Debug($"{item.TypeString}: \"{item.Text}\" exported to \"{exportFullPath}\"");
|
Logger.Debug($"{item.TypeString} \"{item.Text}\" exported to \"{exportFullPath}\"");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -38,12 +63,12 @@ namespace AssetStudioCLI
|
|||||||
if (!TryExportFile(exportPath, item, ".tex", out var exportFullPath))
|
if (!TryExportFile(exportPath, item, ".tex", out var exportFullPath))
|
||||||
return false;
|
return false;
|
||||||
File.WriteAllBytes(exportFullPath, m_Texture2D.image_data.GetData());
|
File.WriteAllBytes(exportFullPath, m_Texture2D.image_data.GetData());
|
||||||
Logger.Debug($"{item.TypeString}: \"{item.Text}\" exported to \"{exportFullPath}\"");
|
Logger.Debug($"{item.TypeString} \"{item.Text}\" exported to \"{exportFullPath}\"");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool ExportAudioClip(AssetItem item, string exportPath, CLIOptions options)
|
public static bool ExportAudioClip(AssetItem item, string exportPath)
|
||||||
{
|
{
|
||||||
string exportFullPath;
|
string exportFullPath;
|
||||||
var m_AudioClip = (AudioClip)item.Asset;
|
var m_AudioClip = (AudioClip)item.Asset;
|
||||||
@@ -54,18 +79,21 @@ namespace AssetStudioCLI
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
var converter = new AudioClipConverter(m_AudioClip);
|
var converter = new AudioClipConverter(m_AudioClip);
|
||||||
if (options.o_audioFormat.Value != AudioFormat.None && converter.IsSupport)
|
if (CLIOptions.o_audioFormat.Value != AudioFormat.None && converter.IsSupport)
|
||||||
{
|
{
|
||||||
if (!TryExportFile(exportPath, item, ".wav", out exportFullPath))
|
if (!TryExportFile(exportPath, item, ".wav", out exportFullPath))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var sb = new StringBuilder();
|
if (CLIOptions.o_logLevel.Value <= LoggerEvent.Debug)
|
||||||
sb.AppendLine($"Converting \"{m_AudioClip.m_Name}\" to wav..");
|
{
|
||||||
sb.AppendLine(m_AudioClip.version[0] < 5 ? $"AudioClip type: {m_AudioClip.m_Type}" : $"AudioClip compression format: {m_AudioClip.m_CompressionFormat}");
|
var sb = new StringBuilder();
|
||||||
sb.AppendLine($"AudioClip channel count: {m_AudioClip.m_Channels}");
|
sb.AppendLine($"Converting \"{m_AudioClip.m_Name}\" to wav..");
|
||||||
sb.AppendLine($"AudioClip sample rate: {m_AudioClip.m_Frequency}");
|
sb.AppendLine(m_AudioClip.version[0] < 5 ? $"AudioClip type: {m_AudioClip.m_Type}" : $"AudioClip compression format: {m_AudioClip.m_CompressionFormat}");
|
||||||
sb.AppendLine($"AudioClip bit depth: {m_AudioClip.m_BitsPerSample}");
|
sb.AppendLine($"AudioClip channel count: {m_AudioClip.m_Channels}");
|
||||||
Logger.Debug(sb.ToString());
|
sb.AppendLine($"AudioClip sample rate: {m_AudioClip.m_Frequency}");
|
||||||
|
sb.AppendLine($"AudioClip bit depth: {m_AudioClip.m_BitsPerSample}");
|
||||||
|
Logger.Debug(sb.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
var buffer = converter.ConvertToWav(m_AudioData);
|
var buffer = converter.ConvertToWav(m_AudioData);
|
||||||
if (buffer == null)
|
if (buffer == null)
|
||||||
@@ -82,7 +110,7 @@ namespace AssetStudioCLI
|
|||||||
File.WriteAllBytes(exportFullPath, m_AudioData);
|
File.WriteAllBytes(exportFullPath, m_AudioData);
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger.Debug($"{item.TypeString}: \"{item.Text}\" exported to \"{exportFullPath}\"");
|
Logger.Debug($"{item.TypeString} \"{item.Text}\" exported to \"{exportFullPath}\"");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,16 +122,19 @@ namespace AssetStudioCLI
|
|||||||
if (!TryExportFile(exportPath, item, Path.GetExtension(m_VideoClip.m_OriginalPath), out var exportFullPath))
|
if (!TryExportFile(exportPath, item, Path.GetExtension(m_VideoClip.m_OriginalPath), out var exportFullPath))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var sb = new StringBuilder();
|
if (CLIOptions.o_logLevel.Value <= LoggerEvent.Debug)
|
||||||
sb.AppendLine($"VideoClip format: {m_VideoClip.m_Format}");
|
{
|
||||||
sb.AppendLine($"VideoClip width: {m_VideoClip.Width}");
|
var sb = new StringBuilder();
|
||||||
sb.AppendLine($"VideoClip height: {m_VideoClip.Height}");
|
sb.AppendLine($"VideoClip format: {m_VideoClip.m_Format}");
|
||||||
sb.AppendLine($"VideoClip frame rate: {m_VideoClip.m_FrameRate}");
|
sb.AppendLine($"VideoClip width: {m_VideoClip.Width}");
|
||||||
sb.AppendLine($"VideoClip split alpha: {m_VideoClip.m_HasSplitAlpha}");
|
sb.AppendLine($"VideoClip height: {m_VideoClip.Height}");
|
||||||
Logger.Debug(sb.ToString());
|
sb.AppendLine($"VideoClip frame rate: {m_VideoClip.m_FrameRate:.0##}");
|
||||||
|
sb.AppendLine($"VideoClip split alpha: {m_VideoClip.m_HasSplitAlpha}");
|
||||||
|
Logger.Debug(sb.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
m_VideoClip.m_VideoData.WriteData(exportFullPath);
|
m_VideoClip.m_VideoData.WriteData(exportFullPath);
|
||||||
Logger.Debug($"{item.TypeString}: \"{item.Text}\" exported to \"{exportFullPath}\"");
|
Logger.Debug($"{item.TypeString} \"{item.Text}\" exported to \"{exportFullPath}\"");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -116,7 +147,7 @@ namespace AssetStudioCLI
|
|||||||
return false;
|
return false;
|
||||||
File.WriteAllBytes(exportFullPath, m_MovieTexture.m_MovieData);
|
File.WriteAllBytes(exportFullPath, m_MovieTexture.m_MovieData);
|
||||||
|
|
||||||
Logger.Debug($"{item.TypeString}: \"{item.Text}\" exported to \"{exportFullPath}\"");
|
Logger.Debug($"{item.TypeString} \"{item.Text}\" exported to \"{exportFullPath}\"");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,16 +159,16 @@ namespace AssetStudioCLI
|
|||||||
var str = m_Shader.Convert();
|
var str = m_Shader.Convert();
|
||||||
File.WriteAllText(exportFullPath, str);
|
File.WriteAllText(exportFullPath, str);
|
||||||
|
|
||||||
Logger.Debug($"{item.TypeString}: \"{item.Text}\" exported to \"{exportFullPath}\"");
|
Logger.Debug($"{item.TypeString} \"{item.Text}\" exported to \"{exportFullPath}\"");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool ExportTextAsset(AssetItem item, string exportPath, CLIOptions options)
|
public static bool ExportTextAsset(AssetItem item, string exportPath)
|
||||||
{
|
{
|
||||||
var m_TextAsset = (TextAsset)item.Asset;
|
var m_TextAsset = (TextAsset)item.Asset;
|
||||||
var extension = ".txt";
|
var extension = ".txt";
|
||||||
var assetExtension = Path.GetExtension(m_TextAsset.m_Name);
|
var assetExtension = Path.GetExtension(m_TextAsset.m_Name);
|
||||||
if (!options.f_notRestoreExtensionName.Value)
|
if (!CLIOptions.f_notRestoreExtensionName.Value)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(assetExtension))
|
if (!string.IsNullOrEmpty(assetExtension))
|
||||||
{
|
{
|
||||||
@@ -156,11 +187,11 @@ namespace AssetStudioCLI
|
|||||||
return false;
|
return false;
|
||||||
File.WriteAllBytes(exportFullPath, m_TextAsset.m_Script);
|
File.WriteAllBytes(exportFullPath, m_TextAsset.m_Script);
|
||||||
|
|
||||||
Logger.Debug($"{item.TypeString}: \"{item.Text}\" exported to \"{exportFullPath}\"");
|
Logger.Debug($"{item.TypeString} \"{item.Text}\" exported to \"{exportFullPath}\"");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool ExportMonoBehaviour(AssetItem item, string exportPath, AssemblyLoader assemblyLoader)
|
public static bool ExportMonoBehaviour(AssetItem item, string exportPath)
|
||||||
{
|
{
|
||||||
if (!TryExportFile(exportPath, item, ".json", out var exportFullPath))
|
if (!TryExportFile(exportPath, item, ".json", out var exportFullPath))
|
||||||
return false;
|
return false;
|
||||||
@@ -168,7 +199,7 @@ namespace AssetStudioCLI
|
|||||||
var type = m_MonoBehaviour.ToType();
|
var type = m_MonoBehaviour.ToType();
|
||||||
if (type == null)
|
if (type == null)
|
||||||
{
|
{
|
||||||
var m_Type = m_MonoBehaviour.ConvertToTypeTree(assemblyLoader);
|
var m_Type = m_MonoBehaviour.ConvertToTypeTree(Studio.assemblyLoader);
|
||||||
type = m_MonoBehaviour.ToType(m_Type);
|
type = m_MonoBehaviour.ToType(m_Type);
|
||||||
}
|
}
|
||||||
if (type != null)
|
if (type != null)
|
||||||
@@ -176,7 +207,7 @@ namespace AssetStudioCLI
|
|||||||
var str = JsonConvert.SerializeObject(type, Formatting.Indented);
|
var str = JsonConvert.SerializeObject(type, Formatting.Indented);
|
||||||
File.WriteAllText(exportFullPath, str);
|
File.WriteAllText(exportFullPath, str);
|
||||||
|
|
||||||
Logger.Debug($"{item.TypeString}: \"{item.Text}\" exported to \"{exportFullPath}\"");
|
Logger.Debug($"{item.TypeString} \"{item.Text}\" exported to \"{exportFullPath}\"");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -196,15 +227,15 @@ namespace AssetStudioCLI
|
|||||||
return false;
|
return false;
|
||||||
File.WriteAllBytes(exportFullPath, m_Font.m_FontData);
|
File.WriteAllBytes(exportFullPath, m_Font.m_FontData);
|
||||||
|
|
||||||
Logger.Debug($"{item.TypeString}: \"{item.Text}\" exported to \"{exportFullPath}\"");
|
Logger.Debug($"{item.TypeString} \"{item.Text}\" exported to \"{exportFullPath}\"");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool ExportSprite(AssetItem item, string exportPath, CLIOptions options)
|
public static bool ExportSprite(AssetItem item, string exportPath)
|
||||||
{
|
{
|
||||||
var type = options.o_imageFormat.Value;
|
var type = CLIOptions.o_imageFormat.Value;
|
||||||
var alphaMask = SpriteMaskMode.On;
|
var alphaMask = SpriteMaskMode.On;
|
||||||
if (!TryExportFile(exportPath, item, "." + type.ToString().ToLower(), out var exportFullPath))
|
if (!TryExportFile(exportPath, item, "." + type.ToString().ToLower(), out var exportFullPath))
|
||||||
return false;
|
return false;
|
||||||
@@ -217,7 +248,7 @@ namespace AssetStudioCLI
|
|||||||
{
|
{
|
||||||
image.WriteToStream(file, type);
|
image.WriteToStream(file, type);
|
||||||
}
|
}
|
||||||
Logger.Debug($"{item.TypeString}: \"{item.Text}\" exported to \"{exportFullPath}\"");
|
Logger.Debug($"{item.TypeString} \"{item.Text}\" exported to \"{exportFullPath}\"");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -230,24 +261,52 @@ namespace AssetStudioCLI
|
|||||||
return false;
|
return false;
|
||||||
File.WriteAllBytes(exportFullPath, item.Asset.GetRawData());
|
File.WriteAllBytes(exportFullPath, item.Asset.GetRawData());
|
||||||
|
|
||||||
Logger.Debug($"{item.TypeString}: \"{item.Text}\" exported to \"{exportFullPath}\"");
|
Logger.Debug($"{item.TypeString} \"{item.Text}\" exported to \"{exportFullPath}\"");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool ExportDumpFile(AssetItem item, string exportPath, AssemblyLoader assemblyLoader)
|
public static void ExportGameObject(GameObject gameObject, string exportPath, List<AssetItem> animationList = null)
|
||||||
|
{
|
||||||
|
var convert = animationList != null
|
||||||
|
? new ModelConverter(gameObject, CLIOptions.o_imageFormat.Value, animationList.Select(x => (AnimationClip)x.Asset).ToArray())
|
||||||
|
: new ModelConverter(gameObject, CLIOptions.o_imageFormat.Value);
|
||||||
|
exportPath = exportPath + FixFileName(gameObject.m_Name) + ".fbx";
|
||||||
|
ExportFbx(convert, exportPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ExportFbx(IImported convert, string exportPath)
|
||||||
|
{
|
||||||
|
var eulerFilter = true;
|
||||||
|
var filterPrecision = (float)0.25f;
|
||||||
|
var exportAllNodes = true;
|
||||||
|
var exportSkins = true;
|
||||||
|
var exportAnimations = true;
|
||||||
|
var exportBlendShape = true;
|
||||||
|
var castToBone = false;
|
||||||
|
var boneSize = CLIOptions.o_fbxBoneSize.Value;
|
||||||
|
var exportAllUvsAsDiffuseMaps = false;
|
||||||
|
var scaleFactor = CLIOptions.o_fbxScaleFactor.Value;
|
||||||
|
var fbxVersion = 3;
|
||||||
|
var fbxFormat = 0;
|
||||||
|
ModelExporter.ExportFbx(exportPath, convert, eulerFilter, filterPrecision,
|
||||||
|
exportAllNodes, exportSkins, exportAnimations, exportBlendShape, castToBone, boneSize, exportAllUvsAsDiffuseMaps, scaleFactor, fbxVersion, fbxFormat == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static bool ExportDumpFile(AssetItem item, string exportPath)
|
||||||
{
|
{
|
||||||
if (!TryExportFile(exportPath, item, ".txt", out var exportFullPath))
|
if (!TryExportFile(exportPath, item, ".txt", out var exportFullPath))
|
||||||
return false;
|
return false;
|
||||||
var str = item.Asset.Dump();
|
var str = item.Asset.Dump();
|
||||||
if (str == null && item.Asset is MonoBehaviour m_MonoBehaviour)
|
if (str == null && item.Asset is MonoBehaviour m_MonoBehaviour)
|
||||||
{
|
{
|
||||||
var m_Type = m_MonoBehaviour.ConvertToTypeTree(assemblyLoader);
|
var m_Type = m_MonoBehaviour.ConvertToTypeTree(Studio.assemblyLoader);
|
||||||
str = m_MonoBehaviour.Dump(m_Type);
|
str = m_MonoBehaviour.Dump(m_Type);
|
||||||
}
|
}
|
||||||
if (str != null)
|
if (str != null)
|
||||||
{
|
{
|
||||||
File.WriteAllText(exportFullPath, str);
|
File.WriteAllText(exportFullPath, str);
|
||||||
Logger.Debug($"{item.TypeString}: \"{item.Text}\" saved to \"{exportFullPath}\"");
|
Logger.Debug($"{item.TypeString} \"{item.Text}\" saved to \"{exportFullPath}\"");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -365,18 +424,18 @@ namespace AssetStudioCLI
|
|||||||
|
|
||||||
sb.Replace("NaN", "0");
|
sb.Replace("NaN", "0");
|
||||||
File.WriteAllText(exportFullPath, sb.ToString());
|
File.WriteAllText(exportFullPath, sb.ToString());
|
||||||
Logger.Debug($"{item.TypeString}: \"{item.Text}\" exported to \"{exportFullPath}\"");
|
Logger.Debug($"{item.TypeString} \"{item.Text}\" exported to \"{exportFullPath}\"");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool ExportConvertFile(AssetItem item, string exportPath, CLIOptions options, AssemblyLoader assemblyLoader)
|
public static bool ExportConvertFile(AssetItem item, string exportPath)
|
||||||
{
|
{
|
||||||
switch (item.Type)
|
switch (item.Type)
|
||||||
{
|
{
|
||||||
case ClassIDType.Texture2D:
|
case ClassIDType.Texture2D:
|
||||||
return ExportTexture2D(item, exportPath, options);
|
return ExportTexture2D(item, exportPath);
|
||||||
case ClassIDType.AudioClip:
|
case ClassIDType.AudioClip:
|
||||||
return ExportAudioClip(item, exportPath, options);
|
return ExportAudioClip(item, exportPath);
|
||||||
case ClassIDType.VideoClip:
|
case ClassIDType.VideoClip:
|
||||||
return ExportVideoClip(item, exportPath);
|
return ExportVideoClip(item, exportPath);
|
||||||
case ClassIDType.MovieTexture:
|
case ClassIDType.MovieTexture:
|
||||||
@@ -384,13 +443,13 @@ namespace AssetStudioCLI
|
|||||||
case ClassIDType.Shader:
|
case ClassIDType.Shader:
|
||||||
return ExportShader(item, exportPath);
|
return ExportShader(item, exportPath);
|
||||||
case ClassIDType.TextAsset:
|
case ClassIDType.TextAsset:
|
||||||
return ExportTextAsset(item, exportPath, options);
|
return ExportTextAsset(item, exportPath);
|
||||||
case ClassIDType.MonoBehaviour:
|
case ClassIDType.MonoBehaviour:
|
||||||
return ExportMonoBehaviour(item, exportPath, assemblyLoader);
|
return ExportMonoBehaviour(item, exportPath);
|
||||||
case ClassIDType.Font:
|
case ClassIDType.Font:
|
||||||
return ExportFont(item, exportPath);
|
return ExportFont(item, exportPath);
|
||||||
case ClassIDType.Sprite:
|
case ClassIDType.Sprite:
|
||||||
return ExportSprite(item, exportPath, options);
|
return ExportSprite(item, exportPath);
|
||||||
case ClassIDType.Mesh:
|
case ClassIDType.Mesh:
|
||||||
return ExportMesh(item, exportPath);
|
return ExportMesh(item, exportPath);
|
||||||
default:
|
default:
|
||||||
|
|||||||
BIN
AssetStudioCLI/Libraries/linux-x64/libAssetStudioFBXNative.so
Normal file
BIN
AssetStudioCLI/Libraries/linux-x64/libAssetStudioFBXNative.so
Normal file
Binary file not shown.
BIN
AssetStudioCLI/Libraries/osx-arm64/libAssetStudioFBXNative.dylib
Normal file
BIN
AssetStudioCLI/Libraries/osx-arm64/libAssetStudioFBXNative.dylib
Normal file
Binary file not shown.
BIN
AssetStudioCLI/Libraries/osx-x64/libAssetStudioFBXNative.dylib
Normal file
BIN
AssetStudioCLI/Libraries/osx-x64/libAssetStudioFBXNative.dylib
Normal file
Binary file not shown.
@@ -12,6 +12,8 @@ namespace AssetStudioCLI.Options
|
|||||||
General,
|
General,
|
||||||
Convert,
|
Convert,
|
||||||
Logger,
|
Logger,
|
||||||
|
FBX,
|
||||||
|
Filter,
|
||||||
Advanced,
|
Advanced,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -22,6 +24,7 @@ namespace AssetStudioCLI.Options
|
|||||||
Dump,
|
Dump,
|
||||||
Info,
|
Info,
|
||||||
ExportLive2D,
|
ExportLive2D,
|
||||||
|
SplitObjects,
|
||||||
}
|
}
|
||||||
|
|
||||||
internal enum AssetGroupOption
|
internal enum AssetGroupOption
|
||||||
@@ -55,65 +58,90 @@ namespace AssetStudioCLI.Options
|
|||||||
NameAndContainer,
|
NameAndContainer,
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class GroupedOption<T> : Option<T>
|
internal static class CLIOptions
|
||||||
{
|
{
|
||||||
public GroupedOption(T optionDefaultValue, string optionName, string optionDescription, HelpGroups optionHelpGroup, bool isFlag = false) : base(optionDefaultValue, optionName, optionDescription, optionHelpGroup, isFlag)
|
public static bool isParsed;
|
||||||
{
|
public static bool showHelp;
|
||||||
CLIOptions.OptionGrouping(optionName, optionDescription, optionHelpGroup, isFlag);
|
public static string[] cliArgs;
|
||||||
}
|
public static string inputPath;
|
||||||
}
|
public static FilterBy filterBy;
|
||||||
|
|
||||||
internal class CLIOptions
|
|
||||||
{
|
|
||||||
public bool isParsed;
|
|
||||||
public bool showHelp;
|
|
||||||
public string[] cliArgs;
|
|
||||||
public string inputPath;
|
|
||||||
public FilterBy filterBy;
|
|
||||||
private static Dictionary<string, string> optionsDict;
|
private static Dictionary<string, string> optionsDict;
|
||||||
private static Dictionary<string, string> flagsDict;
|
private static Dictionary<string, string> flagsDict;
|
||||||
private static Dictionary<HelpGroups, Dictionary<string, string>> optionGroups;
|
private static Dictionary<HelpGroups, Dictionary<string, string>> optionGroups;
|
||||||
private List<ClassIDType> supportedAssetTypes;
|
private static List<ClassIDType> exportableAssetTypes;
|
||||||
|
private static Dictionary<string, ClassIDType> knownAssetTypesDict;
|
||||||
//general
|
//general
|
||||||
public Option<WorkMode> o_workMode;
|
public static Option<WorkMode> o_workMode;
|
||||||
public Option<List<ClassIDType>> o_exportAssetTypes;
|
public static Option<List<ClassIDType>> o_exportAssetTypes;
|
||||||
public Option<AssetGroupOption> o_groupAssetsBy;
|
public static Option<AssetGroupOption> o_groupAssetsBy;
|
||||||
public Option<string> o_outputFolder;
|
public static Option<string> o_outputFolder;
|
||||||
public Option<bool> o_displayHelp;
|
public static Option<bool> o_displayHelp;
|
||||||
//logger
|
//logger
|
||||||
public Option<LoggerEvent> o_logLevel;
|
public static Option<LoggerEvent> o_logLevel;
|
||||||
public Option<LogOutputMode> o_logOutput;
|
public static Option<LogOutputMode> o_logOutput;
|
||||||
//convert
|
//convert
|
||||||
public bool convertTexture;
|
public static bool convertTexture;
|
||||||
public Option<ImageFormat> o_imageFormat;
|
public static Option<ImageFormat> o_imageFormat;
|
||||||
public Option<AudioFormat> o_audioFormat;
|
public static Option<AudioFormat> o_audioFormat;
|
||||||
|
//fbx
|
||||||
|
public static Option<float> o_fbxScaleFactor;
|
||||||
|
public static Option<int> o_fbxBoneSize;
|
||||||
|
//filter
|
||||||
|
public static Option<List<string>> o_filterByName;
|
||||||
|
public static Option<List<string>> o_filterByContainer;
|
||||||
|
public static Option<List<string>> o_filterByPathID;
|
||||||
|
public static Option<List<string>> o_filterByText;
|
||||||
//advanced
|
//advanced
|
||||||
public Option<ExportListType> o_exportAssetList;
|
public static Option<ExportListType> o_exportAssetList;
|
||||||
public Option<List<string>> o_filterByName;
|
public static Option<string> o_assemblyPath;
|
||||||
public Option<List<string>> o_filterByContainer;
|
public static Option<string> o_unityVersion;
|
||||||
public Option<List<string>> o_filterByPathID;
|
public static Option<bool> f_notRestoreExtensionName;
|
||||||
public Option<List<string>> o_filterByText;
|
public static Option<bool> f_loadAllAssets;
|
||||||
public Option<string> o_assemblyPath;
|
|
||||||
public Option<string> o_unityVersion;
|
|
||||||
public Option<bool> f_notRestoreExtensionName;
|
|
||||||
|
|
||||||
public CLIOptions(string[] args)
|
static CLIOptions()
|
||||||
{
|
{
|
||||||
cliArgs = args;
|
OptionExtensions.OptionGrouping = OptionGrouping;
|
||||||
InitOptions();
|
InitOptions();
|
||||||
ParseArgs(args);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InitOptions()
|
private static void OptionGrouping(string name, string desc, HelpGroups group, bool isFlag)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(name))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var optionDict = new Dictionary<string, string>() { { name, desc } };
|
||||||
|
if (!optionGroups.ContainsKey(group))
|
||||||
|
{
|
||||||
|
optionGroups.Add(group, optionDict);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
optionGroups[group].Add(name, desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isFlag)
|
||||||
|
{
|
||||||
|
flagsDict.Add(name, desc);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
optionsDict.Add(name, desc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void InitOptions()
|
||||||
{
|
{
|
||||||
isParsed = false;
|
isParsed = false;
|
||||||
showHelp = false;
|
showHelp = false;
|
||||||
|
cliArgs = null;
|
||||||
inputPath = "";
|
inputPath = "";
|
||||||
filterBy = FilterBy.None;
|
filterBy = FilterBy.None;
|
||||||
optionsDict = new Dictionary<string, string>();
|
optionsDict = new Dictionary<string, string>();
|
||||||
flagsDict = new Dictionary<string, string>();
|
flagsDict = new Dictionary<string, string>();
|
||||||
optionGroups = new Dictionary<HelpGroups, Dictionary<string, string>>();
|
optionGroups = new Dictionary<HelpGroups, Dictionary<string, string>>();
|
||||||
supportedAssetTypes = new List<ClassIDType>
|
exportableAssetTypes = new List<ClassIDType>
|
||||||
{
|
{
|
||||||
ClassIDType.Texture2D,
|
ClassIDType.Texture2D,
|
||||||
ClassIDType.Sprite,
|
ClassIDType.Sprite,
|
||||||
@@ -126,6 +154,7 @@ namespace AssetStudioCLI.Options
|
|||||||
ClassIDType.MovieTexture,
|
ClassIDType.MovieTexture,
|
||||||
ClassIDType.Mesh,
|
ClassIDType.Mesh,
|
||||||
};
|
};
|
||||||
|
knownAssetTypesDict = ((ClassIDType[])Enum.GetValues(typeof(ClassIDType))).ToHashSet().ToDictionary(x => x.ToString().ToLower(), y => y);
|
||||||
|
|
||||||
#region Init General Options
|
#region Init General Options
|
||||||
o_workMode = new GroupedOption<WorkMode>
|
o_workMode = new GroupedOption<WorkMode>
|
||||||
@@ -133,18 +162,19 @@ namespace AssetStudioCLI.Options
|
|||||||
optionDefaultValue: WorkMode.Export,
|
optionDefaultValue: WorkMode.Export,
|
||||||
optionName: "-m, --mode <value>",
|
optionName: "-m, --mode <value>",
|
||||||
optionDescription: "Specify working mode\n" +
|
optionDescription: "Specify working mode\n" +
|
||||||
"<Value: export(default) | exportRaw | dump | info | live2d>\n" +
|
"<Value: export(default) | exportRaw | dump | info | live2d | splitObjects>\n" +
|
||||||
"Export - Exports converted assets\n" +
|
"Export - Exports converted assets\n" +
|
||||||
"ExportRaw - Exports raw data\n" +
|
"ExportRaw - Exports raw data\n" +
|
||||||
"Dump - Makes asset dumps\n" +
|
"Dump - Makes asset dumps\n" +
|
||||||
"Info - Loads file(s), shows the number of available for export assets and exits\n" +
|
"Info - Loads file(s), shows the number of available for export assets and exits\n" +
|
||||||
"Live2D - Exports Live2D Cubism 3 models\n" +
|
"Live2D - Exports Live2D Cubism 3 models\n" +
|
||||||
|
"SplitObjects - Exports split objects (fbx)\n" +
|
||||||
"Example: \"-m info\"\n",
|
"Example: \"-m info\"\n",
|
||||||
optionHelpGroup: HelpGroups.General
|
optionHelpGroup: HelpGroups.General
|
||||||
);
|
);
|
||||||
o_exportAssetTypes = new GroupedOption<List<ClassIDType>>
|
o_exportAssetTypes = new GroupedOption<List<ClassIDType>>
|
||||||
(
|
(
|
||||||
optionDefaultValue: supportedAssetTypes,
|
optionDefaultValue: exportableAssetTypes,
|
||||||
optionName: "-t, --asset-type <value(s)>",
|
optionName: "-t, --asset-type <value(s)>",
|
||||||
optionDescription: "Specify asset type(s) to export\n" +
|
optionDescription: "Specify asset type(s) to export\n" +
|
||||||
"<Value(s): tex2d, sprite, textAsset, monoBehaviour, font, shader, movieTexture,\n" +
|
"<Value(s): tex2d, sprite, textAsset, monoBehaviour, font, shader, movieTexture,\n" +
|
||||||
@@ -170,7 +200,7 @@ namespace AssetStudioCLI.Options
|
|||||||
);
|
);
|
||||||
o_outputFolder = new GroupedOption<string>
|
o_outputFolder = new GroupedOption<string>
|
||||||
(
|
(
|
||||||
optionDefaultValue: "",
|
optionDefaultValue: "ASExport",
|
||||||
optionName: "-o, --output <path>",
|
optionName: "-o, --output <path>",
|
||||||
optionDescription: "Specify path to the output folder\n" +
|
optionDescription: "Specify path to the output folder\n" +
|
||||||
"If path isn't specifyed, 'ASExport' folder will be created in the program's work folder\n",
|
"If path isn't specifyed, 'ASExport' folder will be created in the program's work folder\n",
|
||||||
@@ -230,6 +260,67 @@ namespace AssetStudioCLI.Options
|
|||||||
);
|
);
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region Init FBX Options
|
||||||
|
o_fbxScaleFactor = new GroupedOption<float>
|
||||||
|
(
|
||||||
|
optionDefaultValue: 1f,
|
||||||
|
optionName: "--fbx-scale-factor <value>",
|
||||||
|
optionDescription: "Specify the FBX Scale Factor\n" +
|
||||||
|
"<Value: float number from 0 to 100 (default=1)\n" +
|
||||||
|
"Example: \"--fbx-scale-factor 50\"\n",
|
||||||
|
optionHelpGroup: HelpGroups.FBX
|
||||||
|
);
|
||||||
|
o_fbxBoneSize = new GroupedOption<int>
|
||||||
|
(
|
||||||
|
optionDefaultValue: 10,
|
||||||
|
optionName: "--fbx-bone-size <value>",
|
||||||
|
optionDescription: "Specify the FBX Bone Size\n" +
|
||||||
|
"<Value: integer number from 0 to 100 (default=10)\n" +
|
||||||
|
"Example: \"--fbx-bone-size 10\"",
|
||||||
|
optionHelpGroup: HelpGroups.FBX
|
||||||
|
);
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Init Filter Options
|
||||||
|
o_filterByName = new GroupedOption<List<string>>
|
||||||
|
(
|
||||||
|
optionDefaultValue: new List<string>(),
|
||||||
|
optionName: "--filter-by-name <text>",
|
||||||
|
optionDescription: "Specify the name by which assets should be filtered\n" +
|
||||||
|
"*To specify multiple names write them separated by ',' or ';' without spaces\n" +
|
||||||
|
"Example: \"--filter-by-name char\" or \"--filter-by-name char,bg\"\n",
|
||||||
|
optionHelpGroup: HelpGroups.Filter
|
||||||
|
);
|
||||||
|
o_filterByContainer = new GroupedOption<List<string>>
|
||||||
|
(
|
||||||
|
optionDefaultValue: new List<string>(),
|
||||||
|
optionName: "--filter-by-container <text>",
|
||||||
|
optionDescription: "Specify the container by which assets should be filtered\n" +
|
||||||
|
"*To specify multiple containers write them separated by ',' or ';' without spaces\n" +
|
||||||
|
"Example: \"--filter-by-container arts\" or \"--filter-by-container arts,icons\"\n",
|
||||||
|
optionHelpGroup: HelpGroups.Filter
|
||||||
|
);
|
||||||
|
o_filterByPathID = new GroupedOption<List<string>>
|
||||||
|
(
|
||||||
|
optionDefaultValue: new List<string>(),
|
||||||
|
optionName: "--filter-by-pathid <text>",
|
||||||
|
optionDescription: "Specify the PathID by which assets should be filtered\n" +
|
||||||
|
"*To specify multiple PathIDs write them separated by ',' or ';' without spaces\n" +
|
||||||
|
"Example: \"--filter-by-pathid 7238605633795851352,-2430306240205277265\"\n",
|
||||||
|
optionHelpGroup: HelpGroups.Filter
|
||||||
|
);
|
||||||
|
o_filterByText = new GroupedOption<List<string>>
|
||||||
|
(
|
||||||
|
optionDefaultValue: new List<string>(),
|
||||||
|
optionName: "--filter-by-text <text>",
|
||||||
|
optionDescription: "Specify the text by which assets should be filtered\n" +
|
||||||
|
"Looks for assets that contain the specified text in their names or containers\n" +
|
||||||
|
"*To specify multiple values write them separated by ',' or ';' without spaces\n" +
|
||||||
|
"Example: \"--filter-by-text portrait\" or \"--filter-by-text portrait,art\"\n",
|
||||||
|
optionHelpGroup: HelpGroups.Filter
|
||||||
|
);
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region Init Advanced Options
|
#region Init Advanced Options
|
||||||
o_exportAssetList = new GroupedOption<ExportListType>
|
o_exportAssetList = new GroupedOption<ExportListType>
|
||||||
(
|
(
|
||||||
@@ -241,101 +332,47 @@ namespace AssetStudioCLI.Options
|
|||||||
"Example: \"--export-asset-list xml\"\n",
|
"Example: \"--export-asset-list xml\"\n",
|
||||||
optionHelpGroup: HelpGroups.Advanced
|
optionHelpGroup: HelpGroups.Advanced
|
||||||
);
|
);
|
||||||
o_filterByName = new GroupedOption<List<string>>
|
|
||||||
(
|
|
||||||
optionDefaultValue: new List<string>(),
|
|
||||||
optionName: "--filter-by-name <text>",
|
|
||||||
optionDescription: "Specify the name by which assets should be filtered\n" +
|
|
||||||
"*To specify multiple names write them separated by ',' or ';' without spaces\n" +
|
|
||||||
"Example: \"--filter-by-name char\" or \"--filter-by-name char,bg\"\n",
|
|
||||||
optionHelpGroup: HelpGroups.Advanced
|
|
||||||
);
|
|
||||||
o_filterByContainer = new GroupedOption<List<string>>
|
|
||||||
(
|
|
||||||
optionDefaultValue: new List<string>(),
|
|
||||||
optionName: "--filter-by-container <text>",
|
|
||||||
optionDescription: "Specify the container by which assets should be filtered\n" +
|
|
||||||
"*To specify multiple containers write them separated by ',' or ';' without spaces\n" +
|
|
||||||
"Example: \"--filter-by-container arts\" or \"--filter-by-container arts,icons\"\n",
|
|
||||||
optionHelpGroup: HelpGroups.Advanced
|
|
||||||
);
|
|
||||||
o_filterByPathID = new GroupedOption<List<string>>
|
|
||||||
(
|
|
||||||
optionDefaultValue: new List<string>(),
|
|
||||||
optionName: "--filter-by-pathid <text>",
|
|
||||||
optionDescription: "Specify the PathID by which assets should be filtered\n" +
|
|
||||||
"*To specify multiple PathIDs write them separated by ',' or ';' without spaces\n" +
|
|
||||||
"Example: \"--filter-by-pathid 7238605633795851352,-2430306240205277265\"\n",
|
|
||||||
optionHelpGroup: HelpGroups.Advanced
|
|
||||||
);
|
|
||||||
o_filterByText = new GroupedOption<List<string>>
|
|
||||||
(
|
|
||||||
optionDefaultValue: new List<string>(),
|
|
||||||
optionName: "--filter-by-text <text>",
|
|
||||||
optionDescription: "Specify the text by which assets should be filtered\n" +
|
|
||||||
"Looks for assets that contain the specified text in their names or containers\n" +
|
|
||||||
"*To specify multiple values write them separated by ',' or ';' without spaces\n" +
|
|
||||||
"Example: \"--filter-by-text portrait\" or \"--filter-by-text portrait,art\"\n",
|
|
||||||
optionHelpGroup: HelpGroups.Advanced
|
|
||||||
);
|
|
||||||
o_assemblyPath = new GroupedOption<string>
|
o_assemblyPath = new GroupedOption<string>
|
||||||
(
|
(
|
||||||
optionDefaultValue: "",
|
optionDefaultValue: "",
|
||||||
optionName: "--assembly-folder <path>",
|
optionName: "--assembly-folder <path>",
|
||||||
optionDescription: "Specify the path to the assembly folder",
|
optionDescription: "Specify the path to the assembly folder\n",
|
||||||
optionHelpGroup: HelpGroups.Advanced
|
optionHelpGroup: HelpGroups.Advanced
|
||||||
);
|
);
|
||||||
o_unityVersion = new GroupedOption<string>
|
o_unityVersion = new GroupedOption<string>
|
||||||
(
|
(
|
||||||
optionDefaultValue: "",
|
optionDefaultValue: "",
|
||||||
optionName: "--unity-version <text>",
|
optionName: "--unity-version <text>",
|
||||||
optionDescription: "Specify Unity version. Example: \"--unity-version 2017.4.39f1\"",
|
optionDescription: "Specify Unity version\nExample: \"--unity-version 2017.4.39f1\"\n",
|
||||||
optionHelpGroup: HelpGroups.Advanced
|
optionHelpGroup: HelpGroups.Advanced
|
||||||
);
|
);
|
||||||
f_notRestoreExtensionName = new GroupedOption<bool>
|
f_notRestoreExtensionName = new GroupedOption<bool>
|
||||||
(
|
(
|
||||||
optionDefaultValue: false,
|
optionDefaultValue: false,
|
||||||
optionName: "--not-restore-extension",
|
optionName: "--not-restore-extension",
|
||||||
optionDescription: "(Flag) If specified, AssetStudio will not try to use/restore original TextAsset\nextension name, and will just export all TextAssets with the \".txt\" extension",
|
optionDescription: "(Flag) If specified, AssetStudio will not try to use/restore original TextAsset\nextension name, and will just export all TextAssets with the \".txt\" extension\n",
|
||||||
|
optionHelpGroup: HelpGroups.Advanced,
|
||||||
|
isFlag: true
|
||||||
|
);
|
||||||
|
f_loadAllAssets = new GroupedOption<bool>
|
||||||
|
(
|
||||||
|
optionDefaultValue: false,
|
||||||
|
optionName: "--load-all",
|
||||||
|
optionDescription: "(Flag) If specified, AssetStudio will load assets of all types\n(Only for Dump, Info and ExportRaw modes)",
|
||||||
optionHelpGroup: HelpGroups.Advanced,
|
optionHelpGroup: HelpGroups.Advanced,
|
||||||
isFlag: true
|
isFlag: true
|
||||||
);
|
);
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void OptionGrouping(string name, string desc, HelpGroups group, bool isFlag)
|
public static void ParseArgs(string[] args)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(name))
|
cliArgs = args;
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var optionDict = new Dictionary<string, string>() { { name, desc } };
|
|
||||||
if (!optionGroups.ContainsKey(group))
|
|
||||||
{
|
|
||||||
optionGroups.Add(group, optionDict);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
optionGroups[group].Add(name, desc);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isFlag)
|
|
||||||
{
|
|
||||||
flagsDict.Add(name, desc);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
optionsDict.Add(name, desc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ParseArgs(string[] args)
|
|
||||||
{
|
|
||||||
var brightYellow = CLIAnsiColors.BrightYellow;
|
var brightYellow = CLIAnsiColors.BrightYellow;
|
||||||
var brightRed = CLIAnsiColors.BrightRed;
|
var brightRed = CLIAnsiColors.BrightRed;
|
||||||
|
|
||||||
if (args.Length == 0 || args.Any(x => x == "-h" || x == "--help"))
|
if (args.Length == 0 || args.Any(x => x.ToLower() == "-h" || x.ToLower() == "--help" || x.ToLower() == "-?"))
|
||||||
{
|
{
|
||||||
showHelp = true;
|
showHelp = true;
|
||||||
return;
|
return;
|
||||||
@@ -350,7 +387,6 @@ namespace AssetStudioCLI.Options
|
|||||||
$"Specified file or folder was not found. The input path must be specified as the first argument.");
|
$"Specified file or folder was not found. The input path must be specified as the first argument.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
o_outputFolder.Value = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "ASExport");
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -375,6 +411,64 @@ namespace AssetStudioCLI.Options
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var workModeOptionIndex = resplittedArgs.FindIndex(x => x.ToLower() == "-m" || x.ToLower() == "--mode");
|
||||||
|
if (workModeOptionIndex >= 0)
|
||||||
|
{
|
||||||
|
var option = resplittedArgs[workModeOptionIndex];
|
||||||
|
if (workModeOptionIndex + 1 >= resplittedArgs.Count)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"{"Error during parsing options:".Color(brightRed)} Value for [{option.Color(brightRed)}] option was not found.\n");
|
||||||
|
TryShowOptionDescription(option, optionsDict);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var value = resplittedArgs[workModeOptionIndex + 1];
|
||||||
|
switch (value.ToLower())
|
||||||
|
{
|
||||||
|
case "export":
|
||||||
|
o_workMode.Value = WorkMode.Export;
|
||||||
|
break;
|
||||||
|
case "raw":
|
||||||
|
case "exportraw":
|
||||||
|
o_workMode.Value = WorkMode.ExportRaw;
|
||||||
|
break;
|
||||||
|
case "dump":
|
||||||
|
o_workMode.Value = WorkMode.Dump;
|
||||||
|
break;
|
||||||
|
case "info":
|
||||||
|
o_workMode.Value = WorkMode.Info;
|
||||||
|
break;
|
||||||
|
case "live2d":
|
||||||
|
o_workMode.Value = WorkMode.ExportLive2D;
|
||||||
|
o_exportAssetTypes.Value = new List<ClassIDType>()
|
||||||
|
{
|
||||||
|
ClassIDType.AnimationClip,
|
||||||
|
ClassIDType.GameObject,
|
||||||
|
ClassIDType.MonoBehaviour,
|
||||||
|
ClassIDType.Texture2D,
|
||||||
|
ClassIDType.Transform,
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
case "splitobjects":
|
||||||
|
o_workMode.Value = WorkMode.SplitObjects;
|
||||||
|
o_exportAssetTypes.Value = new List<ClassIDType>()
|
||||||
|
{
|
||||||
|
ClassIDType.GameObject,
|
||||||
|
ClassIDType.Texture2D,
|
||||||
|
ClassIDType.Material,
|
||||||
|
ClassIDType.Transform,
|
||||||
|
ClassIDType.Mesh,
|
||||||
|
ClassIDType.MeshRenderer,
|
||||||
|
ClassIDType.MeshFilter,
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Console.WriteLine($"{"Error".Color(brightRed)} during parsing [{option}] option. Unsupported working mode: [{value.Color(brightRed)}].\n");
|
||||||
|
Console.WriteLine(o_workMode.Description);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
resplittedArgs.RemoveRange(workModeOptionIndex, 2);
|
||||||
|
}
|
||||||
|
|
||||||
#region Parse Flags
|
#region Parse Flags
|
||||||
for (int i = 0; i < resplittedArgs.Count; i++)
|
for (int i = 0; i < resplittedArgs.Count; i++)
|
||||||
{
|
{
|
||||||
@@ -386,6 +480,21 @@ namespace AssetStudioCLI.Options
|
|||||||
f_notRestoreExtensionName.Value = true;
|
f_notRestoreExtensionName.Value = true;
|
||||||
resplittedArgs.RemoveAt(i);
|
resplittedArgs.RemoveAt(i);
|
||||||
break;
|
break;
|
||||||
|
case "--load-all":
|
||||||
|
switch (o_workMode.Value)
|
||||||
|
{
|
||||||
|
case WorkMode.ExportRaw:
|
||||||
|
case WorkMode.Dump:
|
||||||
|
case WorkMode.Info:
|
||||||
|
f_loadAllAssets.Value = true;
|
||||||
|
resplittedArgs.RemoveAt(i);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Console.WriteLine($"{"Error".Color(brightRed)} during parsing [{flag}] flag. This flag is not suitable for the current working mode [{o_workMode.Value}].\n");
|
||||||
|
Console.WriteLine(f_loadAllAssets.Description);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
@@ -399,43 +508,9 @@ namespace AssetStudioCLI.Options
|
|||||||
var value = resplittedArgs[i + 1].Replace("\"", "");
|
var value = resplittedArgs[i + 1].Replace("\"", "");
|
||||||
switch (option)
|
switch (option)
|
||||||
{
|
{
|
||||||
case "-m":
|
|
||||||
case "--mode":
|
|
||||||
switch (value.ToLower())
|
|
||||||
{
|
|
||||||
case "export":
|
|
||||||
o_workMode.Value = WorkMode.Export;
|
|
||||||
break;
|
|
||||||
case "raw":
|
|
||||||
case "exportraw":
|
|
||||||
o_workMode.Value = WorkMode.ExportRaw;
|
|
||||||
break;
|
|
||||||
case "dump":
|
|
||||||
o_workMode.Value = WorkMode.Dump;
|
|
||||||
break;
|
|
||||||
case "info":
|
|
||||||
o_workMode.Value = WorkMode.Info;
|
|
||||||
break;
|
|
||||||
case "live2d":
|
|
||||||
o_workMode.Value = WorkMode.ExportLive2D;
|
|
||||||
o_exportAssetTypes.Value = new List<ClassIDType>()
|
|
||||||
{
|
|
||||||
ClassIDType.AnimationClip,
|
|
||||||
ClassIDType.GameObject,
|
|
||||||
ClassIDType.MonoBehaviour,
|
|
||||||
ClassIDType.Texture2D,
|
|
||||||
ClassIDType.Transform,
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Console.WriteLine($"{"Error".Color(brightRed)} during parsing [{option}] option. Unsupported working mode: [{value.Color(brightRed)}].\n");
|
|
||||||
Console.WriteLine(o_workMode.Description);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "-t":
|
case "-t":
|
||||||
case "--asset-type":
|
case "--asset-type":
|
||||||
if (o_workMode.Value == WorkMode.ExportLive2D)
|
if (o_workMode.Value == WorkMode.ExportLive2D || o_workMode.Value == WorkMode.SplitObjects)
|
||||||
{
|
{
|
||||||
i++;
|
i++;
|
||||||
continue;
|
continue;
|
||||||
@@ -447,43 +522,34 @@ namespace AssetStudioCLI.Options
|
|||||||
switch (type.ToLower())
|
switch (type.ToLower())
|
||||||
{
|
{
|
||||||
case "tex2d":
|
case "tex2d":
|
||||||
case "texture2d":
|
|
||||||
o_exportAssetTypes.Value.Add(ClassIDType.Texture2D);
|
o_exportAssetTypes.Value.Add(ClassIDType.Texture2D);
|
||||||
break;
|
break;
|
||||||
case "sprite":
|
|
||||||
o_exportAssetTypes.Value.Add(ClassIDType.Sprite);
|
|
||||||
break;
|
|
||||||
case "textasset":
|
|
||||||
o_exportAssetTypes.Value.Add(ClassIDType.TextAsset);
|
|
||||||
break;
|
|
||||||
case "monobehaviour":
|
|
||||||
o_exportAssetTypes.Value.Add(ClassIDType.MonoBehaviour);
|
|
||||||
break;
|
|
||||||
case "font":
|
|
||||||
o_exportAssetTypes.Value.Add(ClassIDType.Font);
|
|
||||||
break;
|
|
||||||
case "shader":
|
|
||||||
o_exportAssetTypes.Value.Add(ClassIDType.Shader);
|
|
||||||
break;
|
|
||||||
case "audio":
|
case "audio":
|
||||||
case "audioclip":
|
|
||||||
o_exportAssetTypes.Value.Add(ClassIDType.AudioClip);
|
o_exportAssetTypes.Value.Add(ClassIDType.AudioClip);
|
||||||
break;
|
break;
|
||||||
case "video":
|
case "video":
|
||||||
case "videoclip":
|
|
||||||
o_exportAssetTypes.Value.Add(ClassIDType.VideoClip);
|
o_exportAssetTypes.Value.Add(ClassIDType.VideoClip);
|
||||||
break;
|
break;
|
||||||
case "movietexture":
|
|
||||||
o_exportAssetTypes.Value.Add(ClassIDType.MovieTexture);
|
|
||||||
break;
|
|
||||||
case "mesh":
|
|
||||||
o_exportAssetTypes.Value.Add(ClassIDType.Mesh);
|
|
||||||
break;
|
|
||||||
case "all":
|
case "all":
|
||||||
o_exportAssetTypes.Value = supportedAssetTypes;
|
o_exportAssetTypes.Value = exportableAssetTypes;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Console.WriteLine($"{"Error".Color(brightRed)} during parsing [{option}] option. Unsupported asset type: [{value.Color(brightRed)}].\n");
|
var isKnownType = knownAssetTypesDict.TryGetValue(type.ToLower(), out var assetType);
|
||||||
|
if (isKnownType)
|
||||||
|
{
|
||||||
|
if (f_loadAllAssets.Value || exportableAssetTypes.Contains(assetType))
|
||||||
|
{
|
||||||
|
o_exportAssetTypes.Value.Add(assetType);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine($"{"Error".Color(brightRed)} during parsing [{option}] option. Unknown asset type specified [{type.Color(brightRed)}].\n");
|
||||||
|
Console.WriteLine(o_exportAssetTypes.Description);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Console.WriteLine($"{"Error".Color(brightRed)} during parsing [{option}] option. Asset type [{type.Color(brightRed)}] is not supported for exporting.\n");
|
||||||
Console.WriteLine(o_exportAssetTypes.Description);
|
Console.WriteLine(o_exportAssetTypes.Description);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -523,6 +589,10 @@ namespace AssetStudioCLI.Options
|
|||||||
{
|
{
|
||||||
Directory.CreateDirectory(value);
|
Directory.CreateDirectory(value);
|
||||||
}
|
}
|
||||||
|
if (!value.EndsWith($"{Path.DirectorySeparatorChar}"))
|
||||||
|
{
|
||||||
|
value += Path.DirectorySeparatorChar;
|
||||||
|
}
|
||||||
o_outputFolder.Value = value;
|
o_outputFolder.Value = value;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@@ -623,6 +693,32 @@ namespace AssetStudioCLI.Options
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case "--fbx-scale-factor":
|
||||||
|
var isFloat = float.TryParse(value, out float floatValue);
|
||||||
|
if (isFloat && floatValue >= 0 && floatValue <= 100)
|
||||||
|
{
|
||||||
|
o_fbxScaleFactor.Value = floatValue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine($"{"Error".Color(brightRed)} during parsing [{option}] option. Unsupported scale factor value: [{value.Color(brightRed)}].\n");
|
||||||
|
Console.WriteLine(o_fbxScaleFactor.Description);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "--fbx-bone-size":
|
||||||
|
var isInt = int.TryParse(value, out int intValue);
|
||||||
|
if (isInt && intValue >= 0 && intValue <= 100)
|
||||||
|
{
|
||||||
|
o_fbxBoneSize.Value = intValue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine($"{"Error".Color(brightRed)} during parsing [{option}] option. Unsupported bone size value: [{value.Color(brightRed)}].\n");
|
||||||
|
Console.WriteLine(o_fbxBoneSize.Description);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case "--export-asset-list":
|
case "--export-asset-list":
|
||||||
switch (value.ToLower())
|
switch (value.ToLower())
|
||||||
{
|
{
|
||||||
@@ -658,6 +754,7 @@ namespace AssetStudioCLI.Options
|
|||||||
if (Directory.Exists(value))
|
if (Directory.Exists(value))
|
||||||
{
|
{
|
||||||
o_assemblyPath.Value = value;
|
o_assemblyPath.Value = value;
|
||||||
|
Studio.assemblyLoader.Load(value);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -703,8 +800,22 @@ namespace AssetStudioCLI.Options
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
isParsed = true;
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
if (!Studio.assemblyLoader.Loaded)
|
||||||
|
{
|
||||||
|
Studio.assemblyLoader.Loaded = true;
|
||||||
|
}
|
||||||
|
if (o_outputFolder.Value == o_outputFolder.DefaultValue)
|
||||||
|
{
|
||||||
|
var fullPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, o_outputFolder.DefaultValue + Path.DirectorySeparatorChar);
|
||||||
|
if (!Directory.Exists(fullPath))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(fullPath);
|
||||||
|
}
|
||||||
|
o_outputFolder.Value = fullPath;
|
||||||
|
}
|
||||||
|
isParsed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string[] ValueSplitter(string value)
|
private static string[] ValueSplitter(string value)
|
||||||
@@ -713,7 +824,7 @@ namespace AssetStudioCLI.Options
|
|||||||
return value.Split(separator);
|
return value.Split(separator);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool TryShowOptionDescription(string option, Dictionary<string, string> descDict)
|
private static bool TryShowOptionDescription(string option, Dictionary<string, string> descDict)
|
||||||
{
|
{
|
||||||
var optionDesc = descDict.Where(x => x.Key.Contains(option));
|
var optionDesc = descDict.Where(x => x.Key.Contains(option));
|
||||||
if (optionDesc.Any())
|
if (optionDesc.Any())
|
||||||
@@ -728,7 +839,7 @@ namespace AssetStudioCLI.Options
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ShowHelp(bool showUsageOnly = false)
|
public static void ShowHelp(bool showUsageOnly = false)
|
||||||
{
|
{
|
||||||
const int indent = 22;
|
const int indent = 22;
|
||||||
var helpMessage = new StringBuilder();
|
var helpMessage = new StringBuilder();
|
||||||
@@ -761,12 +872,13 @@ namespace AssetStudioCLI.Options
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Console.WriteLine($"# {appAssembly.Name}\n# Based on AssetStudioMod v{appAssembly.Version}\n");
|
var arch = Environment.Is64BitProcess ? "x64" : "x32";
|
||||||
|
Console.WriteLine($"# {appAssembly.Name} [{arch}]\n# Based on AssetStudioMod v{appAssembly.Version}\n");
|
||||||
Console.WriteLine($"{usage}\n\n{helpMessage}");
|
Console.WriteLine($"{usage}\n\n{helpMessage}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private string ShowCurrentFilter()
|
private static string ShowCurrentFilter()
|
||||||
{
|
{
|
||||||
switch (filterBy)
|
switch (filterBy)
|
||||||
{
|
{
|
||||||
@@ -785,7 +897,22 @@ namespace AssetStudioCLI.Options
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ShowCurrentOptions()
|
private static string ShowExportTypes()
|
||||||
|
{
|
||||||
|
switch (o_workMode.Value)
|
||||||
|
{
|
||||||
|
case WorkMode.ExportRaw:
|
||||||
|
case WorkMode.Dump:
|
||||||
|
case WorkMode.Info:
|
||||||
|
return f_loadAllAssets.Value && o_exportAssetTypes.Value == o_exportAssetTypes.DefaultValue
|
||||||
|
? $"# Export Asset Type(s): All"
|
||||||
|
: $"# Export Asset Type(s): {string.Join(", ", o_exportAssetTypes.Value)}";
|
||||||
|
default:
|
||||||
|
return $"# Export Asset Type(s): {string.Join(", ", o_exportAssetTypes.Value)}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ShowCurrentOptions()
|
||||||
{
|
{
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
sb.AppendLine("[Current Options]");
|
sb.AppendLine("[Current Options]");
|
||||||
@@ -793,8 +920,35 @@ namespace AssetStudioCLI.Options
|
|||||||
sb.AppendLine($"# Input Path: \"{inputPath}\"");
|
sb.AppendLine($"# Input Path: \"{inputPath}\"");
|
||||||
switch (o_workMode.Value)
|
switch (o_workMode.Value)
|
||||||
{
|
{
|
||||||
|
case WorkMode.Export:
|
||||||
|
case WorkMode.ExportRaw:
|
||||||
|
case WorkMode.Dump:
|
||||||
|
sb.AppendLine($"# Output Path: \"{o_outputFolder}\"");
|
||||||
|
if (o_workMode.Value != WorkMode.Export)
|
||||||
|
{
|
||||||
|
sb.AppendLine($"# Load All Assets: {f_loadAllAssets}");
|
||||||
|
}
|
||||||
|
sb.AppendLine(ShowExportTypes());
|
||||||
|
sb.AppendLine($"# Asset Group Option: {o_groupAssetsBy}");
|
||||||
|
if (o_workMode.Value == WorkMode.Export)
|
||||||
|
{
|
||||||
|
sb.AppendLine($"# Export Image Format: {o_imageFormat}");
|
||||||
|
sb.AppendLine($"# Export Audio Format: {o_audioFormat}");
|
||||||
|
}
|
||||||
|
sb.AppendLine($"# Log Level: {o_logLevel}");
|
||||||
|
sb.AppendLine($"# Log Output: {o_logOutput}");
|
||||||
|
sb.AppendLine($"# Export Asset List: {o_exportAssetList}");
|
||||||
|
sb.AppendLine(ShowCurrentFilter());
|
||||||
|
sb.AppendLine($"# Assebmly Path: \"{o_assemblyPath}\"");
|
||||||
|
sb.AppendLine($"# Unity Version: \"{o_unityVersion}\"");
|
||||||
|
if (o_workMode.Value == WorkMode.Export)
|
||||||
|
{
|
||||||
|
sb.AppendLine($"# Restore TextAsset Extension: {!f_notRestoreExtensionName.Value}");
|
||||||
|
}
|
||||||
|
break;
|
||||||
case WorkMode.Info:
|
case WorkMode.Info:
|
||||||
sb.AppendLine($"# Export Asset Type(s): {string.Join(", ", o_exportAssetTypes.Value)}");
|
sb.AppendLine($"# Load All Assets: {f_loadAllAssets}");
|
||||||
|
sb.AppendLine(ShowExportTypes());
|
||||||
sb.AppendLine($"# Log Level: {o_logLevel}");
|
sb.AppendLine($"# Log Level: {o_logLevel}");
|
||||||
sb.AppendLine($"# Log Output: {o_logOutput}");
|
sb.AppendLine($"# Log Output: {o_logOutput}");
|
||||||
sb.AppendLine($"# Export Asset List: {o_exportAssetList}");
|
sb.AppendLine($"# Export Asset List: {o_exportAssetList}");
|
||||||
@@ -802,27 +956,22 @@ namespace AssetStudioCLI.Options
|
|||||||
sb.AppendLine($"# Unity Version: \"{o_unityVersion}\"");
|
sb.AppendLine($"# Unity Version: \"{o_unityVersion}\"");
|
||||||
break;
|
break;
|
||||||
case WorkMode.ExportLive2D:
|
case WorkMode.ExportLive2D:
|
||||||
|
case WorkMode.SplitObjects:
|
||||||
sb.AppendLine($"# Output Path: \"{o_outputFolder}\"");
|
sb.AppendLine($"# Output Path: \"{o_outputFolder}\"");
|
||||||
sb.AppendLine($"# Log Level: {o_logLevel}");
|
sb.AppendLine($"# Log Level: {o_logLevel}");
|
||||||
sb.AppendLine($"# Log Output: {o_logOutput}");
|
sb.AppendLine($"# Log Output: {o_logOutput}");
|
||||||
sb.AppendLine($"# Export Asset List: {o_exportAssetList}");
|
sb.AppendLine($"# Export Asset List: {o_exportAssetList}");
|
||||||
sb.AppendLine($"# Assebmly Path: \"{o_assemblyPath}\"");
|
if (o_workMode.Value == WorkMode.SplitObjects)
|
||||||
|
{
|
||||||
|
sb.AppendLine($"# Export Image Format: {o_imageFormat}");
|
||||||
|
sb.AppendLine($"# Filter by Name(s): \"{string.Join("\", \"", o_filterByName.Value)}\"");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sb.AppendLine($"# Assebmly Path: \"{o_assemblyPath}\"");
|
||||||
|
}
|
||||||
sb.AppendLine($"# Unity Version: \"{o_unityVersion}\"");
|
sb.AppendLine($"# Unity Version: \"{o_unityVersion}\"");
|
||||||
break;
|
break;
|
||||||
default:
|
|
||||||
sb.AppendLine($"# Output Path: \"{o_outputFolder}\"");
|
|
||||||
sb.AppendLine($"# Export Asset Type(s): {string.Join(", ", o_exportAssetTypes.Value)}");
|
|
||||||
sb.AppendLine($"# Asset Group Option: {o_groupAssetsBy}");
|
|
||||||
sb.AppendLine($"# Export Image Format: {o_imageFormat}");
|
|
||||||
sb.AppendLine($"# Export Audio Format: {o_audioFormat}");
|
|
||||||
sb.AppendLine($"# Log Level: {o_logLevel}");
|
|
||||||
sb.AppendLine($"# Log Output: {o_logOutput}");
|
|
||||||
sb.AppendLine($"# Export Asset List: {o_exportAssetList}");
|
|
||||||
sb.AppendLine(ShowCurrentFilter());
|
|
||||||
sb.AppendLine($"# Assebmly Path: \"{o_assemblyPath}\"");
|
|
||||||
sb.AppendLine($"# Unity Version: \"{o_unityVersion}\"");
|
|
||||||
sb.AppendLine($"# Restore TextAsset extension: {!f_notRestoreExtensionName.Value}");
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
sb.AppendLine("======");
|
sb.AppendLine("======");
|
||||||
Logger.Info(sb.ToString());
|
Logger.Info(sb.ToString());
|
||||||
|
|||||||
17
AssetStudioCLI/Options/OptionExtensions.cs
Normal file
17
AssetStudioCLI/Options/OptionExtensions.cs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace AssetStudioCLI.Options
|
||||||
|
{
|
||||||
|
internal static class OptionExtensions
|
||||||
|
{
|
||||||
|
public static Action<string, string, HelpGroups, bool> OptionGrouping = (name, desc, group, isFlag) => { };
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class GroupedOption<T> : Option<T>
|
||||||
|
{
|
||||||
|
public GroupedOption(T optionDefaultValue, string optionName, string optionDescription, HelpGroups optionHelpGroup, bool isFlag = false) : base(optionDefaultValue, optionName, optionDescription, optionHelpGroup, isFlag)
|
||||||
|
{
|
||||||
|
OptionExtensions.OptionGrouping(optionName, optionDescription, optionHelpGroup, isFlag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,52 +8,54 @@ namespace AssetStudioCLI
|
|||||||
{
|
{
|
||||||
public static void Main(string[] args)
|
public static void Main(string[] args)
|
||||||
{
|
{
|
||||||
var options = new CLIOptions(args);
|
CLIOptions.ParseArgs(args);
|
||||||
if (options.isParsed)
|
if (CLIOptions.isParsed)
|
||||||
{
|
{
|
||||||
CLIRun(options);
|
CLIRun();
|
||||||
}
|
}
|
||||||
else if (options.showHelp)
|
else if (CLIOptions.showHelp)
|
||||||
{
|
{
|
||||||
options.ShowHelp();
|
CLIOptions.ShowHelp();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Console.WriteLine();
|
Console.WriteLine();
|
||||||
options.ShowHelp(showUsageOnly: true);
|
CLIOptions.ShowHelp(showUsageOnly: true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void CLIRun(CLIOptions options)
|
private static void CLIRun()
|
||||||
{
|
{
|
||||||
var cliLogger = new CLILogger(options);
|
var cliLogger = new CLILogger();
|
||||||
Logger.Default = cliLogger;
|
Logger.Default = cliLogger;
|
||||||
var studio = new Studio(options);
|
CLIOptions.ShowCurrentOptions();
|
||||||
options.ShowCurrentOptions();
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (studio.LoadAssets())
|
if (Studio.LoadAssets())
|
||||||
{
|
{
|
||||||
studio.ParseAssets();
|
Studio.ParseAssets();
|
||||||
if (options.filterBy != FilterBy.None && options.o_workMode.Value != WorkMode.ExportLive2D)
|
if (CLIOptions.filterBy != FilterBy.None)
|
||||||
{
|
{
|
||||||
studio.FilterAssets();
|
Studio.Filter();
|
||||||
}
|
}
|
||||||
if (options.o_exportAssetList.Value != ExportListType.None)
|
if (CLIOptions.o_exportAssetList.Value != ExportListType.None)
|
||||||
{
|
{
|
||||||
studio.ExportAssetList();
|
Studio.ExportAssetList();
|
||||||
}
|
}
|
||||||
switch (options.o_workMode.Value)
|
switch (CLIOptions.o_workMode.Value)
|
||||||
{
|
{
|
||||||
case WorkMode.Info:
|
case WorkMode.Info:
|
||||||
studio.ShowExportableAssetsInfo();
|
Studio.ShowExportableAssetsInfo();
|
||||||
break;
|
break;
|
||||||
case WorkMode.ExportLive2D:
|
case WorkMode.ExportLive2D:
|
||||||
studio.ExportLive2D();
|
Studio.ExportLive2D();
|
||||||
|
break;
|
||||||
|
case WorkMode.SplitObjects:
|
||||||
|
Studio.ExportSplitObjects();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
studio.ExportAssets();
|
Studio.ExportAssets();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
## AssetStudioModCLI
|
## AssetStudioModCLI
|
||||||
CLI version of AssetStudioMod.
|
CLI version of AssetStudioMod.
|
||||||
- Supported asset types: `Texture2D`, `Sprite`, `TextAsset`, `MonoBehaviour`, `Font`, `Shader`, `MovieTexture`, `AudioClip`, `VideoClip`, `Mesh`.
|
- Supported asset types for export: `Texture2D`, `Sprite`, `TextAsset`, `MonoBehaviour`, `Font`, `Shader`, `MovieTexture`, `AudioClip`, `VideoClip`, `Mesh`.
|
||||||
- *There are no plans to add support for `AnimationClip`, `Animator` for now.*
|
- *There are no plans to add support for `AnimationClip`, `Animator` for now.*
|
||||||
|
|
||||||
### Usage
|
### Usage
|
||||||
@@ -10,20 +10,22 @@ AssetStudioModCLI <input path to asset file/folder> [-m, --mode <value>]
|
|||||||
[-o, --output <path>] [-h, --help]
|
[-o, --output <path>] [-h, --help]
|
||||||
[--log-level <value>] [--log-output <value>]
|
[--log-level <value>] [--log-output <value>]
|
||||||
[--image-format <value>] [--audio-format <value>]
|
[--image-format <value>] [--audio-format <value>]
|
||||||
[--export-asset-list <value>] [--filter-by-name <text>]
|
[--fbx-scale-factor <value>] [--fbx-bone-size <value>]
|
||||||
[--filter-by-container <text>] [--filter-by-pathid <text>]
|
[--filter-by-name <text>] [--filter-by-container <text>]
|
||||||
[--filter-by-text <text>] [--assembly-folder <path>]
|
[--filter-by-pathid <text>] [--filter-by-text <text>]
|
||||||
|
[--export-asset-list <value>] [--assembly-folder <path>]
|
||||||
[--unity-version <text>] [--not-restore-extension]
|
[--unity-version <text>] [--not-restore-extension]
|
||||||
|
[--load-all]
|
||||||
|
|
||||||
General Options:
|
General Options:
|
||||||
-m, --mode <value> Specify working mode
|
-m, --mode <value> Specify working mode
|
||||||
<Value: export(default) | exportRaw | dump | info | live2d>
|
<Value: export(default) | exportRaw | dump | info | live2d | splitObjects>
|
||||||
Export - Exports converted assets
|
Export - Exports converted assets
|
||||||
ExportRaw - Exports raw data
|
ExportRaw - Exports raw data
|
||||||
Dump - Makes asset dumps
|
Dump - Makes asset dumps
|
||||||
Info - Loads file(s), shows the number of available for export assets and exits
|
Info - Loads file(s), shows the number of available for export assets and exits
|
||||||
Live2D - Exports Live2D Cubism 3 models
|
Live2D - Exports Live2D Cubism 3 models
|
||||||
|
SplitObjects - Exports split objects (fbx)
|
||||||
Example: "-m info"
|
Example: "-m info"
|
||||||
|
|
||||||
-t, --asset-type <value(s)> Specify asset type(s) to export
|
-t, --asset-type <value(s)> Specify asset type(s) to export
|
||||||
@@ -67,12 +69,16 @@ Convert Options:
|
|||||||
None - Do not convert audios and export them in their own format
|
None - Do not convert audios and export them in their own format
|
||||||
Example: "--audio-format wav"
|
Example: "--audio-format wav"
|
||||||
|
|
||||||
Advanced Options:
|
FBX Options:
|
||||||
--export-asset-list <value> Specify the format in which you want to export asset list
|
--fbx-scale-factor <value> Specify the FBX Scale Factor
|
||||||
<Value: none(default) | xml>
|
<Value: float number from 0 to 100 (default=1)
|
||||||
None - Do not export asset list
|
Example: "--fbx-scale-factor 50"
|
||||||
Example: "--export-asset-list xml"
|
|
||||||
|
|
||||||
|
--fbx-bone-size <value> Specify the FBX Bone Size
|
||||||
|
<Value: integer number from 0 to 100 (default=10)
|
||||||
|
Example: "--fbx-bone-size 10"
|
||||||
|
|
||||||
|
Filter Options:
|
||||||
--filter-by-name <text> Specify the name by which assets should be filtered
|
--filter-by-name <text> Specify the name by which assets should be filtered
|
||||||
*To specify multiple names write them separated by ',' or ';' without spaces
|
*To specify multiple names write them separated by ',' or ';' without spaces
|
||||||
Example: "--filter-by-name char" or "--filter-by-name char,bg"
|
Example: "--filter-by-name char" or "--filter-by-name char,bg"
|
||||||
@@ -90,8 +96,21 @@ Advanced Options:
|
|||||||
*To specify multiple values write them separated by ',' or ';' without spaces
|
*To specify multiple values write them separated by ',' or ';' without spaces
|
||||||
Example: "--filter-by-text portrait" or "--filter-by-text portrait,art"
|
Example: "--filter-by-text portrait" or "--filter-by-text portrait,art"
|
||||||
|
|
||||||
|
|
||||||
|
Advanced Options:
|
||||||
|
--export-asset-list <value> Specify the format in which you want to export asset list
|
||||||
|
<Value: none(default) | xml>
|
||||||
|
None - Do not export asset list
|
||||||
|
Example: "--export-asset-list xml"
|
||||||
|
|
||||||
--assembly-folder <path> Specify the path to the assembly folder
|
--assembly-folder <path> Specify the path to the assembly folder
|
||||||
--unity-version <text> Specify Unity version. Example: "--unity-version 2017.4.39f1"
|
|
||||||
|
--unity-version <text> Specify Unity version
|
||||||
|
Example: "--unity-version 2017.4.39f1"
|
||||||
|
|
||||||
--not-restore-extension (Flag) If specified, AssetStudio will not try to use/restore original TextAsset
|
--not-restore-extension (Flag) If specified, AssetStudio will not try to use/restore original TextAsset
|
||||||
extension name, and will just export all TextAssets with the ".txt" extension
|
extension name, and will just export all TextAssets with the ".txt" extension
|
||||||
|
|
||||||
|
--load-all (Flag) If specified, AssetStudio will load assets of all types
|
||||||
|
(Only for Dump, Info and ExportRaw modes)
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -11,40 +11,33 @@ using Ansi = AssetStudioCLI.CLIAnsiColors;
|
|||||||
|
|
||||||
namespace AssetStudioCLI
|
namespace AssetStudioCLI
|
||||||
{
|
{
|
||||||
internal class Studio
|
internal static class Studio
|
||||||
{
|
{
|
||||||
public AssetsManager assetsManager = new AssetsManager();
|
public static AssetsManager assetsManager = new AssetsManager();
|
||||||
public List<AssetItem> parsedAssetsList = new List<AssetItem>();
|
public static List<AssetItem> parsedAssetsList = new List<AssetItem>();
|
||||||
|
public static List<BaseNode> gameObjectTree = new List<BaseNode>();
|
||||||
|
public static AssemblyLoader assemblyLoader = new AssemblyLoader();
|
||||||
private static Dictionary<AssetStudio.Object, string> containers = new Dictionary<AssetStudio.Object, string>();
|
private static Dictionary<AssetStudio.Object, string> containers = new Dictionary<AssetStudio.Object, string>();
|
||||||
private static AssemblyLoader assemblyLoader = new AssemblyLoader();
|
|
||||||
private readonly CLIOptions options;
|
|
||||||
|
|
||||||
public Studio(CLIOptions cliOptions)
|
static Studio()
|
||||||
{
|
{
|
||||||
Progress.Default = new Progress<int>(ShowCurProgressValue);
|
Progress.Default = new Progress<int>(ShowCurProgressValue);
|
||||||
options = cliOptions;
|
|
||||||
if (options.o_assemblyPath.Value != "")
|
|
||||||
{
|
|
||||||
assemblyLoader.Load(options.o_assemblyPath.Value);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
assemblyLoader.Loaded = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ShowCurProgressValue(int value)
|
private static void ShowCurProgressValue(int value)
|
||||||
{
|
{
|
||||||
Console.Write($"[{value:000}%]\r");
|
Console.Write($"[{value:000}%]\r");
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool LoadAssets()
|
public static bool LoadAssets()
|
||||||
{
|
{
|
||||||
var isLoaded = false;
|
var isLoaded = false;
|
||||||
assetsManager.SpecifyUnityVersion = options.o_unityVersion.Value;
|
assetsManager.SpecifyUnityVersion = CLIOptions.o_unityVersion.Value;
|
||||||
assetsManager.SetAssetFilter(options.o_exportAssetTypes.Value);
|
if (!CLIOptions.f_loadAllAssets.Value)
|
||||||
|
{
|
||||||
assetsManager.LoadFilesAndFolders(options.inputPath);
|
assetsManager.SetAssetFilter(CLIOptions.o_exportAssetTypes.Value);
|
||||||
|
}
|
||||||
|
assetsManager.LoadFilesAndFolders(CLIOptions.inputPath);
|
||||||
if (assetsManager.assetsFileList.Count == 0)
|
if (assetsManager.assetsFileList.Count == 0)
|
||||||
{
|
{
|
||||||
Logger.Warning("No Unity file can be loaded.");
|
Logger.Warning("No Unity file can be loaded.");
|
||||||
@@ -57,12 +50,13 @@ namespace AssetStudioCLI
|
|||||||
return isLoaded;
|
return isLoaded;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ParseAssets()
|
public static void ParseAssets()
|
||||||
{
|
{
|
||||||
Logger.Info("Parse assets...");
|
Logger.Info("Parse assets...");
|
||||||
|
|
||||||
var fileAssetsList = new List<AssetItem>();
|
var fileAssetsList = new List<AssetItem>();
|
||||||
var objectCount = assetsManager.assetsFileList.Sum(x => x.Objects.Count);
|
var objectCount = assetsManager.assetsFileList.Sum(x => x.Objects.Count);
|
||||||
|
var objectAssetItemDic = new Dictionary<AssetStudio.Object, AssetItem>(objectCount);
|
||||||
|
|
||||||
Progress.Reset();
|
Progress.Reset();
|
||||||
var i = 0;
|
var i = 0;
|
||||||
@@ -71,6 +65,7 @@ namespace AssetStudioCLI
|
|||||||
foreach (var asset in assetsFile.Objects)
|
foreach (var asset in assetsFile.Objects)
|
||||||
{
|
{
|
||||||
var assetItem = new AssetItem(asset);
|
var assetItem = new AssetItem(asset);
|
||||||
|
objectAssetItemDic.Add(asset, assetItem);
|
||||||
assetItem.UniqueID = "_#" + i;
|
assetItem.UniqueID = "_#" + i;
|
||||||
var isExportable = false;
|
var isExportable = false;
|
||||||
switch (asset)
|
switch (asset)
|
||||||
@@ -90,6 +85,7 @@ namespace AssetStudioCLI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
assetItem.Text = m_AssetBundle.m_Name;
|
||||||
break;
|
break;
|
||||||
case ResourceManager m_ResourceManager:
|
case ResourceManager m_ResourceManager:
|
||||||
foreach (var m_Container in m_ResourceManager.m_Container)
|
foreach (var m_Container in m_ResourceManager.m_Container)
|
||||||
@@ -115,13 +111,6 @@ namespace AssetStudioCLI
|
|||||||
assetItem.FullSize = asset.byteSize + m_VideoClip.m_ExternalResources.m_Size;
|
assetItem.FullSize = asset.byteSize + m_VideoClip.m_ExternalResources.m_Size;
|
||||||
assetItem.Text = m_VideoClip.m_Name;
|
assetItem.Text = m_VideoClip.m_Name;
|
||||||
break;
|
break;
|
||||||
case Mesh _:
|
|
||||||
case MovieTexture _:
|
|
||||||
case TextAsset _:
|
|
||||||
case Font _:
|
|
||||||
case Sprite _:
|
|
||||||
assetItem.Text = ((NamedObject)asset).m_Name;
|
|
||||||
break;
|
|
||||||
case Shader m_Shader:
|
case Shader m_Shader:
|
||||||
assetItem.Text = m_Shader.m_ParsedForm?.m_Name ?? m_Shader.m_Name;
|
assetItem.Text = m_Shader.m_ParsedForm?.m_Name ?? m_Shader.m_Name;
|
||||||
break;
|
break;
|
||||||
@@ -135,14 +124,26 @@ namespace AssetStudioCLI
|
|||||||
assetItem.Text = m_MonoBehaviour.m_Name;
|
assetItem.Text = m_MonoBehaviour.m_Name;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case GameObject m_GameObject:
|
||||||
|
assetItem.Text = m_GameObject.m_Name;
|
||||||
|
break;
|
||||||
|
case Animator m_Animator:
|
||||||
|
if (m_Animator.m_GameObject.TryGet(out var gameObject))
|
||||||
|
{
|
||||||
|
assetItem.Text = gameObject.m_Name;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NamedObject m_NamedObject:
|
||||||
|
assetItem.Text = m_NamedObject.m_Name;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (assetItem.Text == "")
|
if (string.IsNullOrEmpty(assetItem.Text))
|
||||||
{
|
{
|
||||||
assetItem.Text = assetItem.TypeString + assetItem.UniqueID;
|
assetItem.Text = assetItem.TypeString + assetItem.UniqueID;
|
||||||
}
|
}
|
||||||
|
|
||||||
isExportable = options.o_exportAssetTypes.Value.Contains(asset.type);
|
isExportable = CLIOptions.o_exportAssetTypes.Value.Contains(asset.type);
|
||||||
if (isExportable)
|
if (isExportable || (CLIOptions.f_loadAllAssets.Value && CLIOptions.o_exportAssetTypes.Value == CLIOptions.o_exportAssetTypes.DefaultValue))
|
||||||
{
|
{
|
||||||
fileAssetsList.Add(assetItem);
|
fileAssetsList.Add(assetItem);
|
||||||
}
|
}
|
||||||
@@ -158,14 +159,119 @@ namespace AssetStudioCLI
|
|||||||
}
|
}
|
||||||
parsedAssetsList.AddRange(fileAssetsList);
|
parsedAssetsList.AddRange(fileAssetsList);
|
||||||
fileAssetsList.Clear();
|
fileAssetsList.Clear();
|
||||||
if (options.o_workMode.Value != WorkMode.ExportLive2D)
|
if (CLIOptions.o_workMode.Value != WorkMode.ExportLive2D)
|
||||||
{
|
{
|
||||||
containers.Clear();
|
containers.Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (CLIOptions.o_workMode.Value == WorkMode.SplitObjects)
|
||||||
|
{
|
||||||
|
BuildTreeStructure(objectAssetItemDic);
|
||||||
|
}
|
||||||
|
|
||||||
|
var log = $"Finished loading {assetsManager.assetsFileList.Count} files with {parsedAssetsList.Count} exportable assets";
|
||||||
|
var unityVer = assetsManager.assetsFileList[0].version;
|
||||||
|
long m_ObjectsCount;
|
||||||
|
if (unityVer[0] > 2020)
|
||||||
|
{
|
||||||
|
m_ObjectsCount = assetsManager.assetsFileList.Sum(x => x.m_Objects.LongCount(y =>
|
||||||
|
y.classID != (int)ClassIDType.Shader
|
||||||
|
&& CLIOptions.o_exportAssetTypes.Value.Any(k => (int)k == y.classID))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_ObjectsCount = assetsManager.assetsFileList.Sum(x => x.m_Objects.LongCount(y => CLIOptions.o_exportAssetTypes.Value.Any(k => (int)k == y.classID)));
|
||||||
|
}
|
||||||
|
var objectsCount = assetsManager.assetsFileList.Sum(x => x.Objects.LongCount(y => CLIOptions.o_exportAssetTypes.Value.Any(k => k == y.type)));
|
||||||
|
if (m_ObjectsCount != objectsCount)
|
||||||
|
{
|
||||||
|
log += $" and {m_ObjectsCount - objectsCount} assets failed to read";
|
||||||
|
}
|
||||||
|
Logger.Info(log);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ShowExportableAssetsInfo()
|
public static void BuildTreeStructure(Dictionary<AssetStudio.Object, AssetItem> objectAssetItemDic)
|
||||||
|
{
|
||||||
|
Logger.Info("Building tree structure...");
|
||||||
|
|
||||||
|
var treeNodeDictionary = new Dictionary<GameObject, GameObjectNode>();
|
||||||
|
var assetsFileCount = assetsManager.assetsFileList.Count;
|
||||||
|
int j = 0;
|
||||||
|
Progress.Reset();
|
||||||
|
foreach (var assetsFile in assetsManager.assetsFileList)
|
||||||
|
{
|
||||||
|
var fileNode = new BaseNode(); //RootNode
|
||||||
|
|
||||||
|
foreach (var obj in assetsFile.Objects)
|
||||||
|
{
|
||||||
|
if (obj is GameObject m_GameObject)
|
||||||
|
{
|
||||||
|
if (!treeNodeDictionary.TryGetValue(m_GameObject, out var currentNode))
|
||||||
|
{
|
||||||
|
currentNode = new GameObjectNode(m_GameObject);
|
||||||
|
treeNodeDictionary.Add(m_GameObject, currentNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var pptr in m_GameObject.m_Components)
|
||||||
|
{
|
||||||
|
if (pptr.TryGet(out var m_Component))
|
||||||
|
{
|
||||||
|
objectAssetItemDic[m_Component].Node = currentNode;
|
||||||
|
if (m_Component is MeshFilter m_MeshFilter)
|
||||||
|
{
|
||||||
|
if (m_MeshFilter.m_Mesh.TryGet(out var m_Mesh))
|
||||||
|
{
|
||||||
|
objectAssetItemDic[m_Mesh].Node = currentNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (m_Component is SkinnedMeshRenderer m_SkinnedMeshRenderer)
|
||||||
|
{
|
||||||
|
if (m_SkinnedMeshRenderer.m_Mesh.TryGet(out var m_Mesh))
|
||||||
|
{
|
||||||
|
objectAssetItemDic[m_Mesh].Node = currentNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var parentNode = fileNode;
|
||||||
|
|
||||||
|
if (m_GameObject.m_Transform != null)
|
||||||
|
{
|
||||||
|
if (m_GameObject.m_Transform.m_Father.TryGet(out var m_Father))
|
||||||
|
{
|
||||||
|
if (m_Father.m_GameObject.TryGet(out var parentGameObject))
|
||||||
|
{
|
||||||
|
if (!treeNodeDictionary.TryGetValue(parentGameObject, out var parentGameObjectNode))
|
||||||
|
{
|
||||||
|
parentGameObjectNode = new GameObjectNode(parentGameObject);
|
||||||
|
treeNodeDictionary.Add(parentGameObject, parentGameObjectNode);
|
||||||
|
}
|
||||||
|
parentNode = parentGameObjectNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parentNode.nodes.Add(currentNode);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fileNode.nodes.Count > 0)
|
||||||
|
{
|
||||||
|
gameObjectTree.Add(fileNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
Progress.Report(++j, assetsFileCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
treeNodeDictionary.Clear();
|
||||||
|
objectAssetItemDic.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ShowExportableAssetsInfo()
|
||||||
{
|
{
|
||||||
var exportableAssetsCountDict = new Dictionary<ClassIDType, int>();
|
var exportableAssetsCountDict = new Dictionary<ClassIDType, int>();
|
||||||
string info = "";
|
string info = "";
|
||||||
@@ -198,7 +304,7 @@ namespace AssetStudioCLI
|
|||||||
info += "No exportable assets found.";
|
info += "No exportable assets found.";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.o_logLevel.Value > LoggerEvent.Info)
|
if (CLIOptions.o_logLevel.Value > LoggerEvent.Info)
|
||||||
{
|
{
|
||||||
Console.WriteLine(info);
|
Console.WriteLine(info);
|
||||||
}
|
}
|
||||||
@@ -208,53 +314,66 @@ namespace AssetStudioCLI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void FilterAssets()
|
public static void Filter()
|
||||||
|
{
|
||||||
|
switch (CLIOptions.o_workMode.Value)
|
||||||
|
{
|
||||||
|
case WorkMode.ExportLive2D:
|
||||||
|
case WorkMode.SplitObjects:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
FilterAssets();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void FilterAssets()
|
||||||
{
|
{
|
||||||
var assetsCount = parsedAssetsList.Count;
|
var assetsCount = parsedAssetsList.Count;
|
||||||
var filteredAssets = new List<AssetItem>();
|
var filteredAssets = new List<AssetItem>();
|
||||||
|
|
||||||
switch(options.filterBy)
|
switch(CLIOptions.filterBy)
|
||||||
{
|
{
|
||||||
case FilterBy.Name:
|
case FilterBy.Name:
|
||||||
filteredAssets = parsedAssetsList.FindAll(x => options.o_filterByName.Value.Any(y => x.Text.ToString().IndexOf(y, StringComparison.OrdinalIgnoreCase) >= 0));
|
filteredAssets = parsedAssetsList.FindAll(x => CLIOptions.o_filterByName.Value.Any(y => x.Text.IndexOf(y, StringComparison.OrdinalIgnoreCase) >= 0));
|
||||||
Logger.Info(
|
Logger.Info(
|
||||||
$"Found [{filteredAssets.Count}/{assetsCount}] asset(s) " +
|
$"Found [{filteredAssets.Count}/{assetsCount}] asset(s) " +
|
||||||
$"that contain {$"\"{string.Join("\", \"", options.o_filterByName.Value)}\"".Color(Ansi.BrightYellow)} in their Names."
|
$"that contain {$"\"{string.Join("\", \"", CLIOptions.o_filterByName.Value)}\"".Color(Ansi.BrightYellow)} in their Names."
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case FilterBy.Container:
|
case FilterBy.Container:
|
||||||
filteredAssets = parsedAssetsList.FindAll(x => options.o_filterByContainer.Value.Any(y => x.Container.ToString().IndexOf(y, StringComparison.OrdinalIgnoreCase) >= 0));
|
filteredAssets = parsedAssetsList.FindAll(x => CLIOptions.o_filterByContainer.Value.Any(y => x.Container.IndexOf(y, StringComparison.OrdinalIgnoreCase) >= 0));
|
||||||
Logger.Info(
|
Logger.Info(
|
||||||
$"Found [{filteredAssets.Count}/{assetsCount}] asset(s) " +
|
$"Found [{filteredAssets.Count}/{assetsCount}] asset(s) " +
|
||||||
$"that contain {$"\"{string.Join("\", \"", options.o_filterByContainer.Value)}\"".Color(Ansi.BrightYellow)} in their Containers."
|
$"that contain {$"\"{string.Join("\", \"", CLIOptions.o_filterByContainer.Value)}\"".Color(Ansi.BrightYellow)} in their Containers."
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case FilterBy.PathID:
|
case FilterBy.PathID:
|
||||||
filteredAssets = parsedAssetsList.FindAll(x => options.o_filterByPathID.Value.Any(y => x.m_PathID.ToString().IndexOf(y, StringComparison.OrdinalIgnoreCase) >= 0));
|
filteredAssets = parsedAssetsList.FindAll(x => CLIOptions.o_filterByPathID.Value.Any(y => x.m_PathID.ToString().IndexOf(y, StringComparison.OrdinalIgnoreCase) >= 0));
|
||||||
Logger.Info(
|
Logger.Info(
|
||||||
$"Found [{filteredAssets.Count}/{assetsCount}] asset(s) " +
|
$"Found [{filteredAssets.Count}/{assetsCount}] asset(s) " +
|
||||||
$"that contain {$"\"{string.Join("\", \"", options.o_filterByPathID.Value)}\"".Color(Ansi.BrightYellow)} in their PathIDs."
|
$"that contain {$"\"{string.Join("\", \"", CLIOptions.o_filterByPathID.Value)}\"".Color(Ansi.BrightYellow)} in their PathIDs."
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case FilterBy.NameOrContainer:
|
case FilterBy.NameOrContainer:
|
||||||
filteredAssets = parsedAssetsList.FindAll(x =>
|
filteredAssets = parsedAssetsList.FindAll(x =>
|
||||||
options.o_filterByText.Value.Any(y => x.Text.ToString().IndexOf(y, StringComparison.OrdinalIgnoreCase) >= 0) ||
|
CLIOptions.o_filterByText.Value.Any(y => x.Text.IndexOf(y, StringComparison.OrdinalIgnoreCase) >= 0) ||
|
||||||
options.o_filterByText.Value.Any(y => x.Container.ToString().IndexOf(y, StringComparison.OrdinalIgnoreCase) >= 0)
|
CLIOptions.o_filterByText.Value.Any(y => x.Container.IndexOf(y, StringComparison.OrdinalIgnoreCase) >= 0)
|
||||||
);
|
);
|
||||||
Logger.Info(
|
Logger.Info(
|
||||||
$"Found [{filteredAssets.Count}/{assetsCount}] asset(s) " +
|
$"Found [{filteredAssets.Count}/{assetsCount}] asset(s) " +
|
||||||
$"that contain {$"\"{string.Join("\", \"", options.o_filterByText.Value)}\"".Color(Ansi.BrightYellow)} in their Names or Contaniers."
|
$"that contain {$"\"{string.Join("\", \"", CLIOptions.o_filterByText.Value)}\"".Color(Ansi.BrightYellow)} in their Names or Contaniers."
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case FilterBy.NameAndContainer:
|
case FilterBy.NameAndContainer:
|
||||||
filteredAssets = parsedAssetsList.FindAll(x =>
|
filteredAssets = parsedAssetsList.FindAll(x =>
|
||||||
options.o_filterByName.Value.Any(y => x.Text.ToString().IndexOf(y, StringComparison.OrdinalIgnoreCase) >= 0) &&
|
CLIOptions.o_filterByName.Value.Any(y => x.Text.IndexOf(y, StringComparison.OrdinalIgnoreCase) >= 0) &&
|
||||||
options.o_filterByContainer.Value.Any(y => x.Container.ToString().IndexOf(y, StringComparison.OrdinalIgnoreCase) >= 0)
|
CLIOptions.o_filterByContainer.Value.Any(y => x.Container.IndexOf(y, StringComparison.OrdinalIgnoreCase) >= 0)
|
||||||
);
|
);
|
||||||
Logger.Info(
|
Logger.Info(
|
||||||
$"Found [{filteredAssets.Count}/{assetsCount}] asset(s) " +
|
$"Found [{filteredAssets.Count}/{assetsCount}] asset(s) " +
|
||||||
$"that contain {$"\"{string.Join("\", \"", options.o_filterByContainer.Value)}\"".Color(Ansi.BrightYellow)} in their Containers " +
|
$"that contain {$"\"{string.Join("\", \"", CLIOptions.o_filterByContainer.Value)}\"".Color(Ansi.BrightYellow)} in their Containers " +
|
||||||
$"and {$"\"{string.Join("\", \"", options.o_filterByName.Value)}\"".Color(Ansi.BrightYellow)} in their Names."
|
$"and {$"\"{string.Join("\", \"", CLIOptions.o_filterByName.Value)}\"".Color(Ansi.BrightYellow)} in their Names."
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -262,13 +381,13 @@ namespace AssetStudioCLI
|
|||||||
parsedAssetsList = filteredAssets;
|
parsedAssetsList = filteredAssets;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ExportAssets()
|
public static void ExportAssets()
|
||||||
{
|
{
|
||||||
var savePath = options.o_outputFolder.Value;
|
var savePath = CLIOptions.o_outputFolder.Value;
|
||||||
var toExportCount = parsedAssetsList.Count;
|
var toExportCount = parsedAssetsList.Count;
|
||||||
var exportedCount = 0;
|
var exportedCount = 0;
|
||||||
|
|
||||||
var groupOption = options.o_groupAssetsBy.Value;
|
var groupOption = CLIOptions.o_groupAssetsBy.Value;
|
||||||
foreach (var asset in parsedAssetsList)
|
foreach (var asset in parsedAssetsList)
|
||||||
{
|
{
|
||||||
string exportPath;
|
string exportPath;
|
||||||
@@ -310,25 +429,25 @@ namespace AssetStudioCLI
|
|||||||
exportPath += Path.DirectorySeparatorChar;
|
exportPath += Path.DirectorySeparatorChar;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
switch (options.o_workMode.Value)
|
switch (CLIOptions.o_workMode.Value)
|
||||||
{
|
{
|
||||||
case WorkMode.ExportRaw:
|
case WorkMode.ExportRaw:
|
||||||
Logger.Debug($"{options.o_workMode}: {asset.Type} : {asset.Container} : {asset.Text}");
|
Logger.Debug($"{CLIOptions.o_workMode}: {asset.Type} : {asset.Container} : {asset.Text}");
|
||||||
if (ExportRawFile(asset, exportPath))
|
if (ExportRawFile(asset, exportPath))
|
||||||
{
|
{
|
||||||
exportedCount++;
|
exportedCount++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case WorkMode.Dump:
|
case WorkMode.Dump:
|
||||||
Logger.Debug($"{options.o_workMode}: {asset.Type} : {asset.Container} : {asset.Text}");
|
Logger.Debug($"{CLIOptions.o_workMode}: {asset.Type} : {asset.Container} : {asset.Text}");
|
||||||
if (ExportDumpFile(asset, exportPath, assemblyLoader))
|
if (ExportDumpFile(asset, exportPath))
|
||||||
{
|
{
|
||||||
exportedCount++;
|
exportedCount++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case WorkMode.Export:
|
case WorkMode.Export:
|
||||||
Logger.Debug($"{options.o_workMode}: {asset.Type} : {asset.Container} : {asset.Text}");
|
Logger.Debug($"{CLIOptions.o_workMode}: {asset.Type} : {asset.Container} : {asset.Text}");
|
||||||
if (ExportConvertFile(asset, exportPath, options, assemblyLoader))
|
if (ExportConvertFile(asset, exportPath))
|
||||||
{
|
{
|
||||||
exportedCount++;
|
exportedCount++;
|
||||||
}
|
}
|
||||||
@@ -349,11 +468,11 @@ namespace AssetStudioCLI
|
|||||||
}
|
}
|
||||||
else if (toExportCount > exportedCount)
|
else if (toExportCount > exportedCount)
|
||||||
{
|
{
|
||||||
Logger.Default.Log(LoggerEvent.Info, $"Finished exporting {exportedCount} asset(s) to \"{options.o_outputFolder.Value.Color(Ansi.BrightYellow)}\".", ignoreLevel: true);
|
Logger.Default.Log(LoggerEvent.Info, $"Finished exporting {exportedCount} asset(s) to \"{CLIOptions.o_outputFolder.Value.Color(Ansi.BrightYellow)}\".", ignoreLevel: true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Logger.Default.Log(LoggerEvent.Info, $"Finished exporting {exportedCount} asset(s) to \"{options.o_outputFolder.Value.Color(Ansi.BrightGreen)}\".", ignoreLevel: true);
|
Logger.Default.Log(LoggerEvent.Info, $"Finished exporting {exportedCount} asset(s) to \"{CLIOptions.o_outputFolder.Value.Color(Ansi.BrightGreen)}\".", ignoreLevel: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (toExportCount > exportedCount)
|
if (toExportCount > exportedCount)
|
||||||
@@ -362,11 +481,11 @@ namespace AssetStudioCLI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ExportAssetList()
|
public static void ExportAssetList()
|
||||||
{
|
{
|
||||||
var savePath = options.o_outputFolder.Value;
|
var savePath = CLIOptions.o_outputFolder.Value;
|
||||||
|
|
||||||
switch (options.o_exportAssetList.Value)
|
switch (CLIOptions.o_exportAssetList.Value)
|
||||||
{
|
{
|
||||||
case ExportListType.XML:
|
case ExportListType.XML:
|
||||||
var filename = Path.Combine(savePath, "assets.xml");
|
var filename = Path.Combine(savePath, "assets.xml");
|
||||||
@@ -393,9 +512,104 @@ namespace AssetStudioCLI
|
|||||||
Logger.Info($"Finished exporting asset list with {parsedAssetsList.Count} items.");
|
Logger.Info($"Finished exporting asset list with {parsedAssetsList.Count} items.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ExportLive2D()
|
public static void ExportSplitObjects()
|
||||||
{
|
{
|
||||||
var baseDestPath = Path.Combine(options.o_outputFolder.Value, "Live2DOutput");
|
var savePath = CLIOptions.o_outputFolder.Value;
|
||||||
|
var searchList = CLIOptions.o_filterByName.Value;
|
||||||
|
var isFiltered = CLIOptions.filterBy == FilterBy.Name;
|
||||||
|
|
||||||
|
var exportableObjects = new List<GameObjectNode>();
|
||||||
|
var exportedCount = 0;
|
||||||
|
var k = 0;
|
||||||
|
|
||||||
|
Logger.Info($"Searching for objects to export..");
|
||||||
|
Progress.Reset();
|
||||||
|
var count = gameObjectTree.Sum(x => x.nodes.Count);
|
||||||
|
foreach (var node in gameObjectTree)
|
||||||
|
{
|
||||||
|
foreach (GameObjectNode j in node.nodes)
|
||||||
|
{
|
||||||
|
if (isFiltered)
|
||||||
|
{
|
||||||
|
if (!searchList.Any(searchText => j.gameObject.m_Name.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) >= 0))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
var gameObjects = new List<GameObject>();
|
||||||
|
CollectNode(j, gameObjects);
|
||||||
|
|
||||||
|
if (gameObjects.All(x => x.m_SkinnedMeshRenderer == null && x.m_MeshFilter == null))
|
||||||
|
{
|
||||||
|
Progress.Report(++k, count);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
exportableObjects.Add(j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gameObjectTree.Clear();
|
||||||
|
var exportableCount = exportableObjects.Count;
|
||||||
|
var log = $"Found {exportableCount} exportable object(s) ";
|
||||||
|
if (isFiltered)
|
||||||
|
{
|
||||||
|
log += $"that contain {$"\"{string.Join("\", \"", CLIOptions.o_filterByName.Value)}\"".Color(Ansi.BrightYellow)} in their Names";
|
||||||
|
}
|
||||||
|
Logger.Info(log);
|
||||||
|
if (exportableCount > 0)
|
||||||
|
{
|
||||||
|
Progress.Reset();
|
||||||
|
k = 0;
|
||||||
|
|
||||||
|
foreach (var gameObjectNode in exportableObjects)
|
||||||
|
{
|
||||||
|
var gameObject = gameObjectNode.gameObject;
|
||||||
|
var filename = FixFileName(gameObject.m_Name);
|
||||||
|
var targetPath = $"{savePath}{filename}{Path.DirectorySeparatorChar}";
|
||||||
|
//重名文件处理
|
||||||
|
for (int i = 1; ; i++)
|
||||||
|
{
|
||||||
|
if (Directory.Exists(targetPath))
|
||||||
|
{
|
||||||
|
targetPath = $"{savePath}{filename} ({i}){Path.DirectorySeparatorChar}";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Directory.CreateDirectory(targetPath);
|
||||||
|
//导出FBX
|
||||||
|
Logger.Info($"Exporting {filename}.fbx");
|
||||||
|
Progress.Report(k, exportableCount);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ExportGameObject(gameObject, targetPath);
|
||||||
|
Logger.Debug($"{gameObject.type} \"{filename}\" saved to \"{targetPath}\"");
|
||||||
|
exportedCount++;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logger.Error($"Export GameObject:{gameObject.m_Name} error", ex);
|
||||||
|
}
|
||||||
|
k++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var status = exportedCount > 0
|
||||||
|
? $"Finished exporting [{exportedCount}/{exportableCount}] object(s) to \"{CLIOptions.o_outputFolder.Value.Color(Ansi.BrightCyan)}\""
|
||||||
|
: "Nothing exported";
|
||||||
|
Logger.Default.Log(LoggerEvent.Info, status, ignoreLevel: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CollectNode(GameObjectNode node, List<GameObject> gameObjects)
|
||||||
|
{
|
||||||
|
gameObjects.Add(node.gameObject);
|
||||||
|
foreach (GameObjectNode i in node.nodes)
|
||||||
|
{
|
||||||
|
CollectNode(i, gameObjects);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ExportLive2D()
|
||||||
|
{
|
||||||
|
var baseDestPath = Path.Combine(CLIOptions.o_outputFolder.Value, "Live2DOutput");
|
||||||
var useFullContainerPath = false;
|
var useFullContainerPath = false;
|
||||||
|
|
||||||
Progress.Reset();
|
Progress.Reset();
|
||||||
@@ -461,7 +675,7 @@ namespace AssetStudioCLI
|
|||||||
Progress.Report(modelCounter, (int)totalModelCount);
|
Progress.Report(modelCounter, (int)totalModelCount);
|
||||||
}
|
}
|
||||||
var status = modelCounter > 0 ?
|
var status = modelCounter > 0 ?
|
||||||
$"Finished exporting [{modelCounter}/{totalModelCount}] Live2D model(s) to \"{options.o_outputFolder.Value.Color(Ansi.BrightCyan)}\"" :
|
$"Finished exporting [{modelCounter}/{totalModelCount}] Live2D model(s) to \"{CLIOptions.o_outputFolder.Value.Color(Ansi.BrightCyan)}\"" :
|
||||||
"Nothing exported.";
|
"Nothing exported.";
|
||||||
Logger.Default.Log(LoggerEvent.Info, status, ignoreLevel: true);
|
Logger.Default.Log(LoggerEvent.Info, status, ignoreLevel: true);
|
||||||
}
|
}
|
||||||
|
|||||||
22
AssetStudioFBXNative/CMakeLists.txt
Normal file
22
AssetStudioFBXNative/CMakeLists.txt
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
# Set the minimum version of CMake that can be used
|
||||||
|
cmake_minimum_required (VERSION 3.8)
|
||||||
|
|
||||||
|
# Set the project name
|
||||||
|
project("AssetStudioFBXNative")
|
||||||
|
|
||||||
|
# Set the C++ standard to C++ 14
|
||||||
|
set(CMAKE_CXX_STANDARD 14)
|
||||||
|
|
||||||
|
# Generate the shared library from the library sources
|
||||||
|
add_library(AssetStudioFBXNative SHARED
|
||||||
|
asfbx_skin_context.cpp
|
||||||
|
asfbx_morph_context.cpp
|
||||||
|
api.cpp
|
||||||
|
utils.cpp
|
||||||
|
asfbx_context.cpp
|
||||||
|
asfbx_anim_context.cpp)
|
||||||
|
|
||||||
|
# Add the given directories to those the compiler uses to search for include files
|
||||||
|
target_include_directories(AssetStudioFBXNative PRIVATE .)
|
||||||
|
|
||||||
|
target_link_libraries(AssetStudioFBXNative PRIVATE fbxsdk xml2)
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>net472;net6.0;net6.0-windows;net7.0;net7.0-windows</TargetFrameworks>
|
<TargetFrameworks>net472;net6.0;net6.0-windows;net7.0;net7.0-windows</TargetFrameworks>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<Version>0.17.1.0</Version>
|
<Version>0.17.3.0</Version>
|
||||||
<Copyright>Copyright © Perfare 2018-2022; Copyright © hozuki 2020</Copyright>
|
<Copyright>Copyright © Perfare 2018-2022; Copyright © hozuki 2020</Copyright>
|
||||||
<DebugType>embedded</DebugType>
|
<DebugType>embedded</DebugType>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|||||||
@@ -1,14 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.ComponentModel;
|
|
||||||
using System.Data;
|
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Drawing;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection.Emit;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
|
|
||||||
namespace AssetStudioGUI
|
namespace AssetStudioGUI
|
||||||
|
|||||||
@@ -7,13 +7,14 @@
|
|||||||
<ApplicationIcon>Resources\as.ico</ApplicationIcon>
|
<ApplicationIcon>Resources\as.ico</ApplicationIcon>
|
||||||
<AssemblyTitle>AssetStudioMod by aelurum</AssemblyTitle>
|
<AssemblyTitle>AssetStudioMod by aelurum</AssemblyTitle>
|
||||||
<AssemblyName>AssetStudioModGUI</AssemblyName>
|
<AssemblyName>AssetStudioModGUI</AssemblyName>
|
||||||
<Version>0.17.1.0</Version>
|
<Version>0.17.3.0</Version>
|
||||||
<Copyright>Copyright © Perfare 2018-2022; Copyright © aelurum 2021-2023</Copyright>
|
<Copyright>Copyright © Perfare 2018-2022; Copyright © aelurum 2021-2023</Copyright>
|
||||||
<DebugType>embedded</DebugType>
|
<DebugType>embedded</DebugType>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition=" '$(TargetFramework)' == 'net472' ">
|
<PropertyGroup Condition=" '$(TargetFramework)' == 'net472' ">
|
||||||
<IsPublishable>false</IsPublishable>
|
<IsPublishable>false</IsPublishable>
|
||||||
|
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -52,8 +53,15 @@
|
|||||||
</ContentWithTargetPath>
|
</ContentWithTargetPath>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft-WindowsAPICodePack-Core-6.0" Version="1.1.6-preview.2.24bd88f" />
|
||||||
|
<PackageReference Include="Microsoft-WindowsAPICodePack-Shell-6.0" Version="1.1.6-preview.2.24bd88f" />
|
||||||
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup Condition=" '$(TargetFramework)' != 'net472' ">
|
<ItemGroup Condition=" '$(TargetFramework)' != 'net472' ">
|
||||||
<PackageReference Include="OpenTK" Version="4.7.7" />
|
<PackageReference Include="OpenTK.Graphics" Version="4.8.0" />
|
||||||
|
<PackageReference Include="OpenTK.Windowing.Desktop" Version="4.8.0" />
|
||||||
<Reference Include="OpenTK.WinForms">
|
<Reference Include="OpenTK.WinForms">
|
||||||
<HintPath>Libraries\OpenTK.WinForms.dll</HintPath>
|
<HintPath>Libraries\OpenTK.WinForms.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
@@ -64,12 +72,6 @@
|
|||||||
<PackageReference Include="OpenTK.GLControl" Version="3.3.3" />
|
<PackageReference Include="OpenTK.GLControl" Version="3.3.3" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="Microsoft-WindowsAPICodePack-Core-6.0" Version="1.1.6-preview.2.24bd88f" />
|
|
||||||
<PackageReference Include="Microsoft-WindowsAPICodePack-Shell-6.0" Version="1.1.6-preview.2.24bd88f" />
|
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<!-- Use local compiled win-x86 and win-x64 Texture2DDecoder libs, because libs from Kyaru.Texture2DDecoder.Windows were compiled with /MD flag -->
|
<!-- Use local compiled win-x86 and win-x64 Texture2DDecoder libs, because libs from Kyaru.Texture2DDecoder.Windows were compiled with /MD flag -->
|
||||||
|
|
||||||
<Target Name="CopyExtraFilesPortable" AfterTargets="AfterBuild" Condition=" '$(RuntimeIdentifier)' == '' OR '$(TargetFramework)' == 'net472' ">
|
<Target Name="CopyExtraFilesPortable" AfterTargets="AfterBuild" Condition=" '$(RuntimeIdentifier)' == '' OR '$(TargetFramework)' == 'net472' ">
|
||||||
|
|||||||
29
AssetStudioGUI/AssetStudioGUIForm.Designer.cs
generated
29
AssetStudioGUI/AssetStudioGUIForm.Designer.cs
generated
@@ -125,6 +125,8 @@
|
|||||||
this.statusStrip1 = new System.Windows.Forms.StatusStrip();
|
this.statusStrip1 = new System.Windows.Forms.StatusStrip();
|
||||||
this.toolStripStatusLabel1 = new System.Windows.Forms.ToolStripStatusLabel();
|
this.toolStripStatusLabel1 = new System.Windows.Forms.ToolStripStatusLabel();
|
||||||
this.contextMenuStrip2 = new System.Windows.Forms.ContextMenuStrip(this.components);
|
this.contextMenuStrip2 = new System.Windows.Forms.ContextMenuStrip(this.components);
|
||||||
|
this.showRelatedAssetsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
|
this.toolStripSeparator7 = new System.Windows.Forms.ToolStripSeparator();
|
||||||
this.selectAllToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
this.selectAllToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
this.clearSelectionToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
this.clearSelectionToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
this.toolStripSeparator5 = new System.Windows.Forms.ToolStripSeparator();
|
this.toolStripSeparator5 = new System.Windows.Forms.ToolStripSeparator();
|
||||||
@@ -526,7 +528,7 @@
|
|||||||
this.allToolStripMenuItem.CheckOnClick = true;
|
this.allToolStripMenuItem.CheckOnClick = true;
|
||||||
this.allToolStripMenuItem.CheckState = System.Windows.Forms.CheckState.Checked;
|
this.allToolStripMenuItem.CheckState = System.Windows.Forms.CheckState.Checked;
|
||||||
this.allToolStripMenuItem.Name = "allToolStripMenuItem";
|
this.allToolStripMenuItem.Name = "allToolStripMenuItem";
|
||||||
this.allToolStripMenuItem.Size = new System.Drawing.Size(180, 22);
|
this.allToolStripMenuItem.Size = new System.Drawing.Size(88, 22);
|
||||||
this.allToolStripMenuItem.Text = "All";
|
this.allToolStripMenuItem.Text = "All";
|
||||||
this.allToolStripMenuItem.Click += new System.EventHandler(this.typeToolStripMenuItem_Click);
|
this.allToolStripMenuItem.Click += new System.EventHandler(this.typeToolStripMenuItem_Click);
|
||||||
//
|
//
|
||||||
@@ -620,7 +622,7 @@
|
|||||||
this.sceneTreeView.Size = new System.Drawing.Size(472, 587);
|
this.sceneTreeView.Size = new System.Drawing.Size(472, 587);
|
||||||
this.sceneTreeView.TabIndex = 1;
|
this.sceneTreeView.TabIndex = 1;
|
||||||
this.sceneTreeView.AfterCheck += new System.Windows.Forms.TreeViewEventHandler(this.sceneTreeView_AfterCheck);
|
this.sceneTreeView.AfterCheck += new System.Windows.Forms.TreeViewEventHandler(this.sceneTreeView_AfterCheck);
|
||||||
this.sceneTreeView.MouseClick += new System.Windows.Forms.MouseEventHandler(this.sceneTreeView_MouseClick);
|
this.sceneTreeView.NodeMouseClick += new System.Windows.Forms.TreeNodeMouseClickEventHandler(this.sceneTreeView_NodeMouseClick);
|
||||||
//
|
//
|
||||||
// treeSearch
|
// treeSearch
|
||||||
//
|
//
|
||||||
@@ -629,7 +631,7 @@
|
|||||||
this.treeSearch.Location = new System.Drawing.Point(0, 0);
|
this.treeSearch.Location = new System.Drawing.Point(0, 0);
|
||||||
this.treeSearch.Name = "treeSearch";
|
this.treeSearch.Name = "treeSearch";
|
||||||
this.treeSearch.Size = new System.Drawing.Size(472, 20);
|
this.treeSearch.Size = new System.Drawing.Size(472, 20);
|
||||||
this.treeSearch.TabIndex = 0;
|
this.treeSearch.TabIndex = 2;
|
||||||
this.treeSearch.Text = " Search ";
|
this.treeSearch.Text = " Search ";
|
||||||
this.treeSearch.TextChanged += new System.EventHandler(this.treeSearch_TextChanged);
|
this.treeSearch.TextChanged += new System.EventHandler(this.treeSearch_TextChanged);
|
||||||
this.treeSearch.Enter += new System.EventHandler(this.treeSearch_Enter);
|
this.treeSearch.Enter += new System.EventHandler(this.treeSearch_Enter);
|
||||||
@@ -1115,13 +1117,28 @@
|
|||||||
// contextMenuStrip2
|
// contextMenuStrip2
|
||||||
//
|
//
|
||||||
this.contextMenuStrip2.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
this.contextMenuStrip2.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||||
|
this.showRelatedAssetsToolStripMenuItem,
|
||||||
|
this.toolStripSeparator7,
|
||||||
this.selectAllToolStripMenuItem,
|
this.selectAllToolStripMenuItem,
|
||||||
this.clearSelectionToolStripMenuItem,
|
this.clearSelectionToolStripMenuItem,
|
||||||
this.toolStripSeparator5,
|
this.toolStripSeparator5,
|
||||||
this.expandAllToolStripMenuItem,
|
this.expandAllToolStripMenuItem,
|
||||||
this.collapseAllToolStripMenuItem});
|
this.collapseAllToolStripMenuItem});
|
||||||
this.contextMenuStrip2.Name = "contextMenuStrip2";
|
this.contextMenuStrip2.Name = "contextMenuStrip2";
|
||||||
this.contextMenuStrip2.Size = new System.Drawing.Size(152, 98);
|
this.contextMenuStrip2.Size = new System.Drawing.Size(152, 126);
|
||||||
|
this.contextMenuStrip2.Opening += new System.ComponentModel.CancelEventHandler(this.contextMenuStrip2_Opening);
|
||||||
|
//
|
||||||
|
// showRelatedAssetsToolStripMenuItem
|
||||||
|
//
|
||||||
|
this.showRelatedAssetsToolStripMenuItem.Name = "showRelatedAssetsToolStripMenuItem";
|
||||||
|
this.showRelatedAssetsToolStripMenuItem.Size = new System.Drawing.Size(151, 22);
|
||||||
|
this.showRelatedAssetsToolStripMenuItem.Text = "Related assets";
|
||||||
|
this.showRelatedAssetsToolStripMenuItem.Click += new System.EventHandler(this.showRelatedAssetsToolStripMenuItem_Click);
|
||||||
|
//
|
||||||
|
// toolStripSeparator7
|
||||||
|
//
|
||||||
|
this.toolStripSeparator7.Name = "toolStripSeparator7";
|
||||||
|
this.toolStripSeparator7.Size = new System.Drawing.Size(148, 6);
|
||||||
//
|
//
|
||||||
// selectAllToolStripMenuItem
|
// selectAllToolStripMenuItem
|
||||||
//
|
//
|
||||||
@@ -1286,7 +1303,6 @@
|
|||||||
private System.Windows.Forms.TextBox treeSearch;
|
private System.Windows.Forms.TextBox treeSearch;
|
||||||
private System.Windows.Forms.ToolStripMenuItem loadFileToolStripMenuItem;
|
private System.Windows.Forms.ToolStripMenuItem loadFileToolStripMenuItem;
|
||||||
private System.Windows.Forms.ToolStripMenuItem loadFolderToolStripMenuItem;
|
private System.Windows.Forms.ToolStripMenuItem loadFolderToolStripMenuItem;
|
||||||
private System.Windows.Forms.ListView assetListView;
|
|
||||||
private System.Windows.Forms.ColumnHeader columnHeaderName;
|
private System.Windows.Forms.ColumnHeader columnHeaderName;
|
||||||
private System.Windows.Forms.ColumnHeader columnHeaderSize;
|
private System.Windows.Forms.ColumnHeader columnHeaderSize;
|
||||||
private System.Windows.Forms.ColumnHeader columnHeaderType;
|
private System.Windows.Forms.ColumnHeader columnHeaderType;
|
||||||
@@ -1386,6 +1402,9 @@
|
|||||||
private System.Windows.Forms.RichTextBox listSearch;
|
private System.Windows.Forms.RichTextBox listSearch;
|
||||||
private System.Windows.Forms.ToolStripSeparator toolStripSeparator6;
|
private System.Windows.Forms.ToolStripSeparator toolStripSeparator6;
|
||||||
private System.Windows.Forms.ToolStripMenuItem allLive2DModelsToolStripMenuItem;
|
private System.Windows.Forms.ToolStripMenuItem allLive2DModelsToolStripMenuItem;
|
||||||
|
private System.Windows.Forms.ToolStripMenuItem showRelatedAssetsToolStripMenuItem;
|
||||||
|
private System.Windows.Forms.ToolStripSeparator toolStripSeparator7;
|
||||||
|
private System.Windows.Forms.ListView assetListView;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
using AssetStudio;
|
using AssetStudio;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using OpenTK;
|
|
||||||
using OpenTK.Graphics.OpenGL;
|
using OpenTK.Graphics.OpenGL;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@@ -21,6 +20,7 @@ using static AssetStudioGUI.Studio;
|
|||||||
using Font = AssetStudio.Font;
|
using Font = AssetStudio.Font;
|
||||||
using Microsoft.WindowsAPICodePack.Taskbar;
|
using Microsoft.WindowsAPICodePack.Taskbar;
|
||||||
#if NET472
|
#if NET472
|
||||||
|
using OpenTK;
|
||||||
using Vector3 = OpenTK.Vector3;
|
using Vector3 = OpenTK.Vector3;
|
||||||
using Vector4 = OpenTK.Vector4;
|
using Vector4 = OpenTK.Vector4;
|
||||||
#else
|
#else
|
||||||
@@ -267,7 +267,10 @@ namespace AssetStudioGUI
|
|||||||
}
|
}
|
||||||
allToolStripMenuItem.Checked = true;
|
allToolStripMenuItem.Checked = true;
|
||||||
var log = $"Finished loading {assetsManager.assetsFileList.Count} files with {assetListView.Items.Count} exportable assets";
|
var log = $"Finished loading {assetsManager.assetsFileList.Count} files with {assetListView.Items.Count} exportable assets";
|
||||||
var m_ObjectsCount = assetsManager.assetsFileList.Sum(x => x.m_Objects.Count);
|
var unityVer = assetsManager.assetsFileList[0].version;
|
||||||
|
var m_ObjectsCount = unityVer[0] > 2020 ?
|
||||||
|
assetsManager.assetsFileList.Sum(x => x.m_Objects.LongCount(y => y.classID != (int)ClassIDType.Shader)) :
|
||||||
|
assetsManager.assetsFileList.Sum(x => x.m_Objects.Count);
|
||||||
var objectsCount = assetsManager.assetsFileList.Sum(x => x.Objects.Count);
|
var objectsCount = assetsManager.assetsFileList.Sum(x => x.Objects.Count);
|
||||||
if (m_ObjectsCount != objectsCount)
|
if (m_ObjectsCount != objectsCount)
|
||||||
{
|
{
|
||||||
@@ -499,10 +502,10 @@ namespace AssetStudioGUI
|
|||||||
switch (e.TabPageIndex)
|
switch (e.TabPageIndex)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
treeSearch.Select();
|
sceneTreeView.Select();
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
listSearch.Select();
|
assetListView.Select();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -782,42 +785,42 @@ namespace AssetStudioGUI
|
|||||||
return;
|
return;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
switch (assetItem.Asset)
|
switch (assetItem.Type)
|
||||||
{
|
{
|
||||||
case Texture2D m_Texture2D:
|
case ClassIDType.Texture2D:
|
||||||
PreviewTexture2D(assetItem, m_Texture2D);
|
PreviewTexture2D(assetItem, assetItem.Asset as Texture2D);
|
||||||
break;
|
break;
|
||||||
case AudioClip m_AudioClip:
|
case ClassIDType.AudioClip:
|
||||||
PreviewAudioClip(assetItem, m_AudioClip);
|
PreviewAudioClip(assetItem, assetItem.Asset as AudioClip);
|
||||||
break;
|
break;
|
||||||
case Shader m_Shader:
|
case ClassIDType.Shader:
|
||||||
PreviewShader(m_Shader);
|
PreviewShader(assetItem.Asset as Shader);
|
||||||
break;
|
break;
|
||||||
case TextAsset m_TextAsset:
|
case ClassIDType.TextAsset:
|
||||||
PreviewTextAsset(m_TextAsset);
|
PreviewTextAsset(assetItem.Asset as TextAsset);
|
||||||
break;
|
break;
|
||||||
case MonoBehaviour m_MonoBehaviour:
|
case ClassIDType.MonoBehaviour:
|
||||||
PreviewMonoBehaviour(m_MonoBehaviour);
|
PreviewMonoBehaviour(assetItem.Asset as MonoBehaviour);
|
||||||
break;
|
break;
|
||||||
case Font m_Font:
|
case ClassIDType.Font:
|
||||||
PreviewFont(m_Font);
|
PreviewFont(assetItem.Asset as Font);
|
||||||
break;
|
break;
|
||||||
case Mesh m_Mesh:
|
case ClassIDType.Mesh:
|
||||||
PreviewMesh(m_Mesh);
|
PreviewMesh(assetItem.Asset as Mesh);
|
||||||
break;
|
break;
|
||||||
case VideoClip m_VideoClip:
|
case ClassIDType.VideoClip:
|
||||||
PreviewVideoClip(assetItem, m_VideoClip);
|
PreviewVideoClip(assetItem, assetItem.Asset as VideoClip);
|
||||||
break;
|
break;
|
||||||
case MovieTexture _:
|
case ClassIDType.MovieTexture:
|
||||||
StatusStripUpdate("Only supported export.");
|
StatusStripUpdate("Only supported export.");
|
||||||
break;
|
break;
|
||||||
case Sprite m_Sprite:
|
case ClassIDType.Sprite:
|
||||||
PreviewSprite(assetItem, m_Sprite);
|
PreviewSprite(assetItem, assetItem.Asset as Sprite);
|
||||||
break;
|
break;
|
||||||
case Animator _:
|
case ClassIDType.Animator:
|
||||||
StatusStripUpdate("Can be exported to FBX file.");
|
StatusStripUpdate("Can be exported to FBX file.");
|
||||||
break;
|
break;
|
||||||
case AnimationClip _:
|
case ClassIDType.AnimationClip:
|
||||||
StatusStripUpdate("Can be exported with Animator or Objects");
|
StatusStripUpdate("Can be exported with Animator or Objects");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -1026,7 +1029,7 @@ namespace AssetStudioGUI
|
|||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
sb.AppendLine($"Width: {m_VideoClip.Width}");
|
sb.AppendLine($"Width: {m_VideoClip.Width}");
|
||||||
sb.AppendLine($"Height: {m_VideoClip.Height}");
|
sb.AppendLine($"Height: {m_VideoClip.Height}");
|
||||||
sb.AppendLine($"Frame rate: {m_VideoClip.m_FrameRate}");
|
sb.AppendLine($"Frame rate: {m_VideoClip.m_FrameRate:.0##}");
|
||||||
sb.AppendLine($"Split alpha: {m_VideoClip.m_HasSplitAlpha}");
|
sb.AppendLine($"Split alpha: {m_VideoClip.m_HasSplitAlpha}");
|
||||||
assetItem.InfoText = sb.ToString();
|
assetItem.InfoText = sb.ToString();
|
||||||
|
|
||||||
@@ -1809,10 +1812,11 @@ namespace AssetStudioGUI
|
|||||||
logger.ShowErrorMessage = toolStripMenuItem15.Checked;
|
logger.ShowErrorMessage = toolStripMenuItem15.Checked;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sceneTreeView_MouseClick(object sender, MouseEventArgs e)
|
private void sceneTreeView_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
|
||||||
{
|
{
|
||||||
if (e.Button == MouseButtons.Right && sceneTreeView.Nodes.Count > 0)
|
if (e.Button == MouseButtons.Right)
|
||||||
{
|
{
|
||||||
|
sceneTreeView.SelectedNode = e.Node;
|
||||||
contextMenuStrip2.Show(sceneTreeView, e.Location.X, e.Location.Y);
|
contextMenuStrip2.Show(sceneTreeView, e.Location.X, e.Location.Y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1921,6 +1925,77 @@ namespace AssetStudioGUI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void selectRelatedAsset(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
var selectedItem = (ToolStripMenuItem)sender;
|
||||||
|
var index = int.Parse(selectedItem.Name.Split('_')[0]);
|
||||||
|
|
||||||
|
assetListView.SelectedIndices.Clear();
|
||||||
|
tabControl1.SelectedTab = tabPage2;
|
||||||
|
var assetItem = assetListView.Items[index];
|
||||||
|
assetItem.Selected = true;
|
||||||
|
assetItem.EnsureVisible();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void selectAllRelatedAssets(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
var selectedNode = sceneTreeView.SelectedNode;
|
||||||
|
var relatedAssets = visibleAssets.FindAll(x => x.TreeNode == selectedNode);
|
||||||
|
if (relatedAssets.Count > 0)
|
||||||
|
{
|
||||||
|
assetListView.SelectedIndices.Clear();
|
||||||
|
tabControl1.SelectedTab = tabPage2;
|
||||||
|
foreach (var asset in relatedAssets)
|
||||||
|
{
|
||||||
|
var assetItem = assetListView.Items[assetListView.Items.IndexOf(asset)];
|
||||||
|
assetItem.Selected = true;
|
||||||
|
}
|
||||||
|
assetListView.Items[assetListView.Items.IndexOf(relatedAssets[0])].EnsureVisible();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showRelatedAssetsToolStripMenuItem_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
var selectedNode = sceneTreeView.SelectedNode;
|
||||||
|
var relatedAssets = visibleAssets.FindAll(x => x.TreeNode == selectedNode);
|
||||||
|
if (relatedAssets.Count == 0)
|
||||||
|
{
|
||||||
|
StatusStripUpdate("No related assets were found among the visible assets.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void contextMenuStrip2_Opening(object sender, System.ComponentModel.CancelEventArgs e)
|
||||||
|
{
|
||||||
|
var selectedNode = sceneTreeView.SelectedNode;
|
||||||
|
var relatedAssets = visibleAssets.FindAll(x => x.TreeNode == selectedNode);
|
||||||
|
showRelatedAssetsToolStripMenuItem.DropDownItems.Clear();
|
||||||
|
if (relatedAssets.Count > 1)
|
||||||
|
{
|
||||||
|
var assetItem = new ToolStripMenuItem
|
||||||
|
{
|
||||||
|
CheckOnClick = false,
|
||||||
|
Name = "selectAllRelatedAssetsToolStripMenuItem",
|
||||||
|
Size = new Size(180, 22),
|
||||||
|
Text = "Select all"
|
||||||
|
};
|
||||||
|
assetItem.Click += selectAllRelatedAssets;
|
||||||
|
showRelatedAssetsToolStripMenuItem.DropDownItems.Add(assetItem);
|
||||||
|
}
|
||||||
|
foreach (var asset in relatedAssets)
|
||||||
|
{
|
||||||
|
var index = assetListView.Items.IndexOf(asset);
|
||||||
|
var assetItem = new ToolStripMenuItem
|
||||||
|
{
|
||||||
|
CheckOnClick = false,
|
||||||
|
Name = $"{index}_{asset.TypeString}",
|
||||||
|
Size = new Size(180, 22),
|
||||||
|
Text = $"({asset.TypeString}) {asset.Text}"
|
||||||
|
};
|
||||||
|
assetItem.Click += selectRelatedAsset;
|
||||||
|
showRelatedAssetsToolStripMenuItem.DropDownItems.Add(assetItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#region FMOD
|
#region FMOD
|
||||||
private void FMODinit()
|
private void FMODinit()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -120,9 +120,6 @@
|
|||||||
<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.:,;'\"(!?)+-*/=
|
||||||
@@ -141,6 +138,9 @@ 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="contextMenuStrip2.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
<metadata name="contextMenuStrip2.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
<value>775, 21</value>
|
<value>775, 21</value>
|
||||||
</metadata>
|
</metadata>
|
||||||
|
|||||||
77
AssetStudioGUI/app.manifest
Normal file
77
AssetStudioGUI/app.manifest
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<assemblyIdentity version="1.0.0.0" name="AssetStudioMod.app"/>
|
||||||
|
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
|
||||||
|
<security>
|
||||||
|
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||||
|
<!-- UAC Manifest Options
|
||||||
|
If you want to change the Windows User Account Control level replace the
|
||||||
|
requestedExecutionLevel node with one of the following.
|
||||||
|
|
||||||
|
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
|
||||||
|
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
|
||||||
|
<requestedExecutionLevel level="highestAvailable" uiAccess="false" />
|
||||||
|
|
||||||
|
Specifying requestedExecutionLevel element will disable file and registry virtualization.
|
||||||
|
Remove this element if your application requires this virtualization for backwards
|
||||||
|
compatibility.
|
||||||
|
-->
|
||||||
|
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
|
||||||
|
</requestedPrivileges>
|
||||||
|
</security>
|
||||||
|
</trustInfo>
|
||||||
|
|
||||||
|
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||||||
|
<application>
|
||||||
|
<!-- A list of the Windows versions that this application has been tested on
|
||||||
|
and is designed to work with. Uncomment the appropriate elements
|
||||||
|
and Windows will automatically select the most compatible environment. -->
|
||||||
|
|
||||||
|
<!-- Windows Vista -->
|
||||||
|
<!--<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />-->
|
||||||
|
|
||||||
|
<!-- Windows 7 -->
|
||||||
|
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />
|
||||||
|
|
||||||
|
<!-- Windows 8 -->
|
||||||
|
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />
|
||||||
|
|
||||||
|
<!-- Windows 8.1 -->
|
||||||
|
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />
|
||||||
|
|
||||||
|
<!-- Windows 10 and Windows 11 -->
|
||||||
|
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
|
||||||
|
|
||||||
|
</application>
|
||||||
|
</compatibility>
|
||||||
|
|
||||||
|
<!-- Indicates that the application is DPI-aware and will not be automatically scaled by Windows at higher
|
||||||
|
DPIs. Windows Presentation Foundation (WPF) applications are automatically DPI-aware and do not need
|
||||||
|
to opt in. Windows Forms applications targeting .NET Framework 4.6 that opt into this setting, should
|
||||||
|
also set the 'EnableWindowsFormsHighDpiAutoResizing' setting to 'true' in their app.config.
|
||||||
|
|
||||||
|
Makes the application long-path aware. See https://docs.microsoft.com/windows/win32/fileio/maximum-file-path-limitation -->
|
||||||
|
<application xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||||
|
<windowsSettings>
|
||||||
|
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
|
||||||
|
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">system</dpiAwareness>
|
||||||
|
<longPathAware xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">true</longPathAware>
|
||||||
|
</windowsSettings>
|
||||||
|
</application>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Enable themes for Windows common controls and dialogs (Windows XP and later) -->
|
||||||
|
<dependency>
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity
|
||||||
|
type="win32"
|
||||||
|
name="Microsoft.Windows.Common-Controls"
|
||||||
|
version="6.0.0.0"
|
||||||
|
processorArchitecture="*"
|
||||||
|
publicKeyToken="6595b64144ccf1df"
|
||||||
|
language="*"
|
||||||
|
/>
|
||||||
|
</dependentAssembly>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</assembly>
|
||||||
@@ -33,7 +33,12 @@ namespace AssetStudio
|
|||||||
|
|
||||||
public TypeDefinition GetTypeDefinition(string assemblyName, string fullName)
|
public TypeDefinition GetTypeDefinition(string assemblyName, string fullName)
|
||||||
{
|
{
|
||||||
if (moduleDic.TryGetValue(assemblyName, out var module))
|
moduleDic.TryGetValue(assemblyName, out var module);
|
||||||
|
if (module == null && !assemblyName.Contains(".dll"))
|
||||||
|
{
|
||||||
|
moduleDic.TryGetValue(assemblyName + ".dll", out module);
|
||||||
|
}
|
||||||
|
if (module != null)
|
||||||
{
|
{
|
||||||
var typeDef = module.GetType(fullName);
|
var typeDef = module.GetType(fullName);
|
||||||
if (typeDef == null && assemblyName == "UnityEngine.dll")
|
if (typeDef == null && assemblyName == "UnityEngine.dll")
|
||||||
|
|||||||
@@ -2,15 +2,14 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>net472;net6.0;net6.0-windows;net7.0;net7.0-windows</TargetFrameworks>
|
<TargetFrameworks>net472;net6.0;net6.0-windows;net7.0;net7.0-windows</TargetFrameworks>
|
||||||
<Version>0.17.1.0</Version>
|
<Version>0.17.3.0</Version>
|
||||||
<Copyright>Copyright © Perfare 2018-2022</Copyright>
|
<Copyright>Copyright © Perfare 2018-2022; Copyright © aelurum 2023</Copyright>
|
||||||
<DebugType>embedded</DebugType>
|
<DebugType>embedded</DebugType>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Mono.Cecil" Version="0.11.3" />
|
<PackageReference Include="Mono.Cecil" Version="0.11.3" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
<PackageReference Include="SixLabors.ImageSharp.Drawing" Version="1.0.0-beta15" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup Condition=" !$(TargetFramework.Contains('windows')) ">
|
<ItemGroup Condition=" !$(TargetFramework.Contains('windows')) ">
|
||||||
@@ -23,6 +22,11 @@
|
|||||||
<PackageReference Include="Kyaru.Texture2DDecoder">
|
<PackageReference Include="Kyaru.Texture2DDecoder">
|
||||||
<Version>0.17.0</Version>
|
<Version>0.17.0</Version>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
<PackageReference Include="SixLabors.ImageSharp.Drawing" Version="1.0.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup Condition=" '$(TargetFramework)' == 'net472' ">
|
||||||
|
<PackageReference Include="SixLabors.ImageSharp.Drawing" Version="1.0.0-beta15" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ namespace CubismLive2DExtractor
|
|||||||
}
|
}
|
||||||
|
|
||||||
//motion
|
//motion
|
||||||
var motions = new JArray();
|
var motions = new SortedDictionary<string, JArray>();
|
||||||
|
|
||||||
if (gameObjects.Count > 0)
|
if (gameObjects.Count > 0)
|
||||||
{
|
{
|
||||||
@@ -205,11 +205,8 @@ namespace CubismLive2DExtractor
|
|||||||
}
|
}
|
||||||
json.Meta.TotalUserDataSize = totalUserDataSize;
|
json.Meta.TotalUserDataSize = totalUserDataSize;
|
||||||
|
|
||||||
motions.Add(new JObject
|
var motionPath = new JObject(new JProperty("File", $"motions/{animation.Name}.motion3.json"));
|
||||||
{
|
motions.Add(animation.Name, new JArray(motionPath));
|
||||||
{ "Name", animation.Name },
|
|
||||||
{ "File", $"motions/{animation.Name}.motion3.json" }
|
|
||||||
});
|
|
||||||
File.WriteAllText($"{destMotionPath}{animation.Name}.motion3.json", JsonConvert.SerializeObject(json, Formatting.Indented, new MyJsonConverter()));
|
File.WriteAllText($"{destMotionPath}{animation.Name}.motion3.json", JsonConvert.SerializeObject(json, Formatting.Indented, new MyJsonConverter()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -307,7 +304,7 @@ namespace CubismLive2DExtractor
|
|||||||
{
|
{
|
||||||
Moc = $"{modelName}.moc3",
|
Moc = $"{modelName}.moc3",
|
||||||
Textures = textures.ToArray(),
|
Textures = textures.ToArray(),
|
||||||
Motions = new JObject { { "", motions } },
|
Motions = JObject.FromObject(motions),
|
||||||
Expressions = expressions,
|
Expressions = expressions,
|
||||||
},
|
},
|
||||||
Groups = groups.ToArray()
|
Groups = groups.ToArray()
|
||||||
|
|||||||
@@ -34,7 +34,11 @@ namespace AssetStudio
|
|||||||
{
|
{
|
||||||
if (m_Sprite.m_RD.texture.TryGet(out var m_Texture2D) && m_Sprite.m_RD.alphaTexture.TryGet(out var m_AlphaTexture2D) && spriteMaskMode != SpriteMaskMode.Off)
|
if (m_Sprite.m_RD.texture.TryGet(out var m_Texture2D) && m_Sprite.m_RD.alphaTexture.TryGet(out var m_AlphaTexture2D) && spriteMaskMode != SpriteMaskMode.Off)
|
||||||
{
|
{
|
||||||
var tex = CutImage(m_Sprite, m_Texture2D, m_Sprite.m_RD.textureRect, m_Sprite.m_RD.textureRectOffset, m_Sprite.m_RD.downscaleMultiplier, m_Sprite.m_RD.settingsRaw);
|
Image<Bgra32> tex = null;
|
||||||
|
if (spriteMaskMode != SpriteMaskMode.MaskOnly)
|
||||||
|
{
|
||||||
|
tex = CutImage(m_Sprite, m_Texture2D, m_Sprite.m_RD.textureRect, m_Sprite.m_RD.textureRectOffset, m_Sprite.m_RD.downscaleMultiplier, m_Sprite.m_RD.settingsRaw);
|
||||||
|
}
|
||||||
var alphaTex = CutImage(m_Sprite, m_AlphaTexture2D, m_Sprite.m_RD.textureRect, m_Sprite.m_RD.textureRectOffset, m_Sprite.m_RD.downscaleMultiplier, m_Sprite.m_RD.settingsRaw);
|
var alphaTex = CutImage(m_Sprite, m_AlphaTexture2D, m_Sprite.m_RD.textureRect, m_Sprite.m_RD.textureRectOffset, m_Sprite.m_RD.downscaleMultiplier, m_Sprite.m_RD.settingsRaw);
|
||||||
|
|
||||||
switch (spriteMaskMode)
|
switch (spriteMaskMode)
|
||||||
@@ -46,7 +50,6 @@ namespace AssetStudio
|
|||||||
tex.ApplyRGBMask(alphaTex);
|
tex.ApplyRGBMask(alphaTex);
|
||||||
return tex;
|
return tex;
|
||||||
case SpriteMaskMode.MaskOnly:
|
case SpriteMaskMode.MaskOnly:
|
||||||
tex.Dispose();
|
|
||||||
return alphaTex;
|
return alphaTex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -89,92 +92,90 @@ namespace AssetStudio
|
|||||||
var originalImage = m_Texture2D.ConvertToImage(false);
|
var originalImage = m_Texture2D.ConvertToImage(false);
|
||||||
if (originalImage != null)
|
if (originalImage != null)
|
||||||
{
|
{
|
||||||
using (originalImage)
|
if (downscaleMultiplier > 0f && downscaleMultiplier != 1f)
|
||||||
{
|
{
|
||||||
if (downscaleMultiplier > 0f && downscaleMultiplier != 1f)
|
var width = (int)(m_Texture2D.m_Width / downscaleMultiplier);
|
||||||
{
|
var height = (int)(m_Texture2D.m_Height / downscaleMultiplier);
|
||||||
var width = (int)(m_Texture2D.m_Width / downscaleMultiplier);
|
originalImage.Mutate(x => x.Resize(width, height));
|
||||||
var height = (int)(m_Texture2D.m_Height / downscaleMultiplier);
|
|
||||||
originalImage.Mutate(x => x.Resize(width, height));
|
|
||||||
}
|
|
||||||
var rectX = (int)Math.Floor(textureRect.x);
|
|
||||||
var rectY = (int)Math.Floor(textureRect.y);
|
|
||||||
var rectRight = (int)Math.Ceiling(textureRect.x + textureRect.width);
|
|
||||||
var rectBottom = (int)Math.Ceiling(textureRect.y + textureRect.height);
|
|
||||||
rectRight = Math.Min(rectRight, originalImage.Width);
|
|
||||||
rectBottom = Math.Min(rectBottom, originalImage.Height);
|
|
||||||
var rect = new Rectangle(rectX, rectY, rectRight - rectX, rectBottom - rectY);
|
|
||||||
var spriteImage = originalImage.Clone(x => x.Crop(rect));
|
|
||||||
if (settingsRaw.packed == 1)
|
|
||||||
{
|
|
||||||
//RotateAndFlip
|
|
||||||
switch (settingsRaw.packingRotation)
|
|
||||||
{
|
|
||||||
case SpritePackingRotation.FlipHorizontal:
|
|
||||||
spriteImage.Mutate(x => x.Flip(FlipMode.Horizontal));
|
|
||||||
break;
|
|
||||||
case SpritePackingRotation.FlipVertical:
|
|
||||||
spriteImage.Mutate(x => x.Flip(FlipMode.Vertical));
|
|
||||||
break;
|
|
||||||
case SpritePackingRotation.Rotate180:
|
|
||||||
spriteImage.Mutate(x => x.Rotate(180));
|
|
||||||
break;
|
|
||||||
case SpritePackingRotation.Rotate90:
|
|
||||||
spriteImage.Mutate(x => x.Rotate(270));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Tight
|
|
||||||
if (settingsRaw.packingMode == SpritePackingMode.Tight)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var matrix = Matrix3x2.CreateScale(m_Sprite.m_PixelsToUnits);
|
|
||||||
matrix *= Matrix3x2.CreateTranslation(m_Sprite.m_Rect.width * m_Sprite.m_Pivot.X - textureRectOffset.X, m_Sprite.m_Rect.height * m_Sprite.m_Pivot.Y - textureRectOffset.Y);
|
|
||||||
var triangles = GetTriangles(m_Sprite.m_RD);
|
|
||||||
var points = triangles.Select(x => x.Select(y => new PointF(y.X, y.Y)).ToArray());
|
|
||||||
var pathBuilder = new PathBuilder(matrix);
|
|
||||||
foreach (var p in points)
|
|
||||||
{
|
|
||||||
pathBuilder.AddLines(p);
|
|
||||||
pathBuilder.CloseFigure();
|
|
||||||
}
|
|
||||||
var path = pathBuilder.Build();
|
|
||||||
var options = new DrawingOptions
|
|
||||||
{
|
|
||||||
GraphicsOptions = new GraphicsOptions
|
|
||||||
{
|
|
||||||
Antialias = false,
|
|
||||||
AlphaCompositionMode = PixelAlphaCompositionMode.DestOut
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if (triangles.Length < 1024)
|
|
||||||
{
|
|
||||||
var rectP = new RectangularPolygon(0, 0, rect.Width, rect.Height);
|
|
||||||
spriteImage.Mutate(x => x.Fill(options, SixLabors.ImageSharp.Color.Red, rectP.Clip(path)));
|
|
||||||
spriteImage.Mutate(x => x.Flip(FlipMode.Vertical));
|
|
||||||
return spriteImage;
|
|
||||||
}
|
|
||||||
using (var mask = new Image<Bgra32>(rect.Width, rect.Height, SixLabors.ImageSharp.Color.Black))
|
|
||||||
{
|
|
||||||
mask.Mutate(x => x.Fill(options, SixLabors.ImageSharp.Color.Red, path));
|
|
||||||
var brush = new ImageBrush(mask);
|
|
||||||
spriteImage.Mutate(x => x.Fill(options, brush));
|
|
||||||
spriteImage.Mutate(x => x.Flip(FlipMode.Vertical));
|
|
||||||
return spriteImage;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
// ignored
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Rectangle
|
|
||||||
spriteImage.Mutate(x => x.Flip(FlipMode.Vertical));
|
|
||||||
return spriteImage;
|
|
||||||
}
|
}
|
||||||
|
var rectX = (int)Math.Floor(textureRect.x);
|
||||||
|
var rectY = (int)Math.Floor(textureRect.y);
|
||||||
|
var rectRight = (int)Math.Ceiling(textureRect.x + textureRect.width);
|
||||||
|
var rectBottom = (int)Math.Ceiling(textureRect.y + textureRect.height);
|
||||||
|
rectRight = Math.Min(rectRight, originalImage.Width);
|
||||||
|
rectBottom = Math.Min(rectBottom, originalImage.Height);
|
||||||
|
var rect = new Rectangle(rectX, rectY, rectRight - rectX, rectBottom - rectY);
|
||||||
|
var spriteImage = originalImage.Clone(x => x.Crop(rect));
|
||||||
|
originalImage.Dispose();
|
||||||
|
if (settingsRaw.packed == 1)
|
||||||
|
{
|
||||||
|
//RotateAndFlip
|
||||||
|
switch (settingsRaw.packingRotation)
|
||||||
|
{
|
||||||
|
case SpritePackingRotation.FlipHorizontal:
|
||||||
|
spriteImage.Mutate(x => x.Flip(FlipMode.Horizontal));
|
||||||
|
break;
|
||||||
|
case SpritePackingRotation.FlipVertical:
|
||||||
|
spriteImage.Mutate(x => x.Flip(FlipMode.Vertical));
|
||||||
|
break;
|
||||||
|
case SpritePackingRotation.Rotate180:
|
||||||
|
spriteImage.Mutate(x => x.Rotate(180));
|
||||||
|
break;
|
||||||
|
case SpritePackingRotation.Rotate90:
|
||||||
|
spriteImage.Mutate(x => x.Rotate(270));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Tight
|
||||||
|
if (settingsRaw.packingMode == SpritePackingMode.Tight)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var matrix = Matrix3x2.CreateScale(m_Sprite.m_PixelsToUnits);
|
||||||
|
matrix *= Matrix3x2.CreateTranslation(m_Sprite.m_Rect.width * m_Sprite.m_Pivot.X - textureRectOffset.X, m_Sprite.m_Rect.height * m_Sprite.m_Pivot.Y - textureRectOffset.Y);
|
||||||
|
var triangles = GetTriangles(m_Sprite.m_RD);
|
||||||
|
var points = triangles.Select(x => x.Select(y => new PointF(y.X, y.Y)).ToArray());
|
||||||
|
var pathBuilder = new PathBuilder(matrix);
|
||||||
|
foreach (var p in points)
|
||||||
|
{
|
||||||
|
pathBuilder.AddLines(p);
|
||||||
|
pathBuilder.CloseFigure();
|
||||||
|
}
|
||||||
|
var path = pathBuilder.Build();
|
||||||
|
var options = new DrawingOptions
|
||||||
|
{
|
||||||
|
GraphicsOptions = new GraphicsOptions
|
||||||
|
{
|
||||||
|
Antialias = false,
|
||||||
|
AlphaCompositionMode = PixelAlphaCompositionMode.DestOut
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (triangles.Length < 1024)
|
||||||
|
{
|
||||||
|
var rectP = new RectangularPolygon(0, 0, rect.Width, rect.Height);
|
||||||
|
spriteImage.Mutate(x => x.Fill(options, SixLabors.ImageSharp.Color.Red, rectP.Clip(path)));
|
||||||
|
spriteImage.Mutate(x => x.Flip(FlipMode.Vertical));
|
||||||
|
return spriteImage;
|
||||||
|
}
|
||||||
|
using (var mask = new Image<Bgra32>(rect.Width, rect.Height, SixLabors.ImageSharp.Color.Black))
|
||||||
|
{
|
||||||
|
mask.Mutate(x => x.Fill(options, SixLabors.ImageSharp.Color.Red, path));
|
||||||
|
var brush = new ImageBrush(mask);
|
||||||
|
spriteImage.Mutate(x => x.Fill(options, brush));
|
||||||
|
spriteImage.Mutate(x => x.Flip(FlipMode.Vertical));
|
||||||
|
return spriteImage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Rectangle
|
||||||
|
spriteImage.Mutate(x => x.Flip(FlipMode.Vertical));
|
||||||
|
return spriteImage;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
23
CHANGELOG.md
23
CHANGELOG.md
@@ -1,5 +1,28 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## v0.17.3.0 [13-09-2023]
|
||||||
|
- [CLI] Added support for exporting split objects (fbx) (https://github.com/aelurum/AssetStudio/pull/10)
|
||||||
|
- [CLI] Fixed display of asset names in the exported asset list in some working modes
|
||||||
|
- [CLI] Fixed a bug where the default output folder might not exist
|
||||||
|
- Added support of Texture2D assets from Unity 2022.2+
|
||||||
|
- Fixed AssemblyLoader (https://github.com/aelurum/AssetStudio/issues/6)
|
||||||
|
- [CLI] Added --load-all flag to load assets of all types
|
||||||
|
- [CLI] Improved option grouping on the help screen
|
||||||
|
|
||||||
|
## v0.17.2.0 [27-08-2023]
|
||||||
|
- [GUI] Improved Scene Hierarchy tab
|
||||||
|
- Added "Related assets" item to the context menu (https://github.com/aelurum/AssetStudio/issues/7)
|
||||||
|
- [GUI] Added app.manifest for net472 build
|
||||||
|
- Added long paths support (win10 v1607+)
|
||||||
|
- Fixed blurring at high DPI with scaling
|
||||||
|
- [CLI] Fixed sprite export in sprite only mode
|
||||||
|
- Made some changes to motion list for live2d models
|
||||||
|
- Motion list is now sorted
|
||||||
|
- Motions divided into groups (each motion is a separate group)
|
||||||
|
- Motion names are used as group names
|
||||||
|
- Updated dependencies
|
||||||
|
- Made some other minor fixes and improvements
|
||||||
|
|
||||||
## v0.17.1.0 [12-07-2023]
|
## v0.17.1.0 [12-07-2023]
|
||||||
#### Breaking Changes
|
#### Breaking Changes
|
||||||
- With the drag&drop fix (https://github.com/aelurum/AssetStudio/commit/2f8f57c1a63893c0b0d2a55349d6cb6d8f8a5a3b), functions `LoadFiles` and `LoadFolder` in AssetsManager have been replaced with one universal function `LoadFilesAndFolders`
|
- With the drag&drop fix (https://github.com/aelurum/AssetStudio/commit/2f8f57c1a63893c0b0d2a55349d6cb6d8f8a5a3b), functions `LoadFiles` and `LoadFolder` in AssetsManager have been replaced with one universal function `LoadFilesAndFolders`
|
||||||
|
|||||||
31
README.md
31
README.md
@@ -89,12 +89,22 @@ AssetStudioModCLI <asset folder path> -g type
|
|||||||
```
|
```
|
||||||
AssetStudioModCLI <asset folder path> -o <output folder path>
|
AssetStudioModCLI <asset folder path> -o <output folder path>
|
||||||
```
|
```
|
||||||
|
- Dump assets to a specified output folder
|
||||||
|
```
|
||||||
|
AssetStudioModCLI <asset folder path> -m dump -o <output folder path>
|
||||||
|
```
|
||||||
- Export Live2D Cubism models
|
- Export Live2D Cubism models
|
||||||
```
|
```
|
||||||
AssetStudioModCLI <asset folder path> -m live2d
|
AssetStudioModCLI <asset folder path> -m live2d
|
||||||
```
|
```
|
||||||
> When running in live2d mode you can only specify `-o`, `--log-level`, `--log-output`, `--export-asset-list`, `--unity-version` and `--assembly-folder` options.
|
> When running in live2d mode you can only specify `-o`, `--log-level`, `--log-output`, `--export-asset-list`, `--unity-version` and `--assembly-folder` options.
|
||||||
Any other options will be ignored.
|
Any other options will be ignored.
|
||||||
|
- Export all FBX objects (similar to "Export all objects (split)" option in the GUI)
|
||||||
|
```
|
||||||
|
AssetStudioModCLI <asset folder path> -m splitObjects
|
||||||
|
```
|
||||||
|
> When running in splitObjects mode you can only specify `-o`, `--log-level`, `--log-output`, `--export-asset-list`, `--image-format`, `--filter-by-name` and `--unity-version` options.
|
||||||
|
Any other options will be ignored.
|
||||||
|
|
||||||
### Advanced Samples
|
### Advanced Samples
|
||||||
- Export image assets converted to webp format to a specified output folder
|
- Export image assets converted to webp format to a specified output folder
|
||||||
@@ -109,6 +119,13 @@ AssetStudioModCLI <asset folder path> -m info -t audio --filter-by-name voice
|
|||||||
```
|
```
|
||||||
AssetStudioModCLI <asset folder path> -t audio --filter-by-name voice
|
AssetStudioModCLI <asset folder path> -t audio --filter-by-name voice
|
||||||
```
|
```
|
||||||
|
- Export audio assets that have "music" or "voice" in their names
|
||||||
|
```
|
||||||
|
AssetStudioModCLI <asset folder path> -t audio --filter-by-name music,voice
|
||||||
|
```
|
||||||
|
```
|
||||||
|
AssetStudioModCLI <asset folder path> -t audio --filter-by-name music --filter-by-name voice
|
||||||
|
```
|
||||||
- Export audio assets that have "char" in their names **or** containers
|
- Export audio assets that have "char" in their names **or** containers
|
||||||
```
|
```
|
||||||
AssetStudioModCLI <asset folder path> -t audio --filter-by-text char
|
AssetStudioModCLI <asset folder path> -t audio --filter-by-text char
|
||||||
@@ -117,6 +134,10 @@ AssetStudioModCLI <asset folder path> -t audio --filter-by-text char
|
|||||||
```
|
```
|
||||||
AssetStudioModCLI <asset folder path> -t audio --filter-by-name voice --filter-by-container char
|
AssetStudioModCLI <asset folder path> -t audio --filter-by-name voice --filter-by-container char
|
||||||
```
|
```
|
||||||
|
- Export FBX objects that have "model" or "scene" in their names and set the scale factor to 10
|
||||||
|
```
|
||||||
|
AssetStudioModCLI <asset folder path> -m splitObjects --filter-by-name model,scene --fbx-scale-factor 10
|
||||||
|
```
|
||||||
- Export MonoBehaviour assets that require an assembly folder to read and create a log file
|
- Export MonoBehaviour assets that require an assembly folder to read and create a log file
|
||||||
```
|
```
|
||||||
AssetStudioModCLI <asset folder path> -t monobehaviour --assembly-folder <assembly folder path> --log-output both
|
AssetStudioModCLI <asset folder path> -t monobehaviour --assembly-folder <assembly folder path> --log-output both
|
||||||
@@ -125,6 +146,14 @@ AssetStudioModCLI <asset folder path> -t monobehaviour --assembly-folder <assemb
|
|||||||
```
|
```
|
||||||
AssetStudioModCLI <asset folder path> --unity-version 2017.4.39f1
|
AssetStudioModCLI <asset folder path> --unity-version 2017.4.39f1
|
||||||
```
|
```
|
||||||
|
- Load assets of all types and show them (similar to "Display all assets" option in the GUI)
|
||||||
|
```
|
||||||
|
AssetStudioModCLI <asset folder path> -m info --load-all
|
||||||
|
```
|
||||||
|
- Load assets of all types and dump Material assets
|
||||||
|
```
|
||||||
|
AssetStudioModCLI <asset folder path> -m dump -t material --load-all
|
||||||
|
```
|
||||||
|
|
||||||
## GUI Usage
|
## GUI Usage
|
||||||
|
|
||||||
@@ -140,7 +169,7 @@ Use **File->Extract file** or **File->Extract folder**.
|
|||||||
|
|
||||||
### Export Assets, Live2D models
|
### Export Assets, Live2D models
|
||||||
|
|
||||||
use **Export** menu.
|
Use **Export** menu.
|
||||||
|
|
||||||
### Export Model
|
### Export Model
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net472</TargetFramework>
|
<TargetFramework>net472</TargetFramework>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<Version>0.17.1.0</Version>
|
<Version>0.17.3.0</Version>
|
||||||
<Copyright>Copyright © Perfare 2020-2022; Copyright © hozuki 2020</Copyright>
|
<Copyright>Copyright © Perfare 2020-2022; Copyright © hozuki 2020</Copyright>
|
||||||
<DebugType>embedded</DebugType>
|
<DebugType>embedded</DebugType>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|||||||
Reference in New Issue
Block a user