mirror of
https://github.com/aelurum/AssetStudio.git
synced 2025-05-25 05:40:21 -04:00
Some improvements
This commit is contained in:
parent
906149a58a
commit
de464dfe10
@ -14,9 +14,7 @@ using System.Drawing.Text;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics.OpenGL;
|
||||
using static AssetStudio.Studio;
|
||||
using static AssetStudio.FBXExporter;
|
||||
using static AssetStudio.Importer;
|
||||
using static AssetStudio.SpriteHelper;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
@ -996,7 +994,7 @@ namespace AssetStudio
|
||||
case ClassIDReference.Sprite:
|
||||
{
|
||||
imageTexture?.Dispose();
|
||||
imageTexture = GetImageFromSprite(asset);
|
||||
imageTexture = SpriteHelper.GetImageFromSprite(asset);
|
||||
if (imageTexture != null)
|
||||
{
|
||||
previewPanel.BackgroundImage = imageTexture;
|
||||
@ -1311,64 +1309,18 @@ namespace AssetStudio
|
||||
var saveFolderDialog1 = new OpenFolderDialog();
|
||||
if (saveFolderDialog1.ShowDialog(this) == DialogResult.OK)
|
||||
{
|
||||
var savePath = saveFolderDialog1.Folder;
|
||||
savePath = savePath + "\\";
|
||||
switch ((bool)Properties.Settings.Default["showExpOpt"])
|
||||
var savePath = saveFolderDialog1.Folder + "\\";
|
||||
|
||||
if ((bool)Properties.Settings.Default["showExpOpt"])
|
||||
{
|
||||
case true:
|
||||
ExportOptions exportOpt = new ExportOptions();
|
||||
if (exportOpt.ShowDialog() == DialogResult.OK) { goto case false; }
|
||||
break;
|
||||
case false:
|
||||
{
|
||||
progressBar1.Value = 0;
|
||||
progressBar1.Maximum = sceneTreeView.Nodes.Count;
|
||||
//防止主界面假死
|
||||
ThreadPool.QueueUserWorkItem(state =>
|
||||
{
|
||||
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
|
||||
sceneTreeView.Invoke(new Action(() =>
|
||||
{
|
||||
//挂起控件防止更新
|
||||
sceneTreeView.BeginUpdate();
|
||||
//先取消所有Node的选中
|
||||
foreach (TreeNode i in sceneTreeView.Nodes)
|
||||
{
|
||||
i.Checked = false;
|
||||
}
|
||||
}));
|
||||
//遍历根节点
|
||||
foreach (TreeNode i in sceneTreeView.Nodes)
|
||||
{
|
||||
if (i.Nodes.Count > 0)
|
||||
{
|
||||
//遍历一级子节点
|
||||
foreach (TreeNode j in i.Nodes)
|
||||
{
|
||||
//加上时间,因为可能有重名的object
|
||||
var filename = j.Text + DateTime.Now.ToString("_mm_ss_ffff");
|
||||
//选中它和它的子节点
|
||||
sceneTreeView.Invoke(new Action(() => j.Checked = true));
|
||||
//处理非法文件名
|
||||
filename = FixFileName(filename);
|
||||
//导出FBX
|
||||
WriteFBX(savePath + filename + ".fbx", false);
|
||||
//取消选中
|
||||
sceneTreeView.Invoke(new Action(() => j.Checked = false));
|
||||
}
|
||||
}
|
||||
ProgressBarPerformStep();
|
||||
}
|
||||
//取消挂起
|
||||
sceneTreeView.Invoke(new Action(() => sceneTreeView.EndUpdate()));
|
||||
if (openAfterExport.Checked)
|
||||
{
|
||||
Process.Start(savePath);
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
var exportOpt = new ExportOptions();
|
||||
exportOpt.ShowDialog();
|
||||
}
|
||||
|
||||
progressBar1.Value = 0;
|
||||
progressBar1.Maximum = sceneTreeView.Nodes.Count;
|
||||
|
||||
ThreadPool.QueueUserWorkItem(state => ExportSplitObjects(savePath, sceneTreeView.Nodes));
|
||||
}
|
||||
|
||||
}
|
||||
@ -1382,36 +1334,49 @@ namespace AssetStudio
|
||||
{
|
||||
if (sceneTreeView.Nodes.Count > 0)
|
||||
{
|
||||
var exportSwitch = ((ToolStripItem)sender).Name == "exportallobjectsMenuItem";
|
||||
var exportAll = ((ToolStripItem)sender).Name == "exportallobjectsMenuItem";
|
||||
|
||||
saveFileDialog1.FileName = productName + DateTime.Now.ToString("_yy_MM_dd__HH_mm_ss");
|
||||
|
||||
if (saveFileDialog1.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
switch ((bool)Properties.Settings.Default["showExpOpt"])
|
||||
if ((bool)Properties.Settings.Default["showExpOpt"])
|
||||
{
|
||||
case true:
|
||||
ExportOptions exportOpt = new ExportOptions();
|
||||
if (exportOpt.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
goto case false;
|
||||
}
|
||||
break;
|
||||
case false:
|
||||
WriteFBX(saveFileDialog1.FileName, exportSwitch);
|
||||
var exportOpt = new ExportOptions();
|
||||
exportOpt.ShowDialog();
|
||||
}
|
||||
|
||||
if (openAfterExport.Checked && File.Exists(saveFileDialog1.FileName))
|
||||
var gameObjects = new List<GameObject>();
|
||||
foreach (var assetsFile in assetsfileList)
|
||||
{
|
||||
foreach (var m_GameObject in assetsFile.GameObjectList.Values)
|
||||
{
|
||||
if (m_GameObject.Checked || exportAll)
|
||||
{
|
||||
Process.Start(Path.GetDirectoryName(saveFileDialog1.FileName));
|
||||
gameObjects.Add(m_GameObject);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
progressBar1.Value = 0;
|
||||
progressBar1.Maximum = 1;
|
||||
if (gameObjects.Count == 0)
|
||||
{
|
||||
progressBar1.PerformStep();
|
||||
toolStripStatusLabel1.Text = "Nothing exported.";
|
||||
return;
|
||||
}
|
||||
FBXExporter.WriteFBX(saveFileDialog1.FileName, gameObjects);
|
||||
progressBar1.PerformStep();
|
||||
if (openAfterExport.Checked && File.Exists(saveFileDialog1.FileName))
|
||||
{
|
||||
Process.Start(Path.GetDirectoryName(saveFileDialog1.FileName));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
StatusStripUpdate("No Objects available for export");
|
||||
toolStripStatusLabel1.Text = "No Objects available for export";
|
||||
}
|
||||
}
|
||||
|
||||
@ -1726,7 +1691,7 @@ namespace AssetStudio
|
||||
secondSortColumn = 0;
|
||||
reverseSort = false;
|
||||
enableFiltering = false;
|
||||
|
||||
listSearch.Text = " Filter ";
|
||||
FMODreset();
|
||||
}
|
||||
|
||||
|
@ -684,6 +684,8 @@ namespace AssetStudio
|
||||
else
|
||||
{
|
||||
m_AnimationType = reader.ReadInt32();
|
||||
if (m_AnimationType == 1)
|
||||
m_Legacy = true;
|
||||
}
|
||||
m_Compressed = reader.ReadBoolean();
|
||||
m_UseHighQualityCurve = reader.ReadBoolean();
|
||||
|
@ -5,7 +5,6 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using static AssetStudio.SpriteHelper;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
@ -13,9 +12,10 @@ namespace AssetStudio
|
||||
{
|
||||
public static bool ExportTexture2D(AssetPreloadData asset, string exportPathName, bool flip)
|
||||
{
|
||||
var m_Texture2D = new Texture2DConverter(new Texture2D(asset, true));
|
||||
if (m_Texture2D.image_data == null)
|
||||
var texture2D = new Texture2D(asset, true);
|
||||
if (texture2D.image_data == null || texture2D.image_data.Length == 0)
|
||||
return false;
|
||||
var m_Texture2D = new Texture2DConverter(texture2D);
|
||||
var convert = (bool)Properties.Settings.Default["convertTexture"];
|
||||
var bitmap = m_Texture2D.ConvertToBitmap(flip);
|
||||
if (convert && bitmap != null)
|
||||
@ -287,7 +287,7 @@ namespace AssetStudio
|
||||
var exportFullName = exportPath + asset.Text + "." + type.ToLower();
|
||||
if (ExportFileExists(exportFullName))
|
||||
return false;
|
||||
var bitmap = GetImageFromSprite(asset);
|
||||
var bitmap = SpriteHelper.GetImageFromSprite(asset);
|
||||
if (bitmap != null)
|
||||
{
|
||||
bitmap.Save(exportFullName, format);
|
||||
@ -349,7 +349,7 @@ namespace AssetStudio
|
||||
var boneSize = (int)(decimal)Properties.Settings.Default["boneSize"];
|
||||
var flatInbetween = (bool)Properties.Settings.Default["flatInbetween"];
|
||||
var compatibility = (bool)Properties.Settings.Default["compatibility"];
|
||||
Fbx.Exporter.Export(exportPath, convert, EulerFilter, filterPrecision, ".fbx", allFrames, allBones, skins, boneSize, flatInbetween, compatibility);
|
||||
Fbx.Exporter.Export(exportPath, convert, EulerFilter, filterPrecision, allFrames, allBones, skins, boneSize, flatInbetween, compatibility);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ namespace AssetStudio
|
||||
{
|
||||
static class FBXExporter
|
||||
{
|
||||
public static void WriteFBX(string FBXfile, bool allNodes)
|
||||
public static void WriteFBX(string FBXfile, List<GameObject> gameObjects)
|
||||
{
|
||||
var timestamp = DateTime.Now;
|
||||
|
||||
@ -47,105 +47,99 @@ namespace AssetStudio
|
||||
*/
|
||||
|
||||
#region loop nodes and collect objects for export
|
||||
foreach (var assetsFile in assetsfileList)
|
||||
foreach (var m_GameObject in gameObjects)
|
||||
{
|
||||
foreach (var m_GameObject in assetsFile.GameObjectList.Values)
|
||||
GameObjects.Add(m_GameObject);
|
||||
|
||||
if (assetsfileList.TryGetPD(m_GameObject.m_MeshFilter, out var MeshFilterPD))
|
||||
{
|
||||
if (m_GameObject.Checked || allNodes)
|
||||
//MeshFilters are not unique!
|
||||
//MeshFilters.Add(MeshFilterPD);
|
||||
MeshFilter m_MeshFilter = new MeshFilter(MeshFilterPD);
|
||||
if (assetsfileList.TryGetPD(m_MeshFilter.m_Mesh, out var MeshPD))
|
||||
{
|
||||
GameObjects.Add(m_GameObject);
|
||||
Meshes.Add(MeshPD);
|
||||
|
||||
if (assetsfileList.TryGetPD(m_GameObject.m_MeshFilter, out var MeshFilterPD))
|
||||
{
|
||||
//MeshFilters are not unique!
|
||||
//MeshFilters.Add(MeshFilterPD);
|
||||
MeshFilter m_MeshFilter = new MeshFilter(MeshFilterPD);
|
||||
if (assetsfileList.TryGetPD(m_MeshFilter.m_Mesh, out var MeshPD))
|
||||
{
|
||||
Meshes.Add(MeshPD);
|
||||
|
||||
//write connections here and Mesh objects separately without having to backtrack through their MEshFilter to het the GameObject ID
|
||||
//also note that MeshFilters are not unique, they cannot be used for instancing geometry
|
||||
cb2.AppendFormat("\n\n\t;Geometry::, Model::{0}", m_GameObject.m_Name);
|
||||
cb2.AppendFormat("\n\tC: \"OO\",3{0},1{1}", MeshPD.uniqueID, m_GameObject.uniqueID);
|
||||
}
|
||||
}
|
||||
|
||||
#region get Renderer
|
||||
if (assetsfileList.TryGetPD(m_GameObject.m_MeshRenderer, out var RendererPD))
|
||||
{
|
||||
MeshRenderer m_Renderer = new MeshRenderer(RendererPD);
|
||||
|
||||
foreach (var MaterialPPtr in m_Renderer.m_Materials)
|
||||
{
|
||||
if (assetsfileList.TryGetPD(MaterialPPtr, out var MaterialPD))
|
||||
{
|
||||
Materials.Add(MaterialPD);
|
||||
cb2.AppendFormat("\n\n\t;Material::, Model::{0}", m_GameObject.m_Name);
|
||||
cb2.AppendFormat("\n\tC: \"OO\",6{0},1{1}", MaterialPD.uniqueID, m_GameObject.uniqueID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region get SkinnedMeshRenderer
|
||||
if (assetsfileList.TryGetPD(m_GameObject.m_SkinnedMeshRenderer, out var SkinnedMeshPD))
|
||||
{
|
||||
Skins.Add(SkinnedMeshPD);
|
||||
|
||||
SkinnedMeshRenderer m_SkinnedMeshRenderer = new SkinnedMeshRenderer(SkinnedMeshPD);
|
||||
|
||||
foreach (var MaterialPPtr in m_SkinnedMeshRenderer.m_Materials)
|
||||
{
|
||||
if (assetsfileList.TryGetPD(MaterialPPtr, out var MaterialPD))
|
||||
{
|
||||
Materials.Add(MaterialPD);
|
||||
cb2.AppendFormat("\n\n\t;Material::, Model::{0}", m_GameObject.m_Name);
|
||||
cb2.AppendFormat("\n\tC: \"OO\",6{0},1{1}", MaterialPD.uniqueID, m_GameObject.uniqueID);
|
||||
}
|
||||
}
|
||||
|
||||
if ((bool)Properties.Settings.Default["exportDeformers"])
|
||||
{
|
||||
DeformerCount += m_SkinnedMeshRenderer.m_Bones.Length;
|
||||
|
||||
//collect skeleton dummies to make sure they are exported
|
||||
foreach (var bonePPtr in m_SkinnedMeshRenderer.m_Bones)
|
||||
{
|
||||
if (assetsfileList.TryGetTransform(bonePPtr, out var b_Transform))
|
||||
{
|
||||
if (assetsfileList.TryGetGameObject(b_Transform.m_GameObject, out var m_Bone))
|
||||
{
|
||||
LimbNodes.Add(m_Bone);
|
||||
//also collect the root bone
|
||||
if (m_Bone.Parent.Level > 0) { LimbNodes.Add((GameObject)m_Bone.Parent); }
|
||||
//should I collect siblings?
|
||||
}
|
||||
|
||||
#region collect children because m_SkinnedMeshRenderer.m_Bones doesn't contain terminations
|
||||
foreach (var ChildPPtr in b_Transform.m_Children)
|
||||
{
|
||||
if (assetsfileList.TryGetTransform(ChildPPtr, out var ChildTR))
|
||||
{
|
||||
if (assetsfileList.TryGetGameObject(ChildTR.m_GameObject, out var m_Child))
|
||||
{
|
||||
//check that the Model doesn't contain a Mesh, although this won't ensure it's part of the skeleton
|
||||
if (m_Child.m_MeshFilter == null && m_Child.m_SkinnedMeshRenderer == null)
|
||||
{
|
||||
LimbNodes.Add(m_Child);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
//write connections here and Mesh objects separately without having to backtrack through their MEshFilter to het the GameObject ID
|
||||
//also note that MeshFilters are not unique, they cannot be used for instancing geometry
|
||||
cb2.AppendFormat("\n\n\t;Geometry::, Model::{0}", m_GameObject.m_Name);
|
||||
cb2.AppendFormat("\n\tC: \"OO\",3{0},1{1}", MeshPD.uniqueID, m_GameObject.uniqueID);
|
||||
}
|
||||
}
|
||||
|
||||
#region get Renderer
|
||||
if (assetsfileList.TryGetPD(m_GameObject.m_MeshRenderer, out var RendererPD))
|
||||
{
|
||||
MeshRenderer m_Renderer = new MeshRenderer(RendererPD);
|
||||
|
||||
foreach (var MaterialPPtr in m_Renderer.m_Materials)
|
||||
{
|
||||
if (assetsfileList.TryGetPD(MaterialPPtr, out var MaterialPD))
|
||||
{
|
||||
Materials.Add(MaterialPD);
|
||||
cb2.AppendFormat("\n\n\t;Material::, Model::{0}", m_GameObject.m_Name);
|
||||
cb2.AppendFormat("\n\tC: \"OO\",6{0},1{1}", MaterialPD.uniqueID, m_GameObject.uniqueID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region get SkinnedMeshRenderer
|
||||
if (assetsfileList.TryGetPD(m_GameObject.m_SkinnedMeshRenderer, out var SkinnedMeshPD))
|
||||
{
|
||||
Skins.Add(SkinnedMeshPD);
|
||||
|
||||
SkinnedMeshRenderer m_SkinnedMeshRenderer = new SkinnedMeshRenderer(SkinnedMeshPD);
|
||||
|
||||
foreach (var MaterialPPtr in m_SkinnedMeshRenderer.m_Materials)
|
||||
{
|
||||
if (assetsfileList.TryGetPD(MaterialPPtr, out var MaterialPD))
|
||||
{
|
||||
Materials.Add(MaterialPD);
|
||||
cb2.AppendFormat("\n\n\t;Material::, Model::{0}", m_GameObject.m_Name);
|
||||
cb2.AppendFormat("\n\tC: \"OO\",6{0},1{1}", MaterialPD.uniqueID, m_GameObject.uniqueID);
|
||||
}
|
||||
}
|
||||
|
||||
if ((bool)Properties.Settings.Default["exportDeformers"])
|
||||
{
|
||||
DeformerCount += m_SkinnedMeshRenderer.m_Bones.Length;
|
||||
|
||||
//collect skeleton dummies to make sure they are exported
|
||||
foreach (var bonePPtr in m_SkinnedMeshRenderer.m_Bones)
|
||||
{
|
||||
if (assetsfileList.TryGetTransform(bonePPtr, out var b_Transform))
|
||||
{
|
||||
if (assetsfileList.TryGetGameObject(b_Transform.m_GameObject, out var m_Bone))
|
||||
{
|
||||
LimbNodes.Add(m_Bone);
|
||||
//also collect the root bone
|
||||
if (m_Bone.Parent.Level > 0) { LimbNodes.Add((GameObject)m_Bone.Parent); }
|
||||
//should I collect siblings?
|
||||
}
|
||||
|
||||
#region collect children because m_SkinnedMeshRenderer.m_Bones doesn't contain terminations
|
||||
foreach (var ChildPPtr in b_Transform.m_Children)
|
||||
{
|
||||
if (assetsfileList.TryGetTransform(ChildPPtr, out var ChildTR))
|
||||
{
|
||||
if (assetsfileList.TryGetGameObject(ChildTR.m_GameObject, out var m_Child))
|
||||
{
|
||||
//check that the Model doesn't contain a Mesh, although this won't ensure it's part of the skeleton
|
||||
if (m_Child.m_MeshFilter == null && m_Child.m_SkinnedMeshRenderer == null)
|
||||
{
|
||||
LimbNodes.Add(m_Child);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
//if ((bool)Properties.Settings.Default["convertDummies"]) { GameObjects.Except(LimbNodes); }
|
||||
|
@ -9,10 +9,6 @@ using static AssetStudio.Studio;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
/* TODO Handle all things in one loop
|
||||
* Init with GameObject
|
||||
* Other optimization
|
||||
*/
|
||||
class ModelConverter : IImported
|
||||
{
|
||||
public List<ImportedFrame> FrameList { get; protected set; } = new List<ImportedFrame>();
|
||||
@ -81,7 +77,6 @@ namespace AssetStudio
|
||||
|
||||
CreateBonePathHash(rootTransform);
|
||||
ConvertFrames(rootTransform, null);
|
||||
CollectMorphInfo(rootTransform);
|
||||
ConvertMeshRenderer(m_Transform);
|
||||
}
|
||||
|
||||
@ -92,21 +87,21 @@ namespace AssetStudio
|
||||
{
|
||||
if (assetsfileList.TryGetPD(m_Component, out var assetPreloadData))
|
||||
{
|
||||
switch (assetPreloadData.Type2)
|
||||
switch (assetPreloadData.Type)
|
||||
{
|
||||
case 23: //MeshRenderer
|
||||
case ClassIDReference.MeshRenderer:
|
||||
{
|
||||
var m_Renderer = new MeshRenderer(assetPreloadData);
|
||||
ConvertMeshRenderer(m_Renderer);
|
||||
break;
|
||||
}
|
||||
case 137: //SkinnedMeshRenderer
|
||||
case ClassIDReference.SkinnedMeshRenderer:
|
||||
{
|
||||
var m_SkinnedMeshRenderer = new SkinnedMeshRenderer(assetPreloadData);
|
||||
ConvertMeshRenderer(m_SkinnedMeshRenderer);
|
||||
break;
|
||||
}
|
||||
case 111: //Animation
|
||||
case ClassIDReference.Animation:
|
||||
{
|
||||
var m_Animation = new Animation(assetPreloadData);
|
||||
foreach (var animation in m_Animation.m_Animations)
|
||||
@ -132,7 +127,7 @@ namespace AssetStudio
|
||||
{
|
||||
if (assetsfileList.TryGetPD(m_Animator.m_Controller, out var assetPreloadData))
|
||||
{
|
||||
if (assetPreloadData.Type2 == 221)//AnimatorOverrideController
|
||||
if (assetPreloadData.Type == ClassIDReference.AnimatorOverrideController)
|
||||
{
|
||||
var m_AnimatorOverrideController = new AnimatorOverrideController(assetPreloadData);
|
||||
if (assetsfileList.TryGetPD(m_AnimatorOverrideController.m_Controller, out assetPreloadData))
|
||||
@ -154,7 +149,7 @@ namespace AssetStudio
|
||||
}
|
||||
}*/
|
||||
}
|
||||
else if (assetPreloadData.Type2 == 91)//AnimatorController
|
||||
else if (assetPreloadData.Type == ClassIDReference.AnimatorController)
|
||||
{
|
||||
var m_AnimatorController = new AnimatorController(assetPreloadData);
|
||||
foreach (var m_AnimationClip in m_AnimatorController.m_AnimationClips)
|
||||
@ -196,30 +191,6 @@ namespace AssetStudio
|
||||
}
|
||||
}
|
||||
|
||||
private void CollectMorphInfo(Transform m_Transform)
|
||||
{
|
||||
assetsfileList.TryGetGameObject(m_Transform.m_GameObject, out var m_GameObject);
|
||||
if (assetsfileList.TryGetPD(m_GameObject.m_SkinnedMeshRenderer, out var assetPreloadData))
|
||||
{
|
||||
var m_SkinnedMeshRenderer = new SkinnedMeshRenderer(assetPreloadData);
|
||||
if (assetsfileList.TryGetPD(m_SkinnedMeshRenderer.m_Mesh, out var MeshPD))
|
||||
{
|
||||
var mesh = new Mesh(MeshPD, true);
|
||||
foreach (var channel in mesh.m_Shapes.channels)
|
||||
{
|
||||
morphChannelInfo.Add(channel.nameHash, channel.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var pptr in m_Transform.m_Children)
|
||||
{
|
||||
if (assetsfileList.TryGetTransform(pptr, out var child))
|
||||
CollectMorphInfo(child);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void ConvertMeshRenderer(MeshRenderer meshR)
|
||||
{
|
||||
var mesh = GetMesh(meshR);
|
||||
@ -375,6 +346,10 @@ namespace AssetStudio
|
||||
}
|
||||
|
||||
//Morphs
|
||||
foreach (var channel in mesh.m_Shapes.channels)
|
||||
{
|
||||
morphChannelInfo.Add(channel.nameHash, channel.name);
|
||||
}
|
||||
if (mesh.m_Shapes.shapes.Count > 0)
|
||||
{
|
||||
ImportedMorph morph = null;
|
||||
@ -446,7 +421,7 @@ namespace AssetStudio
|
||||
{
|
||||
if (assetsfileList.TryGetPD(m_Component, out var assetPreloadData))
|
||||
{
|
||||
if (assetPreloadData.Type2 == 33) //MeshFilter
|
||||
if (assetPreloadData.Type == ClassIDReference.MeshFilter)
|
||||
{
|
||||
var m_MeshFilter = new MeshFilter(assetPreloadData);
|
||||
if (assetsfileList.TryGetPD(m_MeshFilter.m_Mesh, out var MeshPD))
|
||||
@ -529,7 +504,7 @@ namespace AssetStudio
|
||||
foreach (var texEnv in mat.m_TexEnvs)
|
||||
{
|
||||
Texture2D tex2D = null;
|
||||
if (assetsfileList.TryGetPD(texEnv.m_Texture, out var TexturePD) && TexturePD.Type2 == 28)//TODO other Texture
|
||||
if (assetsfileList.TryGetPD(texEnv.m_Texture, out var TexturePD) && TexturePD.Type == ClassIDReference.Texture2D)//TODO other Texture
|
||||
{
|
||||
tex2D = new Texture2D(TexturePD, true);
|
||||
}
|
||||
|
@ -11,12 +11,8 @@ namespace AssetStudio
|
||||
{
|
||||
static class SpriteHelper
|
||||
{
|
||||
private static Dictionary<AssetPreloadData, Bitmap> spriteCache = new Dictionary<AssetPreloadData, Bitmap>();
|
||||
|
||||
public static Bitmap GetImageFromSprite(AssetPreloadData asset)
|
||||
{
|
||||
if (spriteCache.TryGetValue(asset, out var bitmap))
|
||||
return (Bitmap)bitmap.Clone();
|
||||
var m_Sprite = new Sprite(asset, true);
|
||||
if (assetsfileList.TryGetPD(m_Sprite.m_SpriteAtlas, out var assetPreloadData))
|
||||
{
|
||||
@ -51,8 +47,7 @@ namespace AssetStudio
|
||||
asset.InfoText = $"Width: {textureRect.Width}\nHeight: {textureRect.Height}\n" + info;
|
||||
var spriteImage = originalImage.Clone(textureRect, PixelFormat.Format32bppArgb);
|
||||
spriteImage.RotateFlip(RotateFlipType.RotateNoneFlipY);
|
||||
spriteCache.Add(asset, spriteImage);
|
||||
return (Bitmap)spriteImage.Clone();
|
||||
return spriteImage;
|
||||
}
|
||||
}
|
||||
|
||||
@ -87,8 +82,7 @@ namespace AssetStudio
|
||||
{
|
||||
graphic.FillPath(brush, path);
|
||||
bitmap.RotateFlip(RotateFlipType.RotateNoneFlipY);
|
||||
spriteCache.Add(asset, bitmap);
|
||||
return (Bitmap)bitmap.Clone();
|
||||
return bitmap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -506,6 +506,52 @@ namespace AssetStudio
|
||||
});
|
||||
}
|
||||
|
||||
public static void ExportSplitObjects(string savePath, TreeNodeCollection nodes)
|
||||
{
|
||||
foreach (TreeNode node in nodes)
|
||||
{
|
||||
//遍历一级子节点
|
||||
foreach (TreeNode j in node.Nodes)
|
||||
{
|
||||
//收集所有子节点
|
||||
var gameObjects = new List<GameObject>();
|
||||
CollectNode(j, gameObjects);
|
||||
//跳过一些不需要导出的object
|
||||
if (gameObjects.All(x => x.m_SkinnedMeshRenderer == null && x.m_MeshFilter == null))
|
||||
continue;
|
||||
//处理非法文件名
|
||||
var filename = FixFileName(j.Text);
|
||||
//每个文件单独文件夹
|
||||
var saveName = $"{savePath}{filename}\\{filename}.fbx";
|
||||
//重名文件处理
|
||||
for (int i = 1; ; i++)
|
||||
{
|
||||
if (File.Exists(saveName))
|
||||
{
|
||||
saveName = $"{savePath}{filename} ({i})\\{filename}.fbx";
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(saveName));
|
||||
//导出FBX
|
||||
FBXExporter.WriteFBX(saveName, gameObjects);
|
||||
}
|
||||
ProgressBarPerformStep();
|
||||
}
|
||||
}
|
||||
|
||||
private static void CollectNode(TreeNode node, List<GameObject> gameObjects)
|
||||
{
|
||||
gameObjects.Add((GameObject)node);
|
||||
foreach (TreeNode i in node.Nodes)
|
||||
{
|
||||
CollectNode(i, gameObjects);
|
||||
}
|
||||
}
|
||||
|
||||
public static void ExportAnimatorWithAnimationClip(AssetPreloadData animator, List<AssetPreloadData> animationList, string exportPath)
|
||||
{
|
||||
ThreadPool.QueueUserWorkItem(state =>
|
||||
|
@ -78,7 +78,6 @@
|
||||
<ClCompile Include="AssemblyInfo.cpp" />
|
||||
<ClCompile Include="AssetStudioFBX.cpp" />
|
||||
<ClCompile Include="AssetStudioFBXExporter.cpp" />
|
||||
<ClCompile Include="ImportedFBXExporter.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="AssetStudioFBX.h" />
|
||||
|
@ -36,8 +36,8 @@ namespace AssetStudio {
|
||||
ref class Exporter
|
||||
{
|
||||
public:
|
||||
static void Export(String^ path, IImported^ imported, bool EulerFilter, float filterPrecision, String^ exportFormat, bool allFrames, bool allBones, bool skins, float boneSize, bool flatInbetween, bool compatibility);
|
||||
static void ExportMorph(String^ path, IImported^ imported, String^ exportFormat, bool morphMask, bool flatInbetween, bool skins, float boneSize, bool compatibility);
|
||||
static void Export(String^ path, IImported^ imported, bool EulerFilter, float filterPrecision, bool allFrames, bool allBones, bool skins, float boneSize, bool flatInbetween, bool compatibility);
|
||||
static void ExportMorph(String^ path, IImported^ imported, bool morphMask, bool flatInbetween, bool skins, float boneSize, bool compatibility);
|
||||
|
||||
private:
|
||||
HashSet<String^>^ frameNames;
|
||||
@ -56,11 +56,10 @@ namespace AssetStudio {
|
||||
FbxArray<FbxNode*>* pMeshNodes;
|
||||
|
||||
~Exporter();
|
||||
!Exporter();
|
||||
void Fbx::Exporter::LinkTexture(ImportedMaterial^ mat, int attIndex, FbxFileTexture* pTexture, FbxProperty& prop);
|
||||
void SetJointsNode(FbxNode* pNode, HashSet<String^>^ boneNames, bool allBones);
|
||||
|
||||
Exporter(String^ path, IImported^ imported, String^ exportFormat, bool allFrames, bool allBones, bool skins, float boneSize, bool compatibility, bool normals);
|
||||
Exporter(String^ path, IImported^ imported, bool allFrames, bool allBones, bool skins, float boneSize, bool compatibility, bool normals);
|
||||
HashSet<String^>^ SearchHierarchy();
|
||||
void SearchHierarchy(ImportedFrame^ frame, HashSet<String^>^ exportFrames);
|
||||
void SetJointsFromImportedMeshes(bool allBones);
|
||||
|
@ -78,7 +78,6 @@
|
||||
<ClCompile Include="AssemblyInfo.cpp" />
|
||||
<ClCompile Include="AssetStudioFBX.cpp" />
|
||||
<ClCompile Include="AssetStudioFBXExporter.cpp" />
|
||||
<ClCompile Include="ImportedFBXExporter.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="AssetStudioFBX.h" />
|
||||
|
@ -14,9 +14,6 @@
|
||||
<ClCompile Include="AssemblyInfo.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ImportedFBXExporter.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="AssetStudioFBX.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user