Skip to content

Commit

Permalink
Automated texture exporting
Browse files Browse the repository at this point in the history
  • Loading branch information
hozuki committed May 12, 2020
1 parent 034499b commit 570b726
Show file tree
Hide file tree
Showing 14 changed files with 319 additions and 52 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ packages

[Bb]in
[Oo]bj
[Dd]ebug
[Rr]elease

*.csproj.user
*.sln.user
Expand Down
11 changes: 8 additions & 3 deletions scripts/pack_artifacts.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ $subPaths = @(
[String]::Format("src/AcbPack/bin/{0}", $configuration),
[String]::Format("src/HcaDec/bin/{0}", $configuration),
[String]::Format("src/ManifestExport/bin/{0}", $configuration),
[String]::Format("src/MillionDance/bin/{0}", $configuration),
[String]::Format("src/MillionDance/bin/x86/{0}", $configuration), # temporarily fixed to x86 because of AssetStudioUtilities
[String]::Format("src/MillionDanceView/bin/{0}", $configuration),
[String]::Format("src/MiriTore.Common/bin/{0}", $configuration),
[String]::Format("src/MiriTore.Logging/bin/{0}", $configuration),
Expand All @@ -23,8 +23,13 @@ foreach ($subPath in $subPaths) {
continue
}

[String]$fullDirPath = [System.IO.Path]::Combine($basePath, $subPath, "*");
[String]$fullDirPath = [System.IO.Path]::Combine($basePath, $subPath);
[String]$xmlFilesPattern = [System.IO.Path]::Combine($fullDirPath, "*.xml")

Remove-Item $xmlFilesPattern

[String]$allFilesPattern = [System.IO.Path]::Combine($fullDirPath, "*")

[ScriptBlock]$scriptBlock = { 7z a $zipName -r $fullDirPath }
[ScriptBlock]$scriptBlock = { 7z a $zipName -r $allFilesPattern }
Invoke-Command -ScriptBlock $scriptBlock
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
<Compile Include="SkeletonPose.cs" />
<Compile Include="RawTransform.cs" />
<Compile Include="SubMesh.cs" />
<Compile Include="TexturedMaterial.cs" />
<Compile Include="Utilities\EnumerableUtils.cs" />
</ItemGroup>
<ItemGroup>
Expand Down
4 changes: 3 additions & 1 deletion src/AssetStudio.Extended.CompositeModels/CompositeMesh.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,9 @@ private CompositeMesh([NotNull] PrettyMesh[] meshes) {
var subMesh = mesh.SubMeshes[i];
Debug.Assert(subMesh.Topology == PrimitiveType.Triangles);

var newSubMesh = new SubMesh(subMesh.FirstIndex + indexStart, subMesh.IndexCount, subMesh.Topology, subMesh.TriangleCount, subMesh.FirstVertex + vertexStart, subMesh.VertexCount, subMesh.BoundingBox);
var newSubMesh = new SubMesh(
subMesh.FirstIndex + indexStart, subMesh.IndexCount, subMesh.Topology, subMesh.TriangleCount,
subMesh.FirstVertex + vertexStart, subMesh.VertexCount, subMesh.BoundingBox, subMesh.Material);

subMeshList.Add(newSubMesh);

Expand Down
133 changes: 131 additions & 2 deletions src/AssetStudio.Extended.CompositeModels/MeshWrapper.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using JetBrains.Annotations;

namespace AssetStudio.Extended.CompositeModels {
public sealed class MeshWrapper : PrettyMesh {

public MeshWrapper([NotNull] Mesh mesh) {
public MeshWrapper([NotNull] IReadOnlyList<SerializedFile> assetFiles, [NotNull] Mesh mesh, bool flipTexture) {
Name = mesh.m_Name;

{
Expand All @@ -14,7 +16,8 @@ public MeshWrapper([NotNull] Mesh mesh) {

for (var i = 0; i < mesh.m_SubMeshes.Length; i += 1) {
var subMesh = mesh.m_SubMeshes[i];
var sm = new SubMesh(meshIndexStart, subMesh);
var mat = FindMaterialInfo(assetFiles, mesh, i, flipTexture);
var sm = new SubMesh(meshIndexStart, subMesh, mat);
subMeshes[i] = sm;
meshIndexStart += subMesh.indexCount;
}
Expand Down Expand Up @@ -147,6 +150,132 @@ private static Vector3[] ReadVector3Array([NotNull] float[] array, int count) {
return result;
}

[NotNull]
private static TexturedMaterial FindMaterialInfo([NotNull] IReadOnlyList<SerializedFile> assetFiles, [NotNull] Mesh mesh, int meshIndex, bool flipTexture) {
SkinnedMeshRenderer meshRenderer = null;

foreach (var assetFile in assetFiles) {
foreach (var obj in assetFile.Objects) {
if (obj.type != ClassIDType.SkinnedMeshRenderer) {
continue;
}

var renderer = obj as SkinnedMeshRenderer;

Debug.Assert(renderer != null);

if (renderer.m_Mesh.m_PathID == mesh.m_PathID) {
meshRenderer = renderer;
break;
}
}
}

if (meshRenderer == null) {
throw new KeyNotFoundException($"Found no SkinnedMeshRenderer associated with this mesh ({mesh.m_Name}).");
}

Debug.Assert(meshRenderer.m_Materials != null);

if (meshRenderer.m_Materials.Length <= meshIndex) {
throw new FormatException("No corresponding material is associated with this SkinnedMeshRenderer.");
}

var materialPtr = meshRenderer.m_Materials[meshIndex];
Material material = null;

foreach (var assetFile in assetFiles) {
foreach (var obj in assetFile.Objects) {
if (obj.type != ClassIDType.Material) {
continue;
}

var mat = obj as Material;

Debug.Assert(mat != null);

if (mat.m_PathID == materialPtr.m_PathID) {
material = mat;
break;
}
}
}

if (material == null) {
throw new KeyNotFoundException("Main material is not found by path ID.");
}

Debug.Assert(material.m_SavedProperties != null);
Debug.Assert(material.m_SavedProperties.m_TexEnvs != null);
Debug.Assert(material.m_SavedProperties.m_TexEnvs.Length > 0);

var kvPairs = material.m_SavedProperties.m_TexEnvs;
UnityTexEnv mainTexEnv = null;
UnityTexEnv subTexEnv = null;

foreach (var kv in kvPairs) {
if (kv.Key.Equals("_MainTex", StringComparison.Ordinal)) {
mainTexEnv = kv.Value;
} else if (kv.Key.Equals("_SubTex", StringComparison.Ordinal)) {
subTexEnv = kv.Value;
}
}

if (mainTexEnv == null) {
throw new KeyNotFoundException("Main texture is missing.");
}

Texture2D mainTexture = null;

foreach (var assetFile in assetFiles) {
foreach (var obj in assetFile.Objects) {
if (obj.type != ClassIDType.Texture2D) {
continue;
}

var tex = obj as Texture2D;

Debug.Assert(tex != null);

if (tex.m_PathID == mainTexEnv.m_Texture.m_PathID) {
mainTexture = tex;
break;
}
}
}

if (mainTexture == null) {
throw new KeyNotFoundException("Main texture is not found by path ID.");
}

Texture2D subTexture = null;

if (subTexEnv != null) {
foreach (var assetFile in assetFiles) {
foreach (var obj in assetFile.Objects) {
if (obj.type != ClassIDType.Texture2D) {
continue;
}

var tex = obj as Texture2D;

Debug.Assert(tex != null);

if (tex.m_PathID == subTexEnv.m_Texture.m_PathID) {
subTexture = tex;
break;
}
}
}

if (subTexture == null) {
throw new KeyNotFoundException("Sub texture is not found by path ID.");
}
}

return new TexturedMaterial(material.m_Name, mainTexture, subTexture, flipTexture);
}

[NotNull]
private static Vector4[] ReadVector4Array([NotNull] float[] array) {
return ReadVector4Array(array, array.Length / 4);
Expand Down
9 changes: 7 additions & 2 deletions src/AssetStudio.Extended.CompositeModels/SubMesh.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,26 @@
namespace AssetStudio.Extended.CompositeModels {
public sealed class SubMesh {

internal SubMesh(uint firstIndex, uint indexCount, PrimitiveType topology, uint triangleCount, uint firstVertex, uint vertexCount, AABB boundingBox) {
internal SubMesh(uint firstIndex, uint indexCount, PrimitiveType topology, uint triangleCount, uint firstVertex, uint vertexCount, AABB boundingBox, [NotNull] TexturedMaterial material) {
FirstIndex = firstIndex;
IndexCount = indexCount;
Topology = topology;
TriangleCount = triangleCount;
FirstVertex = firstVertex;
VertexCount = vertexCount;
BoundingBox = boundingBox;
Material = material;
}

internal SubMesh(uint firstIndex, [NotNull] AssetStudio.SubMesh mesh) {
internal SubMesh(uint firstIndex, [NotNull] AssetStudio.SubMesh mesh, [NotNull] TexturedMaterial material) {
FirstIndex = firstIndex;
IndexCount = mesh.indexCount;
Topology = (PrimitiveType)mesh.topology;
TriangleCount = mesh.triangleCount;
FirstVertex = mesh.firstVertex;
VertexCount = mesh.vertexCount;
BoundingBox = new AABB(mesh.localAABB);
Material = material;
}

public uint FirstIndex { get; }
Expand All @@ -37,5 +39,8 @@ internal SubMesh(uint firstIndex, [NotNull] AssetStudio.SubMesh mesh) {

public AABB BoundingBox { get; }

[NotNull]
public TexturedMaterial Material { get; }

}
}
25 changes: 25 additions & 0 deletions src/AssetStudio.Extended.CompositeModels/TexturedMaterial.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using JetBrains.Annotations;

namespace AssetStudio.Extended.CompositeModels {
public sealed class TexturedMaterial {

internal TexturedMaterial([NotNull] string materialName, [NotNull] Texture2D mainTexture, [CanBeNull] Texture2D subTexture, bool flip) {
MaterialName = materialName;
MainTexture = mainTexture;
SubTexture = subTexture;
Flip = flip;
}

[NotNull]
public string MaterialName { get; }

[NotNull]
public Texture2D MainTexture { get; }

[CanBeNull]
public Texture2D SubTexture { get; }

public bool Flip { get; }

}
}
67 changes: 55 additions & 12 deletions src/MLTDTools.sln
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ManifestTools", "ManifestTo
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Imas.Data.Serialized", "Imas.Data.Serialized\Imas.Data.Serialized.csproj", "{3E816E61-9809-4B77-92D9-4AD891EAEAA3}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AssetStudioUtility", "..\thirdparty\AssetStudio\AssetStudioUtility\AssetStudioUtility.csproj", "{80AEC261-21EE-4E4F-A93B-7A744DC84888}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AssetStudioFBX", "..\thirdparty\AssetStudio\AssetStudioFBX\AssetStudioFBX.vcxproj", "{B82DD1BA-4EEC-4F29-A686-03D7F0DF39B8}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Texture2DDecoder", "..\thirdparty\AssetStudio\Texture2DDecoder\Texture2DDecoder.vcxproj", "{BEC7B5E6-0A7B-4824-97A7-EEA04D9EBA29}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -204,18 +210,16 @@ Global
{EC1E2F06-5AF6-42E8-9161-E5B26CEF2C63}.Release|x64.Build.0 = Release|Any CPU
{EC1E2F06-5AF6-42E8-9161-E5B26CEF2C63}.Release|x86.ActiveCfg = Release|Any CPU
{EC1E2F06-5AF6-42E8-9161-E5B26CEF2C63}.Release|x86.Build.0 = Release|Any CPU
{8A36E44E-4CF7-48A6-874C-FC770D02D874}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8A36E44E-4CF7-48A6-874C-FC770D02D874}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8A36E44E-4CF7-48A6-874C-FC770D02D874}.Debug|x64.ActiveCfg = Debug|Any CPU
{8A36E44E-4CF7-48A6-874C-FC770D02D874}.Debug|x64.Build.0 = Debug|Any CPU
{8A36E44E-4CF7-48A6-874C-FC770D02D874}.Debug|x86.ActiveCfg = Debug|Any CPU
{8A36E44E-4CF7-48A6-874C-FC770D02D874}.Debug|x86.Build.0 = Debug|Any CPU
{8A36E44E-4CF7-48A6-874C-FC770D02D874}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8A36E44E-4CF7-48A6-874C-FC770D02D874}.Release|Any CPU.Build.0 = Release|Any CPU
{8A36E44E-4CF7-48A6-874C-FC770D02D874}.Release|x64.ActiveCfg = Release|Any CPU
{8A36E44E-4CF7-48A6-874C-FC770D02D874}.Release|x64.Build.0 = Release|Any CPU
{8A36E44E-4CF7-48A6-874C-FC770D02D874}.Release|x86.ActiveCfg = Release|Any CPU
{8A36E44E-4CF7-48A6-874C-FC770D02D874}.Release|x86.Build.0 = Release|Any CPU
{8A36E44E-4CF7-48A6-874C-FC770D02D874}.Debug|Any CPU.ActiveCfg = Debug|x86
{8A36E44E-4CF7-48A6-874C-FC770D02D874}.Debug|Any CPU.Build.0 = Debug|x86
{8A36E44E-4CF7-48A6-874C-FC770D02D874}.Debug|x64.ActiveCfg = Debug|x86
{8A36E44E-4CF7-48A6-874C-FC770D02D874}.Debug|x86.ActiveCfg = Debug|x86
{8A36E44E-4CF7-48A6-874C-FC770D02D874}.Debug|x86.Build.0 = Debug|x86
{8A36E44E-4CF7-48A6-874C-FC770D02D874}.Release|Any CPU.ActiveCfg = Release|x86
{8A36E44E-4CF7-48A6-874C-FC770D02D874}.Release|Any CPU.Build.0 = Release|x86
{8A36E44E-4CF7-48A6-874C-FC770D02D874}.Release|x64.ActiveCfg = Release|x86
{8A36E44E-4CF7-48A6-874C-FC770D02D874}.Release|x86.ActiveCfg = Release|x86
{8A36E44E-4CF7-48A6-874C-FC770D02D874}.Release|x86.Build.0 = Release|x86
{A2039EB5-47FF-475E-A2D8-D72AB85099D5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A2039EB5-47FF-475E-A2D8-D72AB85099D5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A2039EB5-47FF-475E-A2D8-D72AB85099D5}.Debug|x64.ActiveCfg = Debug|Any CPU
Expand Down Expand Up @@ -312,6 +316,42 @@ Global
{3E816E61-9809-4B77-92D9-4AD891EAEAA3}.Release|x64.Build.0 = Release|Any CPU
{3E816E61-9809-4B77-92D9-4AD891EAEAA3}.Release|x86.ActiveCfg = Release|Any CPU
{3E816E61-9809-4B77-92D9-4AD891EAEAA3}.Release|x86.Build.0 = Release|Any CPU
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Debug|Any CPU.ActiveCfg = Debug|x86
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Debug|Any CPU.Build.0 = Debug|x86
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Debug|x64.ActiveCfg = Debug|x64
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Debug|x64.Build.0 = Debug|x64
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Debug|x86.ActiveCfg = Debug|x86
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Debug|x86.Build.0 = Debug|x86
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Release|Any CPU.ActiveCfg = Release|x86
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Release|Any CPU.Build.0 = Release|x86
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Release|x64.ActiveCfg = Release|x64
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Release|x64.Build.0 = Release|x64
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Release|x86.ActiveCfg = Release|x86
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Release|x86.Build.0 = Release|x86
{B82DD1BA-4EEC-4F29-A686-03D7F0DF39B8}.Debug|Any CPU.ActiveCfg = Debug|Win32
{B82DD1BA-4EEC-4F29-A686-03D7F0DF39B8}.Debug|Any CPU.Build.0 = Debug|Win32
{B82DD1BA-4EEC-4F29-A686-03D7F0DF39B8}.Debug|x64.ActiveCfg = Debug|x64
{B82DD1BA-4EEC-4F29-A686-03D7F0DF39B8}.Debug|x64.Build.0 = Debug|x64
{B82DD1BA-4EEC-4F29-A686-03D7F0DF39B8}.Debug|x86.ActiveCfg = Debug|Win32
{B82DD1BA-4EEC-4F29-A686-03D7F0DF39B8}.Debug|x86.Build.0 = Debug|Win32
{B82DD1BA-4EEC-4F29-A686-03D7F0DF39B8}.Release|Any CPU.ActiveCfg = Release|Win32
{B82DD1BA-4EEC-4F29-A686-03D7F0DF39B8}.Release|Any CPU.Build.0 = Release|Win32
{B82DD1BA-4EEC-4F29-A686-03D7F0DF39B8}.Release|x64.ActiveCfg = Release|x64
{B82DD1BA-4EEC-4F29-A686-03D7F0DF39B8}.Release|x64.Build.0 = Release|x64
{B82DD1BA-4EEC-4F29-A686-03D7F0DF39B8}.Release|x86.ActiveCfg = Release|Win32
{B82DD1BA-4EEC-4F29-A686-03D7F0DF39B8}.Release|x86.Build.0 = Release|Win32
{BEC7B5E6-0A7B-4824-97A7-EEA04D9EBA29}.Debug|Any CPU.ActiveCfg = Debug|Win32
{BEC7B5E6-0A7B-4824-97A7-EEA04D9EBA29}.Debug|Any CPU.Build.0 = Debug|Win32
{BEC7B5E6-0A7B-4824-97A7-EEA04D9EBA29}.Debug|x64.ActiveCfg = Debug|x64
{BEC7B5E6-0A7B-4824-97A7-EEA04D9EBA29}.Debug|x64.Build.0 = Debug|x64
{BEC7B5E6-0A7B-4824-97A7-EEA04D9EBA29}.Debug|x86.ActiveCfg = Debug|Win32
{BEC7B5E6-0A7B-4824-97A7-EEA04D9EBA29}.Debug|x86.Build.0 = Debug|Win32
{BEC7B5E6-0A7B-4824-97A7-EEA04D9EBA29}.Release|Any CPU.ActiveCfg = Release|Win32
{BEC7B5E6-0A7B-4824-97A7-EEA04D9EBA29}.Release|Any CPU.Build.0 = Release|Win32
{BEC7B5E6-0A7B-4824-97A7-EEA04D9EBA29}.Release|x64.ActiveCfg = Release|x64
{BEC7B5E6-0A7B-4824-97A7-EEA04D9EBA29}.Release|x64.Build.0 = Release|x64
{BEC7B5E6-0A7B-4824-97A7-EEA04D9EBA29}.Release|x86.ActiveCfg = Release|Win32
{BEC7B5E6-0A7B-4824-97A7-EEA04D9EBA29}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -338,6 +378,9 @@ Global
{A6D3FFB6-4148-476A-AE9A-BD78F76DBBAD} = {3ED8CB94-F888-4777-9DA1-B37FB40E0254}
{62AFF6D3-6D93-4D2E-A412-A3E08D2E269D} = {3ED8CB94-F888-4777-9DA1-B37FB40E0254}
{3E816E61-9809-4B77-92D9-4AD891EAEAA3} = {3ED8CB94-F888-4777-9DA1-B37FB40E0254}
{80AEC261-21EE-4E4F-A93B-7A744DC84888} = {DA4CBFCC-395C-4C21-8441-31FB0738E054}
{B82DD1BA-4EEC-4F29-A686-03D7F0DF39B8} = {DA4CBFCC-395C-4C21-8441-31FB0738E054}
{BEC7B5E6-0A7B-4824-97A7-EEA04D9EBA29} = {DA4CBFCC-395C-4C21-8441-31FB0738E054}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {FBF47D74-8A82-4F43-8D42-04E336207C0F}
Expand Down
Loading

0 comments on commit 570b726

Please sign in to comment.