Add more options to work with Scene Hierarchy (#23)

- Added option to group exported assets by node path in scene hierarchy
- Added field with node path to exported xml asset list
This commit is contained in:
VaDiM 2024-02-13 04:51:35 +03:00
parent c68eaa5e3c
commit 5c24183d18
9 changed files with 61 additions and 22 deletions

View File

@ -30,6 +30,8 @@ namespace AssetStudio
{ {
ClassIDType.AssetBundle, ClassIDType.AssetBundle,
ClassIDType.ResourceManager, ClassIDType.ResourceManager,
ClassIDType.GameObject,
ClassIDType.Transform,
}); });
} }

View File

@ -1,4 +1,3 @@
using AssetStudio;
using System.Collections.Generic; using System.Collections.Generic;
namespace AssetStudioCLI namespace AssetStudioCLI
@ -6,11 +5,12 @@ namespace AssetStudioCLI
internal class BaseNode internal class BaseNode
{ {
public List<BaseNode> nodes = new List<BaseNode>(); public List<BaseNode> nodes = new List<BaseNode>();
public string FullPath = "";
public readonly string Text;
public BaseNode() public BaseNode(string name)
{ {
Text = name;
} }
} }
} }

View File

@ -1,5 +1,4 @@
using AssetStudio; using AssetStudio;
using System.Collections.Generic;
namespace AssetStudioCLI namespace AssetStudioCLI
{ {
@ -7,10 +6,9 @@ namespace AssetStudioCLI
{ {
public GameObject gameObject; public GameObject gameObject;
public GameObjectNode(GameObject gameObject) public GameObjectNode(GameObject gameObject) : base(gameObject.m_Name)
{ {
this.gameObject = gameObject; this.gameObject = gameObject;
} }
} }
} }

View File

