From 5903ddda2b5fac8e6152e3e97d7c76e753fa41ca Mon Sep 17 00:00:00 2001 From: Misaki Date: Sun, 26 Apr 2026 14:49:58 +0900 Subject: [PATCH] Refactor mesh import, meshlet, and asset handler systems - Mesh import now builds full node hierarchy and splits geometry by material, with robust normal/tangent handling - Meshlet generation supports material indices for correct assignment - Refactored texture cube map compression and mipmap handling - Updated asset handler registration to new namespace - Enabled asset reimport on import events - Improved code quality, resource management, and formatting --- .../Assets/MeshProcessor.Import.cs | 233 +++++++++--------- .../Assets/MeshProcessor.Meshlet.cs | 26 +- .../Assets/TextureProcessor.Compress.cs | 83 ++++--- .../Assets/TextureProcessor.GGXMip.cs | 9 +- .../Services/ImportCoordinator.cs | 2 +- src/Editor/Ghost.Editor/ActivationHandler.cs | 12 +- .../Controls/ContentBrowserViewModel.cs | 12 +- .../AssetHandlerRegistrationGenerator.cs | 10 +- 8 files changed, 218 insertions(+), 169 deletions(-) diff --git a/src/Editor/Ghost.Editor.Core/Assets/MeshProcessor.Import.cs b/src/Editor/Ghost.Editor.Core/Assets/MeshProcessor.Import.cs index 094da21..32c5b79 100644 --- a/src/Editor/Ghost.Editor.Core/Assets/MeshProcessor.Import.cs +++ b/src/Editor/Ghost.Editor.Core/Assets/MeshProcessor.Import.cs @@ -1,4 +1,5 @@ using Ghost.Core; +using Ghost.Engine.Utilities; using Ghost.Graphics.RHI; using Ghost.Graphics.Utilities; using Ghost.MeshOptimizer; @@ -59,23 +60,60 @@ internal unsafe class MeshParsingWorkItem : IJob }; } - private GeometryMeshNode ParseGeometry(ufbx_mesh* pMesh) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static float4x4 ToFloat4x4(ufbx_vec3 t, ufbx_quat q, ufbx_vec3 s) { - var meshNode = new GeometryMeshNode + return float4x4.TRS( + new float3(t.x, t.y, t.z), + new quaternion(q.x, q.y, q.z, q.w), + new float3(s.x, s.y, s.z) + ); + } + + private MeshNode ParseHierarchy(ufbx_node* node) + { + var children = new List(); + var meshNode = new MeshNode { - Name = pMesh->name.ToString(), - Children = Array.Empty(), + Name = node->name.ToString(), + LocalTransform = ToFloat4x4(node->local_transform.translation, node->local_transform.rotation, node->local_transform.scale), + Children = children }; + if (node->mesh != null) + { + var geoNodes = ParseGeometry(node->mesh); + children.AddRange(geoNodes); + } + + // TODO: Handle lights, cameras, and other node types. + + for (var i = 0u; i < node->children.count; i++) + { + children.Add(ParseHierarchy(node->children.data[i])); + } + + return meshNode; + } + + private IReadOnlyCollection ParseGeometry(ufbx_mesh* pMesh) + { + var resultNodes = new List(); + if (pMesh->num_faces == 0) { - return meshNode; + return resultNodes; } - var missingNormals = false; - var missingTangents = false; + var numMaterials = pMesh->materials.count > 0 ? (int)pMesh->materials.count : 1; + var materialBuckets = new UnsafeList[numMaterials]; + var missingNormalsBucket = new bool[numMaterials]; + var missingTangentsBucket = new bool[numMaterials]; - using var flatVertices = new UnsafeList(1024, AllocationHandle.FreeList); + for (int i = 0; i < numMaterials; i++) + { + materialBuckets[i] = new UnsafeList(1024, AllocationHandle.FreeList); + } var maxScratchIndices = (int)(pMesh->max_face_triangles * 3u); @@ -84,9 +122,10 @@ internal unsafe class MeshParsingWorkItem : IJob for (var j = 0u; j < pMesh->num_faces; j++) { var face = pMesh->faces.data[j]; + var materialIdx = pMesh->face_material.count > j ? pMesh->face_material.data[j] : 0; var numTris = UfbxApi.TriangulateFace(triIndicesArray.AsSpan(0, maxScratchIndices), pMesh, face); - + var totalIndices = numTris * 3; for (var k = 0; k < totalIndices; k++) { @@ -123,62 +162,88 @@ internal unsafe class MeshParsingWorkItem : IJob vertex.tangent = ComputeTangent(t, n, b); } - var newIndex = (uint)flatVertices.Count; + materialBuckets[materialIdx].Add(vertex); - flatVertices.Add(vertex); - - if (!missingNormals) + if (!missingNormalsBucket[materialIdx]) { - missingNormals = normIdx == uint.MaxValue; + missingNormalsBucket[materialIdx] = normIdx == uint.MaxValue; } - if (!missingTangents) + if (!missingTangentsBucket[materialIdx]) { - missingTangents = tanIdx == uint.MaxValue || btanIdx == uint.MaxValue; + missingTangentsBucket[materialIdx] = tanIdx == uint.MaxValue || btanIdx == uint.MaxValue; } } } - var numIndices = (uint)flatVertices.Count; - - using var weldedIndices = new UnsafeArray((int)numIndices, AllocationHandle.FreeList); - using var cachedIndices = new UnsafeArray((int)numIndices, AllocationHandle.FreeList); - - var stream = new ufbx_vertex_stream + for (int m = 0; m < numMaterials; m++) { - data = flatVertices.GetUnsafePtr(), - vertex_count = numIndices, - vertex_size = (nuint)sizeof(Vertex) - }; + var flatVertices = materialBuckets[m]; + if (flatVertices.Count == 0) + { + flatVertices.Dispose(); + continue; + } - var error = new ufbx_error(); - var numUniqueVertices = UfbxApi.GenerateIndices([stream], weldedIndices, null, &error); - if (numUniqueVertices == 0 && error.type != ufbx_error_type.UFBX_ERROR_NONE) - { - return; + var numIndices = (uint)flatVertices.Count; + + using var weldedIndices = new UnsafeArray((int)numIndices, AllocationHandle.FreeList); + using var cachedIndices = new UnsafeArray((int)numIndices, AllocationHandle.FreeList); + + var stream = new ufbx_vertex_stream + { + data = flatVertices.GetUnsafePtr(), + vertex_count = numIndices, + vertex_size = (nuint)sizeof(Vertex) + }; + + var error = new ufbx_error(); + var numUniqueVertices = UfbxApi.GenerateIndices([stream], weldedIndices, null, &error); + if (numUniqueVertices == 0 && error.type != ufbx_error_type.UFBX_ERROR_NONE) + { + flatVertices.Dispose(); + continue; + } + + MeshOptApi.OptimizeVertexCache((uint*)cachedIndices.GetUnsafePtr(), (uint*)weldedIndices.GetUnsafePtr(), numIndices, numUniqueVertices); + + var nodeVertices = new UnsafeList((int)numUniqueVertices, _allocationHandle); + var nodeIndices = new UnsafeList((int)numIndices, _allocationHandle); + + var finalVertexCount = MeshOptApi.OptimizeVertexFetch(nodeVertices.GetUnsafePtr(), (uint*)cachedIndices.GetUnsafePtr(), numIndices, flatVertices.GetUnsafePtr(), numIndices, (nuint)sizeof(Vertex)); + + nodeVertices.UnsafeSetCount((int)finalVertexCount); + + MemoryUtility.MemCpy(nodeIndices.GetUnsafePtr(), cachedIndices.GetUnsafePtr(), numIndices * sizeof(uint)); + nodeIndices.UnsafeSetCount((int)numIndices); + + if (_settings.NormalDataSource == VertexDataSource.Computed || (_settings.NormalDataSource == VertexDataSource.ComputedIfMissing && missingNormalsBucket[m])) + { + MeshBuilder.ComputeNormal(nodeVertices, nodeIndices); + } + + if (_settings.TangentDataSource == VertexDataSource.Computed || (_settings.TangentDataSource == VertexDataSource.ComputedIfMissing && missingTangentsBucket[m])) + { + MeshBuilder.ComputeTangents(nodeVertices, nodeIndices); + } + + var meshNodeName = numMaterials > 1 ? $"{pMesh->name.ToString()}_mat{m}" : pMesh->name.ToString(); + + var meshNode = new GeometryMeshNode + { + Name = meshNodeName, + LocalTransform = new float4x4(new float4(1, 0, 0, 0), new float4(0, 1, 0, 0), new float4(0, 0, 1, 0), new float4(0, 0, 0, 1)), + Children = Array.Empty(), + Vertices = nodeVertices, + Indices = nodeIndices, + MaterialIndex = m + }; + + resultNodes.Add(meshNode); + flatVertices.Dispose(); } - MeshOptApi.OptimizeVertexCache((uint*)cachedIndices.GetUnsafePtr(), (uint*)weldedIndices.GetUnsafePtr(), numIndices, numUniqueVertices); - - vertices = new UnsafeList((int)numUniqueVertices, _allocationHandle); - indices = new UnsafeList((int)numIndices, _allocationHandle); - - var finalVertexCount = MeshOptApi.OptimizeVertexFetch(vertices.GetUnsafePtr(), (uint*)cachedIndices.GetUnsafePtr(), numIndices, flatVertices.GetUnsafePtr(), numIndices, (nuint)sizeof(Vertex)); - - vertices.UnsafeSetCount((int)finalVertexCount); - - MemoryUtility.MemCpy(indices.GetUnsafePtr(), cachedIndices.GetUnsafePtr(), numIndices * sizeof(uint)); - indices.UnsafeSetCount((int)numIndices); - - if (_settings.NormalDataSource == VertexDataSource.Computed || (_settings.NormalDataSource == VertexDataSource.ComputedIfMissing && missingNormals)) - { - MeshBuilder.ComputeNormal(vertices, indices); - } - - if (_settings.TangentDataSource == VertexDataSource.Computed || (_settings.TangentDataSource == VertexDataSource.ComputedIfMissing && missingTangents)) - { - MeshBuilder.ComputeTangents(vertices, indices); - } + return resultNodes; } public void Execute(ref readonly JobExecutionContext context) @@ -231,68 +296,10 @@ internal unsafe class MeshParsingWorkItem : IJob return; } - using var flatVertices = new UnsafeList(1024, AllocationHandle.FreeList); + var rootNode = ParseHierarchy(scene.Get()->root_node); + rootNode.Name = Path.GetFileNameWithoutExtension(_filePath); - var missingNormals = false; - var missingTangents = false; - - for (var i = 0u; i < scene.Get()->nodes.count; i++) - { - var data = scene.Get()->nodes.data; - var node = scene.Get()->nodes.data[i]; - if (node->is_root) - { - continue; - } - - if (node->mesh != null) - { - - } - } - - var numIndices = (uint)flatVertices.Count; - - using var weldedIndices = new UnsafeArray((int)numIndices, AllocationHandle.FreeList); - using var cachedIndices = new UnsafeArray((int)numIndices, AllocationHandle.FreeList); - - var stream = new ufbx_vertex_stream - { - data = flatVertices.GetUnsafePtr(), - vertex_count = numIndices, - vertex_size = (nuint)sizeof(Vertex) - }; - - var numUniqueVertices = UfbxApi.GenerateIndices([stream], weldedIndices, null, &error); - if (numUniqueVertices == 0 && error.type != ufbx_error_type.UFBX_ERROR_NONE) - { - _taskCompletionSource.SetResult(Result.Failure($"Welding failed: {error.description}")); - return; - } - - MeshOptApi.OptimizeVertexCache((uint*)cachedIndices.GetUnsafePtr(), (uint*)weldedIndices.GetUnsafePtr(), numIndices, numUniqueVertices); - - vertices = new UnsafeList((int)numUniqueVertices, _allocationHandle); - indices = new UnsafeList((int)numIndices, _allocationHandle); - - var finalVertexCount = MeshOptApi.OptimizeVertexFetch(vertices.GetUnsafePtr(), (uint*)cachedIndices.GetUnsafePtr(), numIndices, flatVertices.GetUnsafePtr(), numIndices, (nuint)sizeof(Vertex)); - - vertices.UnsafeSetCount((int)finalVertexCount); - - MemoryUtility.MemCpy(indices.GetUnsafePtr(), cachedIndices.GetUnsafePtr(), numIndices * sizeof(uint)); - indices.UnsafeSetCount((int)numIndices); - - if (_settings.NormalDataSource == VertexDataSource.Computed || (_settings.NormalDataSource == VertexDataSource.ComputedIfMissing && missingNormals)) - { - MeshBuilder.ComputeNormal(vertices, indices); - } - - if (_settings.TangentDataSource == VertexDataSource.Computed || (_settings.TangentDataSource == VertexDataSource.ComputedIfMissing && missingTangents)) - { - MeshBuilder.ComputeTangents(vertices, indices); - } - - _taskCompletionSource.SetResult(Result.Success()); + _taskCompletionSource.SetResult(Result.Success(rootNode)); } } diff --git a/src/Editor/Ghost.Editor.Core/Assets/MeshProcessor.Meshlet.cs b/src/Editor/Ghost.Editor.Core/Assets/MeshProcessor.Meshlet.cs index 12d69a2..47c6572 100644 --- a/src/Editor/Ghost.Editor.Core/Assets/MeshProcessor.Meshlet.cs +++ b/src/Editor/Ghost.Editor.Core/Assets/MeshProcessor.Meshlet.cs @@ -695,7 +695,13 @@ public static unsafe partial class MeshProcessor return finalClusterCount; } - public static void BuildMeshlets(MeshletMeshData* pMeshletData, ReadOnlyUnsafeCollection vertices, ReadOnlyUnsafeCollection indices) + private struct MeshletContext + { + public MeshletMeshData* data; + public int materialIndex; + } + + public static void BuildMeshlets(MeshletMeshData* pMeshletData, ReadOnlyUnsafeCollection vertices, ReadOnlyUnsafeCollection indices, int materialIndex = 0) { Logger.DebugAssert(pMeshletData->meshletCount > 0, "Mesh must have vertices to build meshlets."); @@ -735,7 +741,13 @@ public static unsafe partial class MeshProcessor attributeProtectMask = 0, // TODO: We need to protect UVs and other vertex attributes to ensure they are not altered during simplification. }; - Build(in config, in clodMesh, pMeshletData, MeshletOutputCallback); + var context = new MeshletContext + { + data = pMeshletData, + materialIndex = materialIndex + }; + + Build(in config, in clodMesh, &context, MeshletOutputCallback); pMeshletData->meshletCount = pMeshletData->meshlets.IsCreated ? pMeshletData->meshlets.Count : 0; @@ -750,12 +762,14 @@ public static unsafe partial class MeshProcessor pMeshletData->lodLevelCount = (int)maxLodLevel + 1; } - pMeshletData->materialSlotCount = 1; + pMeshletData->materialSlotCount = Math.Max(pMeshletData->materialSlotCount, materialIndex + 1); } - private static int MeshletOutputCallback(void* context, ClodGroup group, ReadOnlyUnsafeCollection clusters) + private static int MeshletOutputCallback(void* contextPtr, ClodGroup group, ReadOnlyUnsafeCollection clusters) { - var pMeshletData = (MeshletMeshData*)context; + var context = (MeshletContext*)contextPtr; + var pMeshletData = context->data; + var materialIndex = context->materialIndex; // Ensure lists are initialized if (!pMeshletData->groups.IsCreated) pMeshletData->groups = new UnsafeList(16, AllocationHandle.Persistent); @@ -790,7 +804,7 @@ public static unsafe partial class MeshProcessor groupIndex = (uint)pMeshletData->groups.Count - 1, clusterError = cluster.bounds.error, parentError = group.simplified.error, - localMaterialIndex = 0, // TODO: support multiple materials + localMaterialIndex = (byte)materialIndex, lodLevel = (byte)group.depth, }; pMeshletData->meshlets.Add(meshlet); diff --git a/src/Editor/Ghost.Editor.Core/Assets/TextureProcessor.Compress.cs b/src/Editor/Ghost.Editor.Core/Assets/TextureProcessor.Compress.cs index e6f4635..aa405eb 100644 --- a/src/Editor/Ghost.Editor.Core/Assets/TextureProcessor.Compress.cs +++ b/src/Editor/Ghost.Editor.Core/Assets/TextureProcessor.Compress.cs @@ -1,11 +1,8 @@ using Ghost.Core; using Ghost.Engine; using Ghost.Nvtt; -using Misaki.HighPerformance.Jobs; using Misaki.HighPerformance.LowLevel; -using Misaki.HighPerformance.LowLevel.Buffer; using Misaki.HighPerformance.LowLevel.Collections; -using Misaki.HighPerformance.Mathematics.SPMD; using System.IO.Hashing; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -191,45 +188,63 @@ internal static partial class TextureProcessor pCtx.Get()->SetCudaAcceleration(NvttApi.IsCudaSupported()); - int edgeLength; - using (var cubeSurface0 = new DisposablePtr(NvttCubeSurface.Create())) - using (var mip0Surf = new DisposablePtr(NvttSurface.Create())) + int maxCubeMips = _mipLevels.Length; + var cubeSurfaces = new IntPtr[maxCubeMips]; + + try { - if (!mip0Surf.Get()->SetImageData(NvttInputFormat.NVTT_InputFormat_RGBA_32F, _mipLevels[0].width, _mipLevels[0].height, 1, _mipLevels[0].data.GetUnsafePtr(), false, null)) + for (var level = 0; level < maxCubeMips; level++) { - return Result.Failure("Failed to set image data for NVTT compression."); + var cubeSurf = NvttCubeSurface.Create(); + cubeSurfaces[level] = (IntPtr)cubeSurf; + + using var mipSurf = new DisposablePtr(NvttSurface.Create()); + if (!mipSurf.Get()->SetImageData(NvttInputFormat.NVTT_InputFormat_RGBA_32F, _mipLevels[level].width, _mipLevels[level].height, 1, _mipLevels[level].data.GetUnsafePtr(), false, null)) + { + return Result.Failure("Failed to set image data for NVTT compression."); + } + + if (_settings.Basic.IsSRGB) + { + mipSurf.Get()->ToSrgb(null); + } + + cubeSurf->Fold(mipSurf.Get(), NvttCubeLayout.NVTT_CubeLayout_LatitudeLongitude); } - cubeSurface0.Get()->Fold(mip0Surf.Get(), NvttCubeLayout.NVTT_CubeLayout_LatitudeLongitude); - edgeLength = cubeSurface0.Get()->EdgeLength(); - } - - pCtx.Get()->OutputHeaderData(NvttTextureType.NVTT_TextureType_Cube, edgeLength, edgeLength, 1, _mipLevels.Length, false, pCompOpts.Get(), pOutOpts.Get()); - - for (var level = 0; level < _mipLevels.Length; level++) - { - using var cubeSurface = new DisposablePtr(NvttCubeSurface.Create()); - using var mipSurf = new DisposablePtr(NvttSurface.Create()); - - mipSurf.Get()->SetImageData(NvttInputFormat.NVTT_InputFormat_RGBA_32F, _mipLevels[level].width, _mipLevels[level].height, 1, _mipLevels[level].data.GetUnsafePtr(), false, null); - cubeSurface.Get()->Fold(mipSurf.Get(), NvttCubeLayout.NVTT_CubeLayout_LatitudeLongitude); + var firstCube = (NvttCubeSurface*)cubeSurfaces[0]; + if (!pCtx.Get()->OutputHeaderCube(firstCube, maxCubeMips, pCompOpts.Get(), pOutOpts.Get())) + { + return Result.Failure("Failed to output header for cube map."); + } for (var face = 0; face < 6; face++) { - var faceSurf = cubeSurface.Get()->Face(face); - if (_settings.Basic.IsSRGB) + for (var level = 0; level < maxCubeMips; level++) { - faceSurf->ToSrgb(null); + var cubeSurf = (NvttCubeSurface*)cubeSurfaces[level]; + using var faceSurf = new DisposablePtr(cubeSurf->Face(face)); + + if (!pCtx.Get()->Compress(faceSurf.Get(), face, level, pCompOpts.Get(), pOutOpts.Get())) + { + return Result.Failure("Failed to compress cube map face."); + } } - - if (!pCtx.Get()->Compress(faceSurf, face, level, pCompOpts.Get(), pOutOpts.Get())) + } + } + finally + { + for (var level = 0; level < maxCubeMips; level++) + { + if (cubeSurfaces[level] != IntPtr.Zero) { - return Result.Failure("Failed to compress mipmap."); + var cubeSurf = (NvttCubeSurface*)cubeSurfaces[level]; + cubeSurf->Dispose(); } } } - return Result.Success(_mipLevels.Length); + return Result.Success(maxCubeMips); } public void Execute() @@ -316,7 +331,17 @@ internal static partial class TextureProcessor { if (settings.Basic.TextureShape == TextureShape.TextureCube) { - var handle = GenerateMipHDRI(scheduler, textureInfo, out mipLevels); + int maxCubeMips; + unsafe + { + using var cubeSurface0 = new DisposablePtr(NvttCubeSurface.Create()); + using var mip0Surf = new DisposablePtr(NvttSurface.Create()); + mip0Surf.Get()->SetImageData(NvttInputFormat.NVTT_InputFormat_RGBA_32F, textureInfo.width, textureInfo.height, 1, (void*)textureInfo.pixelData, false, null); + cubeSurface0.Get()->Fold(mip0Surf.Get(), NvttCubeLayout.NVTT_CubeLayout_LatitudeLongitude); + maxCubeMips = (int)Math.Floor(Math.Log2(cubeSurface0.Get()->EdgeLength())) + 1; + } + + var handle = GenerateMipHDRI(scheduler, textureInfo, maxCubeMips, out mipLevels); await scheduler.WaitAsync(handle, cancellationToken); } diff --git a/src/Editor/Ghost.Editor.Core/Assets/TextureProcessor.GGXMip.cs b/src/Editor/Ghost.Editor.Core/Assets/TextureProcessor.GGXMip.cs index 8052671..8ef420a 100644 --- a/src/Editor/Ghost.Editor.Core/Assets/TextureProcessor.GGXMip.cs +++ b/src/Editor/Ghost.Editor.Core/Assets/TextureProcessor.GGXMip.cs @@ -212,6 +212,10 @@ internal static partial class TextureProcessor pData[out_idx] = prefilteredColor.x; pData[out_idx + 1] = prefilteredColor.y; pData[out_idx + 2] = prefilteredColor.z; + if (channelCount == 4) + { + pData[out_idx + 3] = 1.0f; + } } } @@ -251,11 +255,10 @@ internal static partial class TextureProcessor return bits * 2.3283064365386963e-10f; // bits / 0x100000000 } - private static JobHandle GenerateMipHDRI(JobScheduler scheduler, TextureAssetHandler.TextureInfo textureInfo, out UnsafeArray mipLevels) + private static JobHandle GenerateMipHDRI(JobScheduler scheduler, TextureAssetHandler.TextureInfo textureInfo, int totalMipLevels, out UnsafeArray mipLevels) { Logger.DebugAssert(textureInfo.isHDR, "GenerateMipHDRI should only be called for HDR textures."); - - var totalMipLevels = (int)Math.Floor(Math.Log2(Math.Max(textureInfo.width, textureInfo.height))) + 1; + Logger.DebugAssert(textureInfo.colorComponents >= 3, "Texture must have at least 3 color components for RGB."); mipLevels = new UnsafeArray(totalMipLevels, AllocationHandle.FreeList); var radicalInverse_VdCLut = new UnsafeArray(_SAMPLE_COUNT, AllocationHandle.FreeList); diff --git a/src/Editor/Ghost.Editor.Core/Services/ImportCoordinator.cs b/src/Editor/Ghost.Editor.Core/Services/ImportCoordinator.cs index 47bcfe5..4740753 100644 --- a/src/Editor/Ghost.Editor.Core/Services/ImportCoordinator.cs +++ b/src/Editor/Ghost.Editor.Core/Services/ImportCoordinator.cs @@ -159,7 +159,7 @@ internal sealed partial class ImportCoordinator : IDisposable return string.Empty; } - var hash = XxHash128.HashToUInt128(JsonSerializer.SerializeToUtf8Bytes(settings)); + var hash = XxHash128.HashToUInt128(JsonSerializer.SerializeToUtf8Bytes(settings, settings.GetType())); Span bytes = stackalloc byte[16]; Unsafe.WriteUnaligned(ref bytes[0], hash); diff --git a/src/Editor/Ghost.Editor/ActivationHandler.cs b/src/Editor/Ghost.Editor/ActivationHandler.cs index bd9cd21..c230ece 100644 --- a/src/Editor/Ghost.Editor/ActivationHandler.cs +++ b/src/Editor/Ghost.Editor/ActivationHandler.cs @@ -66,13 +66,13 @@ internal static class ActivationHandler AllocationManager.Initialize(opts); - //var assetRegistry = App.GetService(); - //var engineCore = App.GetService(); + var assetRegistry = App.GetService(); + var engineCore = App.GetService(); - //assetRegistry.OnAssetImported += (sender, e) => - //{ - // engineCore.AssetManager.ReimportAsset(e); - //}; + assetRegistry.OnAssetImported += (sender, e) => + { + engineCore.AssetManager.ReimportAsset(e); + }; return ValueTask.CompletedTask; } diff --git a/src/Editor/Ghost.Editor/ViewModels/Controls/ContentBrowserViewModel.cs b/src/Editor/Ghost.Editor/ViewModels/Controls/ContentBrowserViewModel.cs index 1c0ef9e..d6e01a2 100644 --- a/src/Editor/Ghost.Editor/ViewModels/Controls/ContentBrowserViewModel.cs +++ b/src/Editor/Ghost.Editor/ViewModels/Controls/ContentBrowserViewModel.cs @@ -1,13 +1,13 @@ using CommunityToolkit.Mvvm.ComponentModel; +using Ghost.Core.Utilities; using Ghost.Editor.Core; +using Ghost.Editor.Core.Assets; using Ghost.Editor.Core.Contracts; using Ghost.Editor.Core.Utilities; using Ghost.Editor.Models; -using Ghost.Editor.Core.AssetHandler; -using System.Collections.ObjectModel; -using Microsoft.UI.Dispatching; using Ghost.Engine; -using Ghost.Core.Utilities; +using Microsoft.UI.Dispatching; +using System.Collections.ObjectModel; namespace Ghost.Editor.ViewModels.Controls; @@ -69,7 +69,7 @@ internal partial class ContentBrowserViewModel : ObservableObject var fullPath = PathUtility.Normalize(e.AssetPath); var dirPath = Path.GetDirectoryName(fullPath); - + if (string.Equals(dirPath, CurrentDirectoryPath, StringComparison.OrdinalIgnoreCase)) { _dispatcherQueue.TryEnqueue(() => @@ -86,7 +86,7 @@ internal partial class ContentBrowserViewModel : ObservableObject if (!Files.Any(f => string.Equals(f.Path, fullPath, StringComparison.OrdinalIgnoreCase))) { var isDir = Directory.Exists(fullPath); - AssetType assetType = AssetType.Unknown; + var assetType = AssetType.Unknown; if (!isDir) { var ext = Path.GetExtension(fullPath); diff --git a/src/Runtime/Ghost.Generator/AssetHandlerRegistrationGenerator.cs b/src/Runtime/Ghost.Generator/AssetHandlerRegistrationGenerator.cs index cac22a3..46e3f2d 100644 --- a/src/Runtime/Ghost.Generator/AssetHandlerRegistrationGenerator.cs +++ b/src/Runtime/Ghost.Generator/AssetHandlerRegistrationGenerator.cs @@ -33,7 +33,7 @@ internal class AssetHandlerRegistrationGenerator : IIncrementalGenerator foreach (var symbol in array) { - var attribute = symbol.GetAttributes().FirstOrDefault(a => a.AttributeClass?.ToDisplayString() == "Ghost.Editor.Core.AssetHandler.CustomAssetHandlerAttribute"); + var attribute = symbol.GetAttributes().FirstOrDefault(a => a.AttributeClass?.ToDisplayString() == "Ghost.Editor.Core.Assets.CustomAssetHandlerAttribute"); if (attribute == null) { continue; @@ -44,7 +44,7 @@ internal class AssetHandlerRegistrationGenerator : IIncrementalGenerator var extensions = $"new string[] {{ {string.Join(", ", extensionsTypesConstants.Select(v => v.ToCSharpString()))} }}"; var version = (int)attribute.ConstructorArguments[2].Value; - sb.Append($" global::Ghost.Editor.Core.AssetHandler.AssetHandlerRegistry.RegisterHandler(new {symbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)}(), Guid.Parse(\"{id}\"), {extensions}, {version});"); + sb.AppendLine($" global::Ghost.Editor.Core.Assets.AssetHandlerRegistry.RegisterHandler(new {symbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)}(), Guid.Parse(\"{id}\"), {extensions}, {version});"); } var registerTypeName = "g_assethandler_registeration"; @@ -71,7 +71,7 @@ internal static partial class {registerTypeName} return null; } - var iHandlerSymbol = context.SemanticModel.Compilation.GetTypeByMetadataName("Ghost.Editor.Core.AssetHandler.IAssetHandler"); + var iHandlerSymbol = context.SemanticModel.Compilation.GetTypeByMetadataName("Ghost.Editor.Core.Assets.IAssetHandler"); if (iHandlerSymbol == null) { return null; @@ -114,7 +114,7 @@ internal class IAssetSettingsRegistrationGenerator : IIncrementalGenerator foreach (var iface in array) { - sb.AppendLine($" global::Ghost.Editor.Core.AssetHandler.AssetHandlerRegistry.RegisterIAssetSettingsType(typeof({iface.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)}), \"{iface.Name}\");"); + sb.AppendLine($" global::Ghost.Editor.Core.Assets.AssetHandlerRegistry.RegisterIAssetSettingsType(typeof({iface.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)}), \"{iface.Name}\");"); } var registerTypeName = "g_iassetsettings_registeration"; @@ -141,7 +141,7 @@ internal static partial class {registerTypeName} return null; } - var iSettingsSymbol = context.SemanticModel.Compilation.GetTypeByMetadataName("Ghost.Editor.Core.AssetHandler.IAssetSettings"); + var iSettingsSymbol = context.SemanticModel.Compilation.GetTypeByMetadataName("Ghost.Editor.Core.Assets.IAssetSettings"); if (iSettingsSymbol == null) { return null;