diff --git a/AssetEditor.sln b/AssetEditor.sln index db0832a5..87400473 100644 --- a/AssetEditor.sln +++ b/AssetEditor.sln @@ -174,6 +174,7 @@ Global {8494EA8F-DBD8-4E4C-880C-7401CE2FB240} = {CED3D0A1-90C6-4F8F-9BD4-2274D79331B4} {D7225D7F-87E4-4FAD-A3BE-9165DFDC315E} = {07AC615B-A8FC-4E1A-BDD5-BC11452429A0} {D29AB45B-3CFD-4994-BD54-CE301704D6CA} = {CED3D0A1-90C6-4F8F-9BD4-2274D79331B4} + {7070A990-1A62-46A9-ABDF-BE030E3A4336} = {CED3D0A1-90C6-4F8F-9BD4-2274D79331B4} {D0F5B9E7-B545-41BF-AA8C-7E1923D35132} = {7070A990-1A62-46A9-ABDF-BE030E3A4336} {E5F640D6-A970-446E-9DCD-71698B95C3AF} = {7070A990-1A62-46A9-ABDF-BE030E3A4336} {D1F5CA6C-DD76-487F-AF31-22B1A71B294C} = {7070A990-1A62-46A9-ABDF-BE030E3A4336} diff --git a/Editors/ImportExportEditor/Editors.ImportExport/Common/VectorConverter.cs b/Editors/ImportExportEditor/Editors.ImportExport/Common/VectorConverter.cs new file mode 100644 index 00000000..296752e7 --- /dev/null +++ b/Editors/ImportExportEditor/Editors.ImportExport/Common/VectorConverter.cs @@ -0,0 +1,30 @@ +using System.Numerics; + +namespace Editors.ImportExport.Common +{ + class VecConv + { + public static Vector4 NormalizeTangentVector4(Vector4 tangent) + { + // normalize only the xyz components of the tangent, the w component is the handedness (1 or -1) in sharpGLTF + var tempTangent = Vector3.Normalize(new Vector3(tangent.X, tangent.Y, tangent.Z)); + return new Vector4(tempTangent.X, tempTangent.Y, tempTangent.Z, tangent.W); + } + + public static Quaternion GetSys(Microsoft.Xna.Framework.Quaternion q) => new Quaternion(q.X, q.Y, q.Z, q.W); + public static Vector4 GetSys(Microsoft.Xna.Framework.Vector4 v) => new Vector4(v.X, v.Y, v.Z, v.W); + public static Vector3 GetSys(Microsoft.Xna.Framework.Vector3 v) => new Vector3(v.X, v.Y, v.Z); + public static Microsoft.Xna.Framework.Vector4 GetXna(Vector4 v) => new Microsoft.Xna.Framework.Vector4(v.X, v.Y, v.Z, v.W); + public static Microsoft.Xna.Framework.Vector3 GetXna(Vector3 v) => new Microsoft.Xna.Framework.Vector3(v.X, v.Y, v.Z); + public static Microsoft.Xna.Framework.Vector2 GetXna(Vector2 v) => new Microsoft.Xna.Framework.Vector2(v.X, v.Y); + public static Microsoft.Xna.Framework.Vector4 GetXnaVector4(Vector3 v) => new Microsoft.Xna.Framework.Vector4(v.X, v.Y, v.Z, 0); + public static Microsoft.Xna.Framework.Vector3 GetXnaVector3(Vector4 v) => new Microsoft.Xna.Framework.Vector3(v.X, v.Y, v.Z); + public static Matrix4x4 GetSys(Microsoft.Xna.Framework.Matrix invMatrices) => + new(invMatrices.M11, invMatrices.M12, invMatrices.M13, invMatrices.M14, + invMatrices.M21, invMatrices.M22, invMatrices.M23, invMatrices.M24, + invMatrices.M31, invMatrices.M32, invMatrices.M33, invMatrices.M34, + invMatrices.M41, invMatrices.M42, invMatrices.M43, invMatrices.M44); + } + +} + diff --git a/Editors/ImportExportEditor/Editors.ImportExport/DependencyInjectionContainer.cs b/Editors/ImportExportEditor/Editors.ImportExport/DependencyInjectionContainer.cs index 9c4331f5..f37e276e 100644 --- a/Editors/ImportExportEditor/Editors.ImportExport/DependencyInjectionContainer.cs +++ b/Editors/ImportExportEditor/Editors.ImportExport/DependencyInjectionContainer.cs @@ -53,8 +53,8 @@ public override void Register(IServiceCollection services) services.AddTransient(); services.AddTransient(); services.AddTransient(); - services.AddTransient(); - + services.AddTransient(); + services.AddTransient(); RegisterAllAsInterface(services, ServiceLifetime.Transient); } diff --git a/Editors/ImportExportEditor/Editors.ImportExport/Editors.ImportExport.csproj b/Editors/ImportExportEditor/Editors.ImportExport/Editors.ImportExport.csproj index 325bfc28..bb9a9ed0 100644 --- a/Editors/ImportExportEditor/Editors.ImportExport/Editors.ImportExport.csproj +++ b/Editors/ImportExportEditor/Editors.ImportExport/Editors.ImportExport.csproj @@ -11,8 +11,9 @@ - + + diff --git a/Editors/ImportExportEditor/Editors.ImportExport/Exporting/Exporters/RmvToGltf/Helpers/GltfAnimationBuilder.cs b/Editors/ImportExportEditor/Editors.ImportExport/Exporting/Exporters/RmvToGltf/Helpers/GltfAnimationBuilder.cs new file mode 100644 index 00000000..069b9705 --- /dev/null +++ b/Editors/ImportExportEditor/Editors.ImportExport/Exporting/Exporters/RmvToGltf/Helpers/GltfAnimationBuilder.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Numerics; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Automation; +using Editors.ImportExport.Common; +using GameWorld.Core.Animation; +using Shared.Core.PackFiles; +using Shared.Core.PackFiles.Models; +using Shared.GameFormats.Animation; +using SharpGLTF.Schema2; +using SysNum = System.Numerics; + +namespace Editors.ImportExport.Exporting.Exporters.RmvToGltf.Helpers +{ + public class GltfAnimationBuilder + { + private readonly IPackFileService _packFileService; + + + public GltfAnimationBuilder(IPackFileService packFileServoce) + { + _packFileService = packFileServoce; + } + + public void Build(AnimationFile animSkeleton, RmvToGltfExporterSettings settings, ProcessedGltfSkeleton gltfSkeleton, ModelRoot outputScene) + { + foreach (var animationPackFile in settings.InputAnimationFiles) + { + var animationToExport = AnimationFile.Create(animationPackFile); + CreateFromTWAnim(animationPackFile.Name, gltfSkeleton, animSkeleton, animationToExport, outputScene, settings); + } + } + + private void CreateFromTWAnim(string animationName, ProcessedGltfSkeleton gltfSkeleton, AnimationFile skeletonAnimFile, AnimationFile animationToExport, ModelRoot modelRoot, RmvToGltfExporterSettings settings) + { + var doMirror = settings.MirrorMesh; + var gameSkeleton = new GameSkeleton(skeletonAnimFile, null); + var animationClip = new AnimationClip(animationToExport, gameSkeleton); + + var secondsPerFrame = animationClip.PlayTimeInSec / animationClip.DynamicFrames.Count; + + var gltfAnimation = modelRoot.CreateAnimation(animationName); + + for (var boneIndex = 0; boneIndex < animationClip.AnimationBoneCount; boneIndex++) + { + var translationKeyFrames = new Dictionary(); + var rotationKeyFrames = new Dictionary(); + var scaleKeyFrames = new Dictionary(); + + // populate the bone track containers with the key frames from the .ANIM animation file + for (var frameIndex = 0; frameIndex < animationClip.DynamicFrames.Count; frameIndex++) + { + translationKeyFrames.Add(secondsPerFrame * (float)frameIndex, VecConv.GetSys(GlobalSceneTransforms.FlipVector(animationClip.DynamicFrames[frameIndex].Position[boneIndex], doMirror))); + rotationKeyFrames.Add(secondsPerFrame * (float)frameIndex, VecConv.GetSys(GlobalSceneTransforms.FlipQuaternion(animationClip.DynamicFrames[frameIndex].Rotation[boneIndex], doMirror))); + scaleKeyFrames.Add(secondsPerFrame * (float)frameIndex, new SysNum.Vector3(1, 1, 1)); + } + + // add the transformations + var boneNode = gltfSkeleton.Data[boneIndex].Item1; + gltfAnimation.CreateRotationChannel(boneNode, rotationKeyFrames); + gltfAnimation.CreateTranslationChannel(boneNode, translationKeyFrames); + gltfAnimation.CreateScaleChannel(boneNode, scaleKeyFrames); + } + } + } +} diff --git a/Editors/ImportExportEditor/Editors.ImportExport/Exporting/Exporters/RmvToGltf/Helpers/GltfAnimationCreator.cs b/Editors/ImportExportEditor/Editors.ImportExport/Exporting/Exporters/RmvToGltf/Helpers/GltfAnimationCreator.cs deleted file mode 100644 index 23ac5647..00000000 --- a/Editors/ImportExportEditor/Editors.ImportExport/Exporting/Exporters/RmvToGltf/Helpers/GltfAnimationCreator.cs +++ /dev/null @@ -1,138 +0,0 @@ -using System.Numerics; -using Editors.ImportExport.Common; -using Editors.ImportExport.Exporting.Exporters.GltfSkeleton; -using GameWorld.Core.Animation; -using Shared.Core.PackFiles; -using Shared.GameFormats.Animation; -using SharpGLTF.Schema2; -using SysNum = System.Numerics; - -namespace Editors.ImportExport.Exporting.Exporters.RmvToGltf.Helpers -{ - public class ProcessedGltfSkeleton - { - public required List<(Node, Matrix4x4)> Data { get; set; } - } - - public class GltfAnimationCreator - { - private readonly IPackFileService _packFileService; - - public GltfAnimationCreator(IPackFileService packFileService) - { - _packFileService = packFileService; - } - - public ProcessedGltfSkeleton? CreateAnimationAndSkeleton(string? skeletonNameFromRmv2, ModelRoot outputScene, RmvToGltfExporterSettings settings) - { - if(string.IsNullOrWhiteSpace(skeletonNameFromRmv2)) - return null; - - var skeletonAnimFile = FetchAnimSkeleton(skeletonNameFromRmv2); - var gltfSkeleton = CreateSkeleton(outputScene, skeletonAnimFile, settings.MirrorMesh); - - if (settings.ExportAnimations == false) - return gltfSkeleton; - - foreach (var animation in settings.InputAnimationFiles) - { - var animationToExport = AnimationFile.Create(animation); - CreateFromTWAnim(gltfSkeleton, skeletonAnimFile, animationToExport, outputScene, settings); - } - - return gltfSkeleton; - } - - ProcessedGltfSkeleton CreateSkeleton(ModelRoot outputScene, AnimationFile animSkeletonFil, bool doMirror) - { - if (animSkeletonFil.AnimationParts.Count == 0) - throw new Exception("No AnimationParts found in AnimationFile"); - - if (animSkeletonFil.AnimationParts[0].DynamicFrames.Count == 0) - throw new Exception("No DynamicFrames found in AnimationPart"); - - var frame = animSkeletonFil.AnimationParts[0].DynamicFrames[0]; - - var framePoseMatrixCalculator = new FramePoseMatrixCalculator(animSkeletonFil); - var invMatrices = framePoseMatrixCalculator.GetInverseBindPoseMatrices(doMirror); - - var outputGltfBindings = new List<(Node node, Matrix4x4 invMatrix)>(); - - var scene = outputScene.UseScene("default"); - - scene.CreateNode($"//skeleton//{animSkeletonFil.Header.SkeletonName.ToLower()}"); - - var parentIdToGltfNode = new Dictionary(); - parentIdToGltfNode[-1] = scene.CreateNode(""); // bones with no parent will be children of the scene - - for (var boneIndex = 0; boneIndex < animSkeletonFil.Bones.Length; boneIndex++) - { - var parentNode = parentIdToGltfNode[animSkeletonFil.Bones[boneIndex].ParentId]; - if (parentNode == null) - throw new Exception($"Parent Node not found for boneIndex={boneIndex}"); - - parentIdToGltfNode[boneIndex] = parentNode.CreateNode(animSkeletonFil.Bones[boneIndex].Name); - - parentIdToGltfNode[boneIndex]. - WithLocalTranslation(VecConv.GetSys(GlobalSceneTransforms.FlipVector(frame.Transforms[boneIndex].ToVector3(), doMirror))). - WithLocalRotation(VecConv.GetSys(GlobalSceneTransforms.FlipQuaternion(frame.Quaternion[boneIndex].ToQuaternion(), doMirror))). - WithLocalScale(new System.Numerics.Vector3(1, 1, 1)); - - var invBindPoseMatrix4x4 = VecConv.GetSys(invMatrices[boneIndex]); - - outputGltfBindings.Add((parentIdToGltfNode[boneIndex], invBindPoseMatrix4x4)); - } - - return new ProcessedGltfSkeleton() { Data = outputGltfBindings }; - } - - AnimationFile FetchAnimSkeleton(string skeletonNameFromRmv2) - { - var skeletonName = skeletonNameFromRmv2 + ".anim"; - - var skeletonSearchList = PackFileServiceUtility.SearchForFile(_packFileService, skeletonName); - var skeletonPath = _packFileService.GetFullPath(_packFileService.FindFile(skeletonSearchList[0])); - var skeletonPackFile = _packFileService.FindFile(skeletonPath); - - var animSkeletonFile = AnimationFile.Create(skeletonPackFile); - return animSkeletonFile; - } - - - void CreateFromTWAnim(ProcessedGltfSkeleton gltfSkeleton, AnimationFile skeletonAnimFile, AnimationFile animationToExport, ModelRoot outputScene, RmvToGltfExporterSettings settings) - { - var doMirror = settings.MirrorMesh; - var gameSkeleton = new GameSkeleton(skeletonAnimFile, null); - var animationClip = new AnimationClip(animationToExport, gameSkeleton); - - var secondsPerFrame = animationClip.PlayTimeInSec / animationClip.DynamicFrames.Count; - - for (var boneIndex = 0; boneIndex < animationClip.AnimationBoneCount; boneIndex++) - { - var translationKeyFrames = new Dictionary(); - var rotationKeyFrames = new Dictionary(); - - // populate the bone track containers with the key frames from the .ANIM animation file - for (var frameIndex = 0; frameIndex < animationClip.DynamicFrames.Count; frameIndex++) - { - translationKeyFrames.Add(secondsPerFrame * frameIndex, VecConv.GetSys(GlobalSceneTransforms.FlipVector(animationClip.DynamicFrames[frameIndex].Position[boneIndex], doMirror))); - rotationKeyFrames.Add(secondsPerFrame * frameIndex, VecConv.GetSys(GlobalSceneTransforms.FlipQuaternion(animationClip.DynamicFrames[frameIndex].Rotation[boneIndex], doMirror))); - } - - // find ACTUAL nodes, as opposed to "fake/visual"? nodes - var boneNode = gltfSkeleton.Data[boneIndex].Item1; - var logicalIndex = boneNode.LogicalIndex; - - if (logicalIndex >= outputScene.LogicalNodes.Count) - throw new Exception($"Fatal Error: Incorrect logical node index. logicalIndex={logicalIndex}, modelRoot.LogicalNodes.Count={outputScene.LogicalNodes.Count}"); - - var logicalNode = outputScene.LogicalNodes[logicalIndex]; - - logicalNode. - WithRotationAnimation("", rotationKeyFrames). - WithTranslationAnimation("", translationKeyFrames). - WithScaleAnimation("", (0.0f, new SysNum.Vector3(1, 1, 1))); - } - } - } -} diff --git a/Editors/ImportExportEditor/Editors.ImportExport/Exporting/Exporters/RmvToGltf/Helpers/GltfMeshBuilder.cs b/Editors/ImportExportEditor/Editors.ImportExport/Exporting/Exporters/RmvToGltf/Helpers/GltfMeshBuilder.cs index 6111359b..23d5ca37 100644 --- a/Editors/ImportExportEditor/Editors.ImportExport/Exporting/Exporters/RmvToGltf/Helpers/GltfMeshBuilder.cs +++ b/Editors/ImportExportEditor/Editors.ImportExport/Exporting/Exporters/RmvToGltf/Helpers/GltfMeshBuilder.cs @@ -21,7 +21,7 @@ public List> Build(RmvFile rmv2, Listx.MeshIndex == i).ToList(); - var gltfMaterial = Create(settings, rmvMesh.Material.ModelName + "_Material", textures); + var gltfMaterial = Create(settings, rmvMesh.Material.ModelName + "_Material", meshTextures); var gltfMesh = GenerateMesh(rmvMesh.Mesh, rmvMesh.Material.ModelName, gltfMaterial, hasSkeleton, settings.MirrorMesh); meshes.Add(gltfMesh); } @@ -46,8 +46,9 @@ MeshBuilder Generate glTfvertex.Material.TexCoord = new Vector2(vertex.Uv.X, vertex.Uv.Y); glTfvertex.Geometry.Position = VecConv.GetSys(GlobalSceneTransforms.FlipVector(VecConv.GetXna(glTfvertex.Geometry.Position), doMirror)); - glTfvertex.Geometry.Normal = VecConv.GetSys(GlobalSceneTransforms.FlipVector(VecConv.GetXna(glTfvertex.Geometry.Normal), doMirror)); - glTfvertex.Geometry.Tangent = VecConv.GetSys(GlobalSceneTransforms.FlipVector(VecConv.GetXna(glTfvertex.Geometry.Tangent), doMirror)); + + glTfvertex.Geometry.Normal = Vector3.Normalize(VecConv.GetSys(GlobalSceneTransforms.FlipVector(VecConv.GetXna(glTfvertex.Geometry.Normal), doMirror))); + glTfvertex.Geometry.Tangent = VecConv.NormalizeTangentVector4(VecConv.GetSys(GlobalSceneTransforms.FlipVector(VecConv.GetXna(glTfvertex.Geometry.Tangent), doMirror))); if (hasSkeleton) { diff --git a/Editors/ImportExportEditor/Editors.ImportExport/Exporting/Exporters/RmvToGltf/Helpers/GltfSceneSaver.cs b/Editors/ImportExportEditor/Editors.ImportExport/Exporting/Exporters/RmvToGltf/Helpers/GltfSceneSaver.cs index fbed1b4b..eaba73d5 100644 --- a/Editors/ImportExportEditor/Editors.ImportExport/Exporting/Exporters/RmvToGltf/Helpers/GltfSceneSaver.cs +++ b/Editors/ImportExportEditor/Editors.ImportExport/Exporting/Exporters/RmvToGltf/Helpers/GltfSceneSaver.cs @@ -1,4 +1,6 @@ -using SharpGLTF.Schema2; +using System.Windows; +using Shared.Core.ErrorHandling.Exceptions; +using SharpGLTF.Schema2; namespace Editors.ImportExport.Exporting.Exporters.RmvToGltf.Helpers { @@ -10,9 +12,23 @@ public interface IGltfSceneSaver public class GltfSceneSaver : IGltfSceneSaver { - public void Save(ModelRoot modelRoot, string fullSystemPath) + private readonly IExceptionService _exceptionService; + + public GltfSceneSaver(IExceptionService exceptionService) { - modelRoot.SaveGLTF(fullSystemPath); + _exceptionService = exceptionService; + } + + public void Save(ModelRoot modelRoot, string fullSystemPath) + { + try + { + modelRoot.SaveGLTF(fullSystemPath); + } + catch (Exception ex) + { + _exceptionService.CreateDialog(ex); + } } } } diff --git a/Editors/ImportExportEditor/Editors.ImportExport/Exporting/Exporters/RmvToGltf/Helpers/GltfSkeletonBuilder.cs b/Editors/ImportExportEditor/Editors.ImportExport/Exporting/Exporters/RmvToGltf/Helpers/GltfSkeletonBuilder.cs new file mode 100644 index 00000000..5ca8377f --- /dev/null +++ b/Editors/ImportExportEditor/Editors.ImportExport/Exporting/Exporters/RmvToGltf/Helpers/GltfSkeletonBuilder.cs @@ -0,0 +1,80 @@ +using System.Numerics; +using Editors.ImportExport.Common; +using Editors.ImportExport.Exporting.Exporters.GltfSkeleton; +using Editors.Shared.Core.Services; +using GameWorld.Core.Animation; +using GameWorld.Core.SceneNodes; +using Shared.Core.PackFiles; +using Shared.GameFormats.Animation; +using SharpGLTF.Schema2; +using SysNum = System.Numerics; + +namespace Editors.ImportExport.Exporting.Exporters.RmvToGltf.Helpers +{ + public class ProcessedGltfSkeleton + { + public required List<(Node, Matrix4x4)> Data { get; set; } + } + + public class GltfSkeletonBuilder + { + private readonly IPackFileService _packFileService; + + public GltfSkeletonBuilder(IPackFileService packFileService) + { + _packFileService = packFileService; + } + + public ProcessedGltfSkeleton CreateSkeleton(AnimationFile skeletonAnimFile, ModelRoot outputScene, RmvToGltfExporterSettings settings) + { + var gltfSkeleton = CreateSkeleton(outputScene, skeletonAnimFile, settings.MirrorMesh); + + return gltfSkeleton; + } + + ProcessedGltfSkeleton CreateSkeleton(ModelRoot outputScene, AnimationFile animSkeletonFil, bool doMirror) + { + if (animSkeletonFil.AnimationParts.Count == 0) + throw new Exception("No AnimationParts found in AnimationFile"); + + if (animSkeletonFil.AnimationParts[0].DynamicFrames.Count == 0) + throw new Exception("No DynamicFrames found in AnimationPart"); + + var frame = animSkeletonFil.AnimationParts[0].DynamicFrames[0]; + + var framePoseMatrixCalculator = new FramePoseMatrixCalculator(animSkeletonFil); + var invMatrices = framePoseMatrixCalculator.GetInverseBindPoseMatrices(doMirror); + + var outputGltfBindings = new List<(Node node, Matrix4x4 invMatrix)>(); + + var scene = outputScene.UseScene("default"); + + scene.CreateNode($"//skeleton//{animSkeletonFil.Header.SkeletonName.ToLower()}"); + + var parentIdToGltfNode = new Dictionary(); + parentIdToGltfNode[-1] = scene.CreateNode(""); // bones with no parent will be children of the scene + + for (var boneIndex = 0; boneIndex < animSkeletonFil.Bones.Length; boneIndex++) + { + var parentNode = parentIdToGltfNode[animSkeletonFil.Bones[boneIndex].ParentId]; + if (parentNode == null) + throw new Exception($"Parent Node not found for boneIndex={boneIndex}"); + + parentIdToGltfNode[boneIndex] = parentNode.CreateNode(animSkeletonFil.Bones[boneIndex].Name); + + parentIdToGltfNode[boneIndex]. + WithLocalTranslation(VecConv.GetSys(GlobalSceneTransforms.FlipVector(frame.Transforms[boneIndex].ToVector3(), doMirror))). + WithLocalRotation(VecConv.GetSys(GlobalSceneTransforms.FlipQuaternion(frame.Quaternion[boneIndex].ToQuaternion(), doMirror))). + WithLocalScale(new System.Numerics.Vector3(1, 1, 1)); + + var invBindPoseMatrix4x4 = VecConv.GetSys(invMatrices[boneIndex]); + + outputGltfBindings.Add((parentIdToGltfNode[boneIndex], invBindPoseMatrix4x4)); + } + + return new ProcessedGltfSkeleton() { Data = outputGltfBindings }; + } + + + } +} diff --git a/Editors/ImportExportEditor/Editors.ImportExport/Exporting/Exporters/RmvToGltf/Helpers/GltfTextureHandler.cs b/Editors/ImportExportEditor/Editors.ImportExport/Exporting/Exporters/RmvToGltf/Helpers/GltfTextureHandler.cs index 826a370a..1224a414 100644 --- a/Editors/ImportExportEditor/Editors.ImportExport/Exporting/Exporters/RmvToGltf/Helpers/GltfTextureHandler.cs +++ b/Editors/ImportExportEditor/Editors.ImportExport/Exporting/Exporters/RmvToGltf/Helpers/GltfTextureHandler.cs @@ -26,53 +26,46 @@ public GltfTextureHandler(IDdsToNormalPngExporter ddsToNormalPngExporter, IDdsTo public List HandleTextures(RmvFile rmvFile, RmvToGltfExporterSettings settings) { - var lodLevel = rmvFile.ModelList.First(); var output = new List(); var exportedTextures = new Dictionary(); // To avoid exporting same texture multiple times - for(var i = 0; i < lodLevel.Length; i++) + int lodICounnt = 1; + for (var lodIndex = 0; lodIndex < lodICounnt; lodIndex++) { - var model = lodLevel[i]; - var textures = ExtractTextures(model); - - var normalMapTexture = textures.FirstOrDefault(t => t.Type == TextureType.Normal); - if (normalMapTexture?.Path != null) - { - if (exportedTextures.ContainsKey(normalMapTexture.Path) == false) - exportedTextures[normalMapTexture.Path] = _ddsToNormalPngExporter.Export(normalMapTexture.Path, settings.OutputPath, settings.ConvertNormalTextureToBlue); - - var systemPath = exportedTextures[normalMapTexture.Path]; - if (systemPath != null) - output.Add(new TextureResult(i, systemPath, KnownChannel.Normal)); - } - - var materialTexture = textures.FirstOrDefault(t => t.Type == TextureType.MaterialMap); - if (materialTexture?.Path != null) + for (var meshIndex = 0; meshIndex < rmvFile.ModelList[lodIndex].Length; meshIndex++) { - if (exportedTextures.ContainsKey(materialTexture.Path) == false) - exportedTextures[materialTexture.Path] = _ddsToMaterialPngExporter.Export(materialTexture.Path, settings.OutputPath, settings.ConvertMaterialTextureToBlender); + var model = rmvFile.ModelList[lodIndex][meshIndex]; + var textures = ExtractTextures(model); - var systemPath = exportedTextures[materialTexture.Path]; - if (systemPath != null) - output.Add(new TextureResult(i, systemPath, KnownChannel.MetallicRoughness)); - } + foreach (var tex in textures) + { + switch (tex.Type) + { + case TextureType.Normal: DoTextureConversionNormalMap(settings, output, exportedTextures, meshIndex, tex); break; + case TextureType.MaterialMap: DoTextureConversionMaterialMap(settings, output, exportedTextures, meshIndex, tex); break; + case TextureType.BaseColour: DoTextureDefault(KnownChannel.BaseColor, settings, output, exportedTextures, meshIndex, tex); break; + case TextureType.Diffuse: DoTextureDefault(KnownChannel.BaseColor, settings, output, exportedTextures, meshIndex, tex); break; + case TextureType.Specular: DoTextureDefault(KnownChannel.SpecularColor, settings, output, exportedTextures, meshIndex, tex); break; + case TextureType.Gloss: DoTextureDefault(KnownChannel.MetallicRoughness, settings, output, exportedTextures, meshIndex, tex); break; + } + } + } - var baseColourTexture = textures.FirstOrDefault(t => t.Type == TextureType.BaseColour); - if (baseColourTexture?.Path != null) - { - if (exportedTextures.ContainsKey(baseColourTexture.Path) == false) - exportedTextures[baseColourTexture.Path] = _ddsToMaterialPngExporter.Export(baseColourTexture.Path, settings.OutputPath, false); - - var systemPath = exportedTextures[baseColourTexture.Path]; - if (systemPath != null) - output.Add(new TextureResult(i, systemPath, KnownChannel.BaseColor)); - } + } return output; + } + interface IDDsToPngExporter + { + public string Export(string path, string outputPath, bool convertToBlender) + { + throw new System.NotImplementedException(); + } } + List ExtractTextures(RmvModel model) { var textures = model.Material.GetAllTextures(); @@ -81,5 +74,35 @@ List ExtractTextures(RmvModel model) } record MaterialBuilderTextureInput(string Path, TextureType Type); + + private void DoTextureConversionMaterialMap(RmvToGltfExporterSettings settings, List output, Dictionary exportedTextures, int meshIndex, MaterialBuilderTextureInput text) + { + if (exportedTextures.ContainsKey(text.Path) == false) + exportedTextures[text.Path] = _ddsToMaterialPngExporter.Export(text.Path, settings.OutputPath, settings.ConvertMaterialTextureToBlender); + + var systemPath = exportedTextures[text.Path]; + if (systemPath != null) + output.Add(new TextureResult(meshIndex, systemPath, KnownChannel.MetallicRoughness)); + } + + private void DoTextureDefault(KnownChannel textureType, RmvToGltfExporterSettings settings, List output, Dictionary exportedTextures, int meshIndex, MaterialBuilderTextureInput text) + { + if (exportedTextures.ContainsKey(text.Path) == false) + exportedTextures[text.Path] = _ddsToMaterialPngExporter.Export(text.Path, settings.OutputPath, false); // TODO: exchange export with a default one + + var systemPath = exportedTextures[text.Path]; + if (systemPath != null) + output.Add(new TextureResult(meshIndex, systemPath, textureType)); + } + + private void DoTextureConversionNormalMap(RmvToGltfExporterSettings settings, List output, Dictionary exportedTextures, int meshIndex, MaterialBuilderTextureInput text) + { + if (exportedTextures.ContainsKey(text.Path) == false) + exportedTextures[text.Path] = _ddsToNormalPngExporter.Export(text.Path, settings.OutputPath, settings.ConvertNormalTextureToBlue); + + var systemPath = exportedTextures[text.Path]; + if (systemPath != null) + output.Add(new TextureResult(meshIndex, systemPath, KnownChannel.Normal)); + } } } diff --git a/Editors/ImportExportEditor/Editors.ImportExport/Exporting/Exporters/RmvToGltf/Helpers/VectorConverter.cs b/Editors/ImportExportEditor/Editors.ImportExport/Exporting/Exporters/RmvToGltf/Helpers/VectorConverter.cs deleted file mode 100644 index f19b5544..00000000 --- a/Editors/ImportExportEditor/Editors.ImportExport/Exporting/Exporters/RmvToGltf/Helpers/VectorConverter.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Numerics; - -namespace Editors.ImportExport.Exporting.Exporters.RmvToGltf.Helpers -{ - class VecConv - { - public static Quaternion GetSys(Microsoft.Xna.Framework.Quaternion q) => new System.Numerics.Quaternion(q.X, q.Y, q.Z, q.W); - public static Vector4 GetSys(Microsoft.Xna.Framework.Vector4 v) => new System.Numerics.Vector4(v.X, v.Y, v.Z, v.W); - public static Vector3 GetSys(Microsoft.Xna.Framework.Vector3 v) => new System.Numerics.Vector3(v.X, v.Y, v.Z); - public static Microsoft.Xna.Framework.Vector4 GetXna(System.Numerics.Vector4 v) => new Microsoft.Xna.Framework.Vector4(v.X, v.Y, v.Z, v.W); - public static Microsoft.Xna.Framework.Vector3 GetXna(System.Numerics.Vector3 v) => new Microsoft.Xna.Framework.Vector3(v.X, v.Y, v.Z); - public static Microsoft.Xna.Framework.Vector2 GetXna(System.Numerics.Vector2 v) => new Microsoft.Xna.Framework.Vector2(v.X, v.Y); - public static Microsoft.Xna.Framework.Vector4 GetXnaVector4(System.Numerics.Vector3 v) => new Microsoft.Xna.Framework.Vector4(v.X, v.Y, v.Z, 0); - public static Microsoft.Xna.Framework.Vector3 GetXnaVector3(System.Numerics.Vector4 v) => new Microsoft.Xna.Framework.Vector3(v.X, v.Y, v.Z); - public static Matrix4x4 GetSys(Microsoft.Xna.Framework.Matrix invMatrices) => - new(invMatrices.M11, invMatrices.M12, invMatrices.M13, invMatrices.M14, - invMatrices.M21, invMatrices.M22, invMatrices.M23, invMatrices.M24, - invMatrices.M31, invMatrices.M32, invMatrices.M33, invMatrices.M34, - invMatrices.M41, invMatrices.M42, invMatrices.M43, invMatrices.M44); - } - -} - diff --git a/Editors/ImportExportEditor/Editors.ImportExport/Exporting/Exporters/RmvToGltf/RmvToGltfExporter.cs b/Editors/ImportExportEditor/Editors.ImportExport/Exporting/Exporters/RmvToGltf/RmvToGltfExporter.cs index 42355718..ad9d7186 100644 --- a/Editors/ImportExportEditor/Editors.ImportExport/Exporting/Exporters/RmvToGltf/RmvToGltfExporter.cs +++ b/Editors/ImportExportEditor/Editors.ImportExport/Exporting/Exporters/RmvToGltf/RmvToGltfExporter.cs @@ -1,8 +1,11 @@ -using Editors.ImportExport.Exporting.Exporters.RmvToGltf.Helpers; +using System.Windows; +using Editors.ImportExport.Exporting.Exporters.RmvToGltf.Helpers; using Editors.ImportExport.Misc; +using Editors.Shared.Core.Services; using Serilog; using Shared.Core.ErrorHandling; using Shared.Core.PackFiles.Models; +using Shared.GameFormats.Animation; using Shared.GameFormats.RigidModel; using SharpGLTF.Geometry; using SharpGLTF.Materials; @@ -16,14 +19,18 @@ public class RmvToGltfExporter private readonly IGltfSceneSaver _gltfSaver; private readonly GltfMeshBuilder _gltfMeshBuilder; private readonly IGltfTextureHandler _gltfTextureHandler; - private readonly GltfAnimationCreator _gltfAnimationCreator; + private readonly GltfSkeletonBuilder _gltfSkeletonBuilder; + private readonly GltfAnimationBuilder _gltfAnimationBuilder; + private readonly SkeletonAnimationLookUpHelper _skeletonLookUpHelper; - public RmvToGltfExporter(IGltfSceneSaver gltfSaver, GltfMeshBuilder gltfMeshBuilder, IGltfTextureHandler gltfTextureHandler, GltfAnimationCreator gltfAnimationCreator) + public RmvToGltfExporter(IGltfSceneSaver gltfSaver, GltfMeshBuilder gltfMeshBuilder, IGltfTextureHandler gltfTextureHandler, GltfSkeletonBuilder gltfSkeletonsBuilder, GltfAnimationBuilder gltfAnimationCreator, SkeletonAnimationLookUpHelper skeletonLookUpHelper) { _gltfSaver = gltfSaver; _gltfMeshBuilder = gltfMeshBuilder; _gltfTextureHandler = gltfTextureHandler; - _gltfAnimationCreator = gltfAnimationCreator; + _gltfSkeletonBuilder = gltfSkeletonsBuilder; + _gltfAnimationBuilder = gltfAnimationCreator; + _skeletonLookUpHelper = skeletonLookUpHelper; } internal ExportSupportEnum CanExportFile(PackFile file) @@ -42,12 +49,30 @@ public void Export(RmvToGltfExporterSettings settings) var rmv2 = new ModelFactory().Load(settings.InputModelFile.DataSource.ReadData()); var outputScene = ModelRoot.CreateModel(); - var skeleton = _gltfAnimationCreator.CreateAnimationAndSkeleton(rmv2.Header.SkeletonName, outputScene, settings); + ProcessedGltfSkeleton? gltfSkeleton = null; + if (settings.ExportAnimations && !string.IsNullOrEmpty(rmv2.Header.SkeletonName)) + { + var skeletonAnimFile = _skeletonLookUpHelper.GetSkeletonFileFromName(rmv2.Header.SkeletonName); + if (skeletonAnimFile == null) + { + if (MessageBox.Show( + "Skeleton file not found, \n(Have you loaded all CA pakcs for the right game?)\n Do you want to continue exporting without skeleton/animations?", + "Warning!", + MessageBoxButton.YesNo, MessageBoxImage.Warning) == MessageBoxResult.No) + return; + } + else + { + gltfSkeleton = _gltfSkeletonBuilder.CreateSkeleton(skeletonAnimFile, outputScene, settings); + _gltfAnimationBuilder.Build(skeletonAnimFile, settings, gltfSkeleton, outputScene); + } + } + var textures = _gltfTextureHandler.HandleTextures(rmv2, settings); var meshes = _gltfMeshBuilder.Build(rmv2, textures, settings); - _logger.Here().Information($"MeshCount={meshes.Count()} TextureCount={textures.Count()} Skeleton={skeleton?.Data.Count}"); - BuildGltfScene(meshes, skeleton, settings, outputScene); + _logger.Here().Information($"MeshCount={meshes.Count()} TextureCount={textures.Count()} Skeleton={gltfSkeleton?.Data.Count}"); + BuildGltfScene(meshes, gltfSkeleton, settings, outputScene); } void BuildGltfScene(List> meshBuilders, ProcessedGltfSkeleton? gltfSkeleton, RmvToGltfExporterSettings settings, ModelRoot outputScene) diff --git a/Editors/ImportExportEditor/Editors.ImportExport/Exporting/Presentation/ExportWindow.xaml.cs b/Editors/ImportExportEditor/Editors.ImportExport/Exporting/Presentation/ExportWindow.xaml.cs index 9b23a06c..73bc78f3 100644 --- a/Editors/ImportExportEditor/Editors.ImportExport/Exporting/Presentation/ExportWindow.xaml.cs +++ b/Editors/ImportExportEditor/Editors.ImportExport/Exporting/Presentation/ExportWindow.xaml.cs @@ -1,4 +1,6 @@ -using System.Windows; +using System.IO; +using System.Windows; +using Microsoft.Xna.Framework.Graphics; using Shared.Core.PackFiles.Models; namespace Editors.ImportExport.Exporting.Presentation @@ -24,8 +26,67 @@ internal void Initialize(PackFile packFile) private void ExportButton_Click(object sender, RoutedEventArgs e) { + if (!PathValidator.IsValid(_viewModel.SystemPath)) + { + MessageBox.Show("Invalid or empty path", "Error"); + return; + } + _viewModel.Export(); Close(); } } + + // TODO: should be moved to a shared library + public static class PathValidator + { + public static bool IsValid(string fileName) + { + if (string.IsNullOrWhiteSpace(fileName)) + { + return false; + } + + if (!IsValidFileName(fileName)) + { + return false; + } + + if (!IsValidFolder(fileName)) + { + return false; + } + + return true; + } + + private static bool IsValidFileName(string fileName) + { + char[] invalidChars = Path.GetInvalidFileNameChars(); + var fileNamOnly = Path.GetFileName(fileName); + foreach (char c in fileNamOnly) + { + if (Array.Exists(invalidChars, invalidChar => invalidChar == c)) + { + return false; + } + } + + return true; + } + + private static bool IsValidFolder(string fileName) + { + char[] invalidChars = Path.GetInvalidPathChars(); + var folder = Path.GetDirectoryName(fileName); + foreach (char c in folder) + { + if (Array.Exists(invalidChars, invalidChar => invalidChar == c)) + { + return false; + } + } + return true; + } + } } diff --git a/Editors/ImportExportEditor/Editors.ImportExport/Importing/DisplayImportFileToolCommand.cs b/Editors/ImportExportEditor/Editors.ImportExport/Importing/DisplayImportFileToolCommand.cs index 4a1936fe..528fd3a4 100644 --- a/Editors/ImportExportEditor/Editors.ImportExport/Importing/DisplayImportFileToolCommand.cs +++ b/Editors/ImportExportEditor/Editors.ImportExport/Importing/DisplayImportFileToolCommand.cs @@ -9,14 +9,14 @@ namespace Editors.ImportExport.Importing { public class DisplayImportFileToolCommand : IUiCommand - { + { // TODO: ? - private readonly GltfImporter _importer; - + private readonly GltfImporter _importer; + public DisplayImportFileToolCommand(GltfImporter importer) - { + { // TODO: ? //_ImportWindowFactory = importWindowFactory; _importer = importer; @@ -25,6 +25,8 @@ public DisplayImportFileToolCommand(GltfImporter importer) public void Execute(TreeNode clickedNode) { var glftFilePath = GetFileFromDiskDialog(); + if (string.IsNullOrEmpty(glftFilePath)) + return; var settings = new GltfImporterSettings(glftFilePath, true, clickedNode); _importer.Import(settings); @@ -42,10 +44,15 @@ private static string GetFileFromDiskDialog() if (openFileDialog.ShowDialog() == DialogResult.OK) { - //Get the path of specified file + // Get the path of specified file filePath = openFileDialog.FileName; } + else + { + filePath = ""; + } } + return filePath; } } diff --git a/Editors/ImportExportEditor/Editors.ImportExport/Importing/ImportFIleContextMenuHelper.cs b/Editors/ImportExportEditor/Editors.ImportExport/Importing/ImportFIleContextMenuHelper.cs index 3c8cd77a..038dc949 100644 --- a/Editors/ImportExportEditor/Editors.ImportExport/Importing/ImportFIleContextMenuHelper.cs +++ b/Editors/ImportExportEditor/Editors.ImportExport/Importing/ImportFIleContextMenuHelper.cs @@ -13,6 +13,7 @@ using Shared.Core.PackFiles.Models; using Shared.Core.Services; using Shared.Ui.BaseDialogs.PackFileBrowser; +using TreeNode = Shared.Ui.BaseDialogs.PackFileBrowser.TreeNode; namespace Editors.ImportExport.Importing { @@ -37,7 +38,7 @@ public bool CanImportFile(string filePath) return false; } - public void ShowDialog(Shared.Ui.BaseDialogs.PackFileBrowser.TreeNode clickedNode) => + public void ShowDialog(TreeNode clickedNode) => _uiCommandFactory.Create().Execute(clickedNode); } } diff --git a/Editors/ImportExportEditor/Editors.ImportExport/Importing/Importers/GltfToRmv/GltfImporter.cs b/Editors/ImportExportEditor/Editors.ImportExport/Importing/Importers/GltfToRmv/GltfImporter.cs index 099c846e..f91d4a7a 100644 --- a/Editors/ImportExportEditor/Editors.ImportExport/Importing/Importers/GltfToRmv/GltfImporter.cs +++ b/Editors/ImportExportEditor/Editors.ImportExport/Importing/Importers/GltfToRmv/GltfImporter.cs @@ -6,6 +6,7 @@ using Shared.Core.PackFiles; using Shared.Ui.BaseDialogs.PackFileBrowser; using static Shared.Core.PackFiles.IPackFileService; +using Shared.Core.ErrorHandling.Exceptions; namespace Editors.ImportExport.Importing.Importers.GltfToRmv @@ -14,35 +15,47 @@ public record GltfImporterSettings ( string InputGltfFile, bool ConvertNormalTextureToOrnge, - TreeNode destinationPackFolder + TreeNode destinationPackNode ); public class GltfImporter { private readonly IPackFileService _packFileService; + private readonly IExceptionService _exceptionService; - public GltfImporter(IPackFileService packFileSerivce) + public GltfImporter(IPackFileService packFileSerivce, IExceptionService exceptionService) { _packFileService = packFileSerivce; + _exceptionService = exceptionService; } private ModelRoot? _modelRoot; + public void Import(GltfImporterSettings settings) { - _modelRoot = ModelRoot.Load(settings.InputGltfFile); + try + { + _modelRoot = ModelRoot.Load(settings.InputGltfFile); + } + catch (Exception ex) + { + _exceptionService.CreateDialog(ex); + return; + } var importedFileName = GetImportedPackFileName(settings); var rmv2File = RmvMeshBuilder.Build(settings, _modelRoot); var bytesRmv2 = ModelFactory.Create().Save(rmv2File); + var packFileImported = new PackFile(importedFileName, new MemorySource(bytesRmv2)); - var newFile = new NewPackFileEntry(settings.destinationPackFolder.GetFullPath(), packFileImported); - _packFileService.AddFilesToPack(settings.destinationPackFolder.FileOwner, [newFile]); + var newFile = new NewPackFileEntry(settings.destinationPackNode.GetFullPath(), packFileImported); + _packFileService.AddFilesToPack(settings.destinationPackNode.FileOwner, [newFile]); } private static string GetImportedPackFileName(GltfImporterSettings settings) - { + { var fileName = Path.GetFileNameWithoutExtension(settings.InputGltfFile); string importedFileName = $@"{fileName}.rigid_model_v2"; diff --git a/Editors/ImportExportEditor/Editors.ImportExport/Importing/Importers/GltfToRmv/Helper/Rmv2FromGltfFIleConverter.cs b/Editors/ImportExportEditor/Editors.ImportExport/Importing/Importers/GltfToRmv/Helper/Rmv2FromGltfFIleConverter.cs index d06b7ab7..56b1e6b9 100644 --- a/Editors/ImportExportEditor/Editors.ImportExport/Importing/Importers/GltfToRmv/Helper/Rmv2FromGltfFIleConverter.cs +++ b/Editors/ImportExportEditor/Editors.ImportExport/Importing/Importers/GltfToRmv/Helper/Rmv2FromGltfFIleConverter.cs @@ -8,7 +8,6 @@ using SharpGLTF.Geometry.VertexTypes; using SharpGLTF.Schema2; using XNA = Microsoft.Xna.Framework; -using Shared.GameFormats.RigidModel; using Xceed.Wpf.Toolkit.PropertyGrid.Editors; using Editors.ImportExport.Exporting.Exporters.RmvToGltf.Helpers; using Shared.GameFormats.RigidModel.Vertex; @@ -22,6 +21,7 @@ using Shared.GameFormats.RigidModel.MaterialHeaders; using SharpGLTF.Runtime; using Shared.GameFormats.RigidModel.LodHeader; +using Shared; using SharpDX.MediaFoundation; using Editors.ImportExport.Common; using Pfim; @@ -70,8 +70,7 @@ private RmvMesh ConvertToRmv2MeshByVertexColumns(SharpGLTF.Schema2.Mesh mesh) { var rmv2Mesh = new RmvMesh(); - var prim = mesh.Primitives.First(); - var tEST_triangleIndices = prim.GetTriangleIndices(); // TODO: TESTING CODE + var prim = mesh.Primitives.First(); var vertexBufferColumns = prim.GetVertexColumns(); rmv2Mesh.VertexList = new CommonVertex[vertexBufferColumns.Positions.Count()]; @@ -116,7 +115,7 @@ private RmvMesh ConvertToRmv2MeshByTriangles(SharpGLTF.Schema2.Mesh mesh) private static CommonVertex ConvertToRmvVertex(VertexBuilder vertexBuilder) { - var rmv2Vertex = new Shared.GameFormats.RigidModel.Vertex.CommonVertex(); + var rmv2Vertex = new CommonVertex(); rmv2Vertex.Position = new XNA.Vector4(-vertexBuilder.Geometry.Position.X, vertexBuilder.Geometry.Position.Y, vertexBuilder.Geometry.Position.Z, 1); rmv2Vertex.Uv = VecConv.GetXna(vertexBuilder.Material.TexCoord); diff --git a/Editors/ImportExportEditor/Editors.ImportExport/Importing/Importers/GltfToRmv/Helper/RmvMeshBuilder.cs b/Editors/ImportExportEditor/Editors.ImportExport/Importing/Importers/GltfToRmv/Helper/RmvMeshBuilder.cs index 7160b084..7a21122a 100644 --- a/Editors/ImportExportEditor/Editors.ImportExport/Importing/Importers/GltfToRmv/Helper/RmvMeshBuilder.cs +++ b/Editors/ImportExportEditor/Editors.ImportExport/Importing/Importers/GltfToRmv/Helper/RmvMeshBuilder.cs @@ -3,7 +3,6 @@ using SharpGLTF.Schema2; using Shared.GameFormats.RigidModel.Vertex; using SharpGLTF.Geometry.VertexTypes; -using Editors.ImportExport.Exporting.Exporters.RmvToGltf.Helpers; using SharpGLTF.Geometry; using GameWorld.Core.Animation; using Shared.GameFormats.RigidModel.MaterialHeaders; @@ -15,6 +14,7 @@ using System.Drawing.Printing; using System; using System.Text; +using Editors.ImportExport.Common; namespace Editors.ImportExport.Importing.Importers.GltfToRmv.Helper { @@ -128,7 +128,8 @@ private static RmvMesh GenerateRmvMesh(SharpGLTF.Schema2.Mesh mesh) private static CommonVertex ConvertToRmvVertex(VertexBuilder vertexBuilder) { - var rmv2Vertex = new Shared.GameFormats.RigidModel.Vertex.CommonVertex(); + + var rmv2Vertex = new CommonVertex(); rmv2Vertex.Position = new XNA.Vector4(-vertexBuilder.Geometry.Position.X, vertexBuilder.Geometry.Position.Y, vertexBuilder.Geometry.Position.Z, 1); rmv2Vertex.Uv = VecConv.GetXna(vertexBuilder.Material.TexCoord); diff --git a/Editors/ImportExportEditor/Test.ImportExport/Exporting/Exporters/RmvToGlft/RmvToGltfExporterTests.cs b/Editors/ImportExportEditor/Test.ImportExport/Exporting/Exporters/RmvToGlft/RmvToGltfExporterTests.cs index 129fb229..0239a42a 100644 --- a/Editors/ImportExportEditor/Test.ImportExport/Exporting/Exporters/RmvToGlft/RmvToGltfExporterTests.cs +++ b/Editors/ImportExportEditor/Test.ImportExport/Exporting/Exporters/RmvToGlft/RmvToGltfExporterTests.cs @@ -2,7 +2,9 @@ using Editors.ImportExport.Exporting.Exporters.DdsToNormalPng; using Editors.ImportExport.Exporting.Exporters.RmvToGltf; using Editors.ImportExport.Exporting.Exporters.RmvToGltf.Helpers; +using Editors.Shared.Core.Services; using Moq; +using Shared.Core.Events; using Shared.TestUtility; namespace Test.ImportExport.Exporting.Exporters.RmvToGlft @@ -21,13 +23,16 @@ public void Test() var meshBuilder = new GltfMeshBuilder(); var normalExporter = new Mock(); var materialExporter = new Mock(); - var animationCreator = new GltfAnimationCreator(pfs); + var eventHub = new Mock(); + var skeletontonLookupHelper = new SkeletonAnimationLookUpHelper(pfs, eventHub.Object); + var skeletontonBuilder = new GltfSkeletonBuilder(pfs); + var animationBuilder = new GltfAnimationBuilder(pfs); var textureHandler = new GltfTextureHandler(normalExporter.Object, materialExporter.Object); var sceneSaver = new TestGltfSceneSaver(); // Act var mesh = pfs.FindFile(_rmvFilePathKarl); - var exporter = new RmvToGltfExporter(sceneSaver, meshBuilder, textureHandler, animationCreator); + var exporter = new RmvToGltfExporter(sceneSaver, meshBuilder, textureHandler, skeletontonBuilder, animationBuilder, skeletontonLookupHelper); var settings = new RmvToGltfExporterSettings(mesh!, [], @"C:\test\myExport.gltf", true, true, true, true); exporter.Export(settings);