@ -277,7 +277,7 @@ namespace AssetStudioCLI
private static void ExportFbx(IImported convert, string exportPath) private static void ExportFbx(IImported convert, string exportPath)
{ {
var eulerFilter = true; var eulerFilter = true;
var filterPrecision = (float)0.25f; var filterPrecision = 0.25f;
var exportAllNodes = true; var exportAllNodes = true;
var exportSkins = true; var exportSkins = true;
var exportAnimations = true; var exportAnimations = true;

View File

@ -35,6 +35,7 @@ namespace AssetStudioCLI.Options
ContainerPath, ContainerPath,
ContainerPathFull, ContainerPathFull,
SourceFileName, SourceFileName,
SceneHierarchy,
} }
internal enum FilenameFormat internal enum FilenameFormat
@ -202,11 +203,12 @@ namespace AssetStudioCLI.Options
optionDefaultValue: AssetGroupOption.ContainerPath, optionDefaultValue: AssetGroupOption.ContainerPath,
optionName: "-g, --group-option <value>", optionName: "-g, --group-option <value>",
optionDescription: "Specify the way in which exported assets should be grouped\n" + optionDescription: "Specify the way in which exported assets should be grouped\n" +
"<Value: none | type | container(default) | containerFull | filename>\n" + "<Value: none | type | container(default) | containerFull | filename | sceneHierarchy>\n" +
"None - Do not group exported assets\n" + "None - Do not group exported assets\n" +
"Type - Group exported assets by type name\n" + "Type - Group exported assets by type name\n" +
"Container - Group exported assets by container path\n" + "Container - Group exported assets by container path\n" +
"ContainerFull - Group exported assets by full container path (e.g. with prefab name)\n" + "ContainerFull - Group exported assets by full container path (e.g. with prefab name)\n" +
"SceneHierarchy - Group exported assets by their node path in scene hierarchy\n" +
"Filename - Group exported assets by source file name\n", "Filename - Group exported assets by source file name\n",
optionExample: "Example: \"-g containerFull\"\n", optionExample: "Example: \"-g containerFull\"\n",
optionHelpGroup: HelpGroups.General optionHelpGroup: HelpGroups.General
@ -500,20 +502,16 @@ namespace AssetStudioCLI.Options
o_exportAssetTypes.Value = new List<ClassIDType>() o_exportAssetTypes.Value = new List<ClassIDType>()
{ {
ClassIDType.AnimationClip, ClassIDType.AnimationClip,
ClassIDType.GameObject,
ClassIDType.MonoBehaviour, ClassIDType.MonoBehaviour,
ClassIDType.Texture2D, ClassIDType.Texture2D,
ClassIDType.Transform,
}; };
break; break;
case "splitobjects": case "splitobjects":
o_workMode.Value = WorkMode.SplitObjects; o_workMode.Value = WorkMode.SplitObjects;
o_exportAssetTypes.Value = new List<ClassIDType>() o_exportAssetTypes.Value = new List<ClassIDType>()
{ {
ClassIDType.GameObject,
ClassIDType.Texture2D, ClassIDType.Texture2D,
ClassIDType.Material, ClassIDType.Material,
ClassIDType.Transform,
ClassIDType.Mesh, ClassIDType.Mesh,
ClassIDType.MeshRenderer, ClassIDType.MeshRenderer,
ClassIDType.MeshFilter, ClassIDType.MeshFilter,
@ -640,6 +638,9 @@ namespace AssetStudioCLI.Options
case "filename": case "filename":
o_groupAssetsBy.Value = AssetGroupOption.SourceFileName; o_groupAssetsBy.Value = AssetGroupOption.SourceFileName;
break; break;
case "scenehierarchy":
o_groupAssetsBy.Value = AssetGroupOption.SceneHierarchy;
break;
case "none": case "none":
o_groupAssetsBy.Value = AssetGroupOption.None; o_groupAssetsBy.Value = AssetGroupOption.None;
break; break;
@ -1051,6 +1052,7 @@ namespace AssetStudioCLI.Options
} }
sb.AppendLine(ShowExportTypes()); sb.AppendLine(ShowExportTypes());
sb.AppendLine($"# Asset Group Option: {o_groupAssetsBy}"); sb.AppendLine($"# Asset Group Option: {o_groupAssetsBy}");
sb.AppendLine($"# Filename format: {o_filenameFormat}");
if (o_workMode.Value == WorkMode.Export) if (o_workMode.Value == WorkMode.Export)
{ {
sb.AppendLine($"# Export Image Format: {o_imageFormat}"); sb.AppendLine($"# Export Image Format: {o_imageFormat}");

View File

@ -178,7 +178,7 @@ namespace AssetStudioCLI
} }
} }
if (CLIOptions.o_workMode.Value == WorkMode.SplitObjects) if (CLIOptions.o_workMode.Value == WorkMode.SplitObjects || CLIOptions.o_groupAssetsBy.Value == AssetGroupOption.SceneHierarchy)
{ {
BuildTreeStructure(objectAssetItemDic); BuildTreeStructure(objectAssetItemDic);
} }
@ -215,7 +215,7 @@ namespace AssetStudioCLI
Progress.Reset(); Progress.Reset();
foreach (var assetsFile in assetsManager.assetsFileList) foreach (var assetsFile in assetsManager.assetsFileList)
{ {
var fileNode = new BaseNode(); //RootNode var fileNode = new BaseNode(assetsFile.fileName); //RootNode
foreach (var obj in assetsFile.Objects) foreach (var obj in assetsFile.Objects)
{ {
@ -250,7 +250,6 @@ namespace AssetStudioCLI
} }
var parentNode = fileNode; var parentNode = fileNode;
if (m_GameObject.m_Transform != null) if (m_GameObject.m_Transform != null)
{ {
if (m_GameObject.m_Transform.m_Father.TryGet(out var m_Father)) if (m_GameObject.m_Transform.m_Father.TryGet(out var m_Father))
@ -266,14 +265,13 @@ namespace AssetStudioCLI
} }
} }
} }
parentNode.nodes.Add(currentNode); parentNode.nodes.Add(currentNode);
} }
} }
if (fileNode.nodes.Count > 0) if (fileNode.nodes.Count > 0)
{ {
GenerateFullPath(fileNode, fileNode.Text);
gameObjectTree.Add(fileNode); gameObjectTree.Add(fileNode);
} }
@ -284,6 +282,22 @@ namespace AssetStudioCLI
objectAssetItemDic.Clear(); objectAssetItemDic.Clear();
} }
private static void GenerateFullPath(BaseNode treeNode, string path)
{
treeNode.FullPath = path;
foreach (var node in treeNode.nodes)
{
if (node.nodes.Count > 0)
{
GenerateFullPath(node, Path.Combine(path, node.Text));
}
else
{
node.FullPath = Path.Combine(path, node.Text);
}
}
}
public static void ShowExportableAssetsInfo() public static void ShowExportableAssetsInfo()
{ {
var exportableAssetsCountDict = new Dictionary<ClassIDType, int>(); var exportableAssetsCountDict = new Dictionary<ClassIDType, int>();
@ -434,6 +448,16 @@ namespace AssetStudioCLI
exportPath = Path.Combine(savePath, Path.GetFileName(asset.SourceFile.originalPath) + "_export", asset.SourceFile.fileName); exportPath = Path.Combine(savePath, Path.GetFileName(asset.SourceFile.originalPath) + "_export", asset.SourceFile.fileName);
} }
break; break;
case AssetGroupOption.SceneHierarchy:
if (asset.Node != null)
{
exportPath = Path.Combine(savePath, asset.Node.FullPath);
}
else
{
exportPath = Path.Combine(savePath, "_sceneRoot", asset.TypeString);
}
break;
default: default:
exportPath = savePath; exportPath = savePath;
break; break;
@ -513,6 +537,7 @@ namespace AssetStudioCLI
new XElement("Type", new XAttribute("id", (int)asset.Type), asset.TypeString), new XElement("Type", new XAttribute("id", (int)asset.Type), asset.TypeString),
new XElement("PathID", asset.m_PathID), new XElement("PathID", asset.m_PathID),
new XElement("Source", asset.SourceFile.fullName), new XElement("Source", asset.SourceFile.fullName),
new XElement("TreeNode", asset.Node != null ? asset.Node.FullPath : ""),
new XElement("Size", asset.FullSize) new XElement("Size", asset.FullSize)
) )
) )
@ -544,7 +569,7 @@ namespace AssetStudioCLI
{ {
if (isFiltered) if (isFiltered)
{ {
if (!searchList.Any(searchText => j.gameObject.m_Name.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) >= 0)) if (!searchList.Any(searchText => j.Text.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) >= 0))
continue; continue;
} }
var gameObjects = new List<GameObject>(); var gameObjects = new List<GameObject>();

