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
This commit is contained in:
2026-04-26 14:49:58 +09:00
parent 1a91811621
commit 5903ddda2b
8 changed files with 218 additions and 169 deletions

View File

@@ -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<MeshNode>();
var meshNode = new MeshNode
{
Name = pMesh->name.ToString(),
Children = Array.Empty<MeshNode>(),
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<GeometryMeshNode> ParseGeometry(ufbx_mesh* pMesh)
{
var resultNodes = new List<GeometryMeshNode>();
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<Vertex>[numMaterials];
var missingNormalsBucket = new bool[numMaterials];
var missingTangentsBucket = new bool[numMaterials];
using var flatVertices = new UnsafeList<Vertex>(1024, AllocationHandle.FreeList);
for (int i = 0; i < numMaterials; i++)
{
materialBuckets[i] = new UnsafeList<Vertex>(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<uint>((int)numIndices, AllocationHandle.FreeList);
using var cachedIndices = new UnsafeArray<uint>((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<uint>((int)numIndices, AllocationHandle.FreeList);
using var cachedIndices = new UnsafeArray<uint>((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<Vertex>((int)numUniqueVertices, _allocationHandle);
var nodeIndices = new UnsafeList<uint>((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<MeshNode>(),
Vertices = nodeVertices,
Indices = nodeIndices,
MaterialIndex = m
};
resultNodes.Add(meshNode);
flatVertices.Dispose();
}
MeshOptApi.OptimizeVertexCache((uint*)cachedIndices.GetUnsafePtr(), (uint*)weldedIndices.GetUnsafePtr(), numIndices, numUniqueVertices);
vertices = new UnsafeList<Vertex>((int)numUniqueVertices, _allocationHandle);
indices = new UnsafeList<uint>((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<Vertex>(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<uint>((int)numIndices, AllocationHandle.FreeList);
using var cachedIndices = new UnsafeArray<uint>((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<Vertex>((int)numUniqueVertices, _allocationHandle);
indices = new UnsafeList<uint>((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<MeshNode>.Success(rootNode));
}
}

View File

@@ -695,7 +695,13 @@ public static unsafe partial class MeshProcessor
return finalClusterCount;
}
public static void BuildMeshlets(MeshletMeshData* pMeshletData, ReadOnlyUnsafeCollection<Vertex> vertices, ReadOnlyUnsafeCollection<uint> indices)
private struct MeshletContext
{
public MeshletMeshData* data;
public int materialIndex;
}
public static void BuildMeshlets(MeshletMeshData* pMeshletData, ReadOnlyUnsafeCollection<Vertex> vertices, ReadOnlyUnsafeCollection<uint> 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<ClodCluster> clusters)
private static int MeshletOutputCallback(void* contextPtr, ClodGroup group, ReadOnlyUnsafeCollection<ClodCluster> 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<MeshletGroup>(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);

View File

@@ -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>(NvttCubeSurface.Create()))
using (var mip0Surf = new DisposablePtr<NvttSurface>(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<int>("Failed to set image data for NVTT compression.");
var cubeSurf = NvttCubeSurface.Create();
cubeSurfaces[level] = (IntPtr)cubeSurf;
using var mipSurf = new DisposablePtr<NvttSurface>(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>(NvttCubeSurface.Create());
using var mipSurf = new DisposablePtr<NvttSurface>(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<NvttSurface>(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>(NvttCubeSurface.Create());
using var mip0Surf = new DisposablePtr<NvttSurface>(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);
}

View File

@@ -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<MipLevel> mipLevels)
private static JobHandle GenerateMipHDRI(JobScheduler scheduler, TextureAssetHandler.TextureInfo textureInfo, int totalMipLevels, out UnsafeArray<MipLevel> 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<MipLevel>(totalMipLevels, AllocationHandle.FreeList);
var radicalInverse_VdCLut = new UnsafeArray<float>(_SAMPLE_COUNT, AllocationHandle.FreeList);

View File

@@ -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<byte> bytes = stackalloc byte[16];
Unsafe.WriteUnaligned(ref bytes[0], hash);

View File

@@ -66,13 +66,13 @@ internal static class ActivationHandler
AllocationManager.Initialize(opts);
//var assetRegistry = App.GetService<IAssetRegistry>();
//var engineCore = App.GetService<EngineCore>();
var assetRegistry = App.GetService<IAssetRegistry>();
var engineCore = App.GetService<EngineCore>();
//assetRegistry.OnAssetImported += (sender, e) =>
//{
// engineCore.AssetManager.ReimportAsset(e);
//};
assetRegistry.OnAssetImported += (sender, e) =>
{
engineCore.AssetManager.ReimportAsset(e);
};
return ValueTask.CompletedTask;
}

View File

@@ -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);

View File

@@ -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;