View File

@ -1948,7 +1948,7 @@ namespace AssetStudioGUI
private void clearSelectionToolStripMenuItem_Click(object sender, EventArgs e) private void clearSelectionToolStripMenuItem_Click(object sender, EventArgs e)
{ {
treeRecursionEnabled = false; treeRecursionEnabled = false;
for(var i = 0; i < treeNodeSelectedList.Count; i++) for (var i = 0; i < treeNodeSelectedList.Count; i++)
{ {
treeNodeSelectedList[i].Checked = false; treeNodeSelectedList[i].Checked = false;
} }

View File

@ -191,6 +191,7 @@
"container path", "container path",
"container path full (with name)", "container path full (with name)",
"source file name", "source file name",
"scene hierarchy",
"do not group"}); "do not group"});
this.assetGroupOptions.Location = new System.Drawing.Point(6, 35); this.assetGroupOptions.Location = new System.Drawing.Point(6, 35);
this.assetGroupOptions.Name = "assetGroupOptions"; this.assetGroupOptions.Name = "assetGroupOptions";

View File

@ -47,7 +47,8 @@ namespace AssetStudioGUI
TypeName, TypeName,
ContainerPath, ContainerPath,
ContainerPathFull, ContainerPathFull,
SourceFileName SourceFileName,
SceneHierarchy,
} }
internal enum ListSearchFilterMode internal enum ListSearchFilterMode
@ -384,7 +385,6 @@ namespace AssetStudioGUI
} }
} }
} }
parentNode.Nodes.Add(currentNode); parentNode.Nodes.Add(currentNode);
} }
} }
@ -481,6 +481,16 @@ namespace AssetStudioGUI
exportPath = Path.Combine(savePath, Path.GetFileName(asset.SourceFile.originalPath) + "_export", asset.SourceFile.fileName); exportPath = Path.Combine(savePath, Path.GetFileName(asset.SourceFile.originalPath) + "_export", asset.SourceFile.fileName);
} }
break; break;
case AssetGroupOption.SceneHierarchy:
if (asset.TreeNode != null)
{
exportPath = Path.Combine(savePath, asset.TreeNode.FullPath);
}
else
{
exportPath = Path.Combine(savePath, "_sceneRoot", asset.TypeString);
}
break;
default: default:
exportPath = savePath; exportPath = savePath;
break; break;
@ -559,6 +569,7 @@ namespace AssetStudioGUI
new XElement("Type", new XAttribute("id", (int)asset.Type), asset.TypeString), new XElement("Type", new XAttribute("id", (int)asset.Type), asset.TypeString),
new XElement("PathID", asset.m_PathID), new XElement("PathID", asset.m_PathID),
new XElement("Source", asset.SourceFile.fullName), new XElement("Source", asset.SourceFile.fullName),
new XElement("TreeNode", asset.TreeNode != null ? asset.TreeNode.FullPath : ""),
new XElement("Size", asset.FullSize) new XElement("Size", asset.FullSize)
) )
) )