Better asset processor selection, process subassets

This commit is contained in:
Simon Lübeß
2024-06-13 15:44:27 +02:00
parent 36e98311c6
commit cd434d64f9
22 changed files with 356 additions and 292 deletions
+48 -27
View File
@@ -46,36 +46,21 @@ class AssetConverter
private void Process(AssetFile assetFile)
{
IAssetImporter importer = _contentManager.GetAssetImporter(assetFile);
IAssetProcessor processor = _contentManager.GetAssetProcessor(assetFile);
Result<ImportedResource> importResult = ImportResource(assetFile);
if (importer == null)
{
Log.EngineLogger.Error("Importer is null!");
return;
}
if (processor == null)
{
Log.EngineLogger.Error("Processor is null!");
return;
}
ImportedResource importedResource = null;
defer { delete importedResource; }
Result<ImportedResource> importResult = importer.Import(assetFile.AssetFile.Path,
assetFile.AssetFile.Identifier, assetFile.AssetConfig.ImporterConfig);
if (importResult case .Err)
if (!(importResult case .Ok(out importedResource)))
{
Log.EngineLogger.Error("Failed to import asset!");
return;
}
defer { delete importResult.Value; }
List<ProcessedResource> processedResources = scope .();
defer { ClearAndDeleteItems!(processedResources); }
List<ProcessedResource> resources = scope .();
defer { ClearAndDeleteItems!(resources); }
Result<void> processResult = processor.Process(importResult.Value, assetFile.AssetConfig.ProcessorConfig, resources);
Result<void> processResult = ProcessResource(assetFile, importedResource, processedResources);
if (processResult case .Err)
{
@@ -83,12 +68,41 @@ class AssetConverter
return;
}
for (ProcessedResource resource in resources)
for (ProcessedResource resource in processedResources)
{
TrySilent!(ExportResource(assetFile, resource));
if (ExportResource(assetFile, resource) case .Err)
{
Log.EngineLogger.Error("Failed to export asset.");
}
}
}
private Result<ImportedResource> ImportResource(AssetFile assetFile)
{
IAssetImporter importer = _contentManager.GetAssetImporter(assetFile);
if (importer == null)
{
Log.EngineLogger.Error("Importer is null!");
return .Err;
}
return importer.Import(assetFile.AssetFile.Path, assetFile.AssetFile.Identifier, assetFile.AssetConfig);
}
private Result<void> ProcessResource(AssetFile assetFile, ImportedResource importedResource, List<ProcessedResource> outProcessedResources)
{
IAssetProcessor processor = _contentManager.GetAssetProcessor(importedResource.GetType());
if (processor == null)
{
Log.EngineLogger.Error($"No asset processor for type {importedResource.GetType()} found.");
return .Err;
}
return processor.Process(importedResource, assetFile.AssetConfig, outProcessedResources);
}
private Result<void> ExportResource(AssetFile assetFile, ProcessedResource resource)
{
IAssetExporter exporter = _contentManager.GetAssetExporter(resource.AssetType);
@@ -101,7 +115,7 @@ class AssetConverter
MemoryStream memoryStream = scope .();
Result<void> exportResult = exporter.Export(memoryStream, resource, assetFile.AssetConfig.ExporterConfig);
Result<void> exportResult = exporter.Export(memoryStream, resource, assetFile.AssetConfig);
if (exportResult case .Err)
{
@@ -109,11 +123,16 @@ class AssetConverter
return .Err;
}
if (assetFile.AssetConfig.ExporterConfig == null)
{
assetFile.AssetConfig.ExporterConfig = new AssetExporterConfig();
}
CachedAsset assetInfo = scope CachedAsset();
assetInfo.Handle = assetFile.AssetConfig.AssetHandle;
assetInfo.Handle = resource.AssetHandle;
assetInfo.CreationTimestamp = DateTime.UtcNow;
assetInfo.Compression = assetFile.AssetConfig.ExporterConfig.Compression;
assetInfo.AssetIdentifier = new AssetIdentifier(assetFile.AssetFile.Identifier);
assetInfo.AssetIdentifier = new AssetIdentifier(resource.AssetIdentifier);
assetInfo.AssetType = resource.AssetType;
if (_contentManager.AssetCache.SaveAsset(assetInfo, memoryStream.Memory) case .Err)
@@ -122,6 +141,8 @@ class AssetConverter
return .Err;
}
assetFile.SaveAssetConfigIfChanged();
return .Ok;
}
}
+1
View File
@@ -2,6 +2,7 @@ using System;
using System.Collections;
using GlitchyEngine.Renderer;
using GlitchyEngine.Content;
namespace GlitchyEditor.Assets;
// TODO: Why exactly are AssetFile and AssetNode separated?
@@ -0,0 +1,39 @@
using System;
using System.IO;
using GlitchyEngine.Renderer;
using GlitchyEditor.Assets.Processors;
using GlitchyEngine;
using GlitchyEditor.Assets.Importers;
using GlitchyEngine.Content;
namespace GlitchyEditor.Assets.Exporters;
class SpriteExporter : IAssetExporter
{
public static AssetType ExportedAssetType => .Sprite;
public AssetExporterConfig CreateDefaultConfig()
{
return new AssetExporterConfig();
}
public Result<void> Export(Stream stream, ProcessedResource processedResource, AssetConfig config)
{
Log.EngineLogger.AssertDebug(processedResource is ProcessedSprite);
ProcessedSprite processedSprite = (.)processedResource;
/*
File Format:
TextureHandle (8 bytes)
TextureCoords (16 bytes) [float4]
*/
Try!(stream.Write(processedSprite.TextureHandle));
Try!(stream.Write(processedSprite.TextureCoordinates));
return .Ok;
}
}
@@ -17,7 +17,7 @@ class TextureExporter : IAssetExporter
return new AssetExporterConfig();
}
public Result<void> Export(Stream stream, ProcessedResource processedResource, AssetExporterConfig config)
public Result<void> Export(Stream stream, ProcessedResource processedResource, AssetConfig config)
{
Log.EngineLogger.AssertDebug(processedResource is ProcessedTexture);
+1 -1
View File
@@ -8,7 +8,7 @@ namespace GlitchyEditor.Assets.Importers;
abstract class Config
{
[BonIgnore]
protected bool _changed;
protected bool _changed = true;
public bool Changed => _changed;
@@ -15,7 +15,7 @@ interface IAssetImporter
/// The type that ImportedResource returns.
static Type ProcessedAssetType { get; }
Result<ImportedResource> Import(StringView fullFileName, AssetIdentifier assetIdentifier, AssetImporterConfig config);
Result<ImportedResource> Import(StringView fullFileName, AssetIdentifier assetIdentifier, AssetConfig config);
}
interface IAssetProcessor
@@ -25,7 +25,7 @@ interface IAssetProcessor
/// The asset type that this processor can process.
static Type ProcessedAssetType { get; }
Result<void> Process(ImportedResource importedResource, AssetProcessorConfig config, List<ProcessedResource> outProcessedResources);
Result<void> Process(ImportedResource importedResource, AssetConfig config, List<ProcessedResource> outProcessedResources);
}
interface IAssetExporter
@@ -35,5 +35,5 @@ interface IAssetExporter
/// The asset type that this exporter can export.
static AssetType ExportedAssetType { get; }
Result<void> Export(Stream stream, ProcessedResource processedObject, AssetExporterConfig config);
Result<void> Export(Stream stream, ProcessedResource processedObject, AssetConfig config);
}
@@ -6,6 +6,7 @@ using GlitchyEngine.Content;
using GlitchyEngine;
using GlitchyEngine.Renderer;
using GlitchyEngine.Math;
//using System.Threading;
using GlitchyEditor.Assets.Processors;
using ImGui;
@@ -53,22 +54,29 @@ class TextureImporterConfig : AssetImporterConfig
}
}
class TextureImporter : IAssetImporter
{
private static readonly List<StringView> _fileExtensions = new .(){".png", ".dds"} ~ delete _;
public static List<StringView> FileExtensions => _fileExtensions;
public static Type ProcessedAssetType => typeof(ImportedTexture);
public AssetImporterConfig CreateDefaultConfig()
{
return new TextureImporterConfig();
}
public Result<ImportedResource> Import(StringView fullFileName, AssetIdentifier assetIdentifier, AssetImporterConfig config)
public Result<ImportedResource> Import(StringView fullFileName, AssetIdentifier assetIdentifier, AssetConfig config)
{
//Thread.Sleep(1000);
Log.EngineLogger.AssertDebug(config is TextureImporterConfig);
TextureImporterConfig textureImporterConfig = config.ImporterConfig as TextureImporterConfig;
if (textureImporterConfig == null)
{
config.ImporterConfig = textureImporterConfig = new TextureImporterConfig();
}
ImportedTexture importedData = new ImportedTexture(new AssetIdentifier(assetIdentifier.FullIdentifier));
@@ -76,7 +84,7 @@ class TextureImporter : IAssetImporter
FileStream stream = scope FileStream();
Try!(stream.Open(fullFileName, .Read, .Read));
Result<void> importResult = ImportTexture(stream, importedData, (TextureImporterConfig)config);
Result<void> importResult = ImportTexture(stream, importedData, (TextureImporterConfig)textureImporterConfig);
stream.Close();
@@ -6,12 +6,17 @@ abstract class ProcessedResource
{
private AssetIdentifier _assetIdentifier ~ delete _;
private AssetHandle _assetHandle;
public AssetIdentifier AssetIdentifier => _assetIdentifier;
public AssetHandle AssetHandle => _assetHandle;
public abstract AssetType AssetType {get;}
public this(AssetIdentifier ownAssetIdentifier)
public this(AssetIdentifier ownAssetIdentifier, AssetHandle assetHandle)
{
_assetIdentifier = ownAssetIdentifier;
_assetHandle = assetHandle;
}
}
@@ -60,6 +60,12 @@ class TextureProcessorConfig : AssetProcessorConfig
public List<SpriteDesc> Sprites => _sprites;
public void AddSprite(SpriteDesc sprite)
{
_sprites.Add(sprite);
_changed = true;
}
public override void ShowEditor(AssetFile assetFile)
{
if (ImGui.BeginPopupModal("Apply Changes", null, .AlwaysAutoResize))
@@ -227,11 +233,18 @@ class TextureProcessorConfig : AssetProcessorConfig
}
}
[BonTarget]
enum TextureCoordinates
{
case Pixel(int2 Min, int2 Max);
case Relative(float2 Offset, float2 Size);
}
[BonTarget]
public class SpriteDesc
{
public String Name ~ delete _;
public int2 TopLeft;
public int2 Size;
public TextureCoordinates TextureCoordinates;
public AssetHandle AssetHandle;
}
@@ -308,7 +321,7 @@ class ProcessedTexture : ProcessedResource
public TextureSurface[,] Surfaces;
public this(AssetIdentifier ownAssetIdentifier) : base(ownAssetIdentifier)
public this(AssetIdentifier ownAssetIdentifier, AssetHandle assetHandle) : base(ownAssetIdentifier, assetHandle)
{
}
@@ -358,21 +371,18 @@ class ProcessedSprite : ProcessedResource
{
public override AssetType AssetType => .Sprite;
private AssetHandle _texture;
private AssetHandle Handle;
private int2 _topLeft;
private int2 _size;
private float4 _textureCoordinates;
public AssetHandle Texture => _texture;
public AssetHandle TextureHandle => Handle;
public int2 TopLeft => _topLeft;
public int2 Size => _size;
public float4 TextureCoordinates => _textureCoordinates;
public this(AssetIdentifier ownAssetIdentifier, AssetHandle texture, int2 topLeft, int2 size) : base(ownAssetIdentifier)
public this(AssetIdentifier ownAssetIdentifier, AssetHandle assetHandle, AssetHandle textureHandle, float4 textureCoordinates) : base(ownAssetIdentifier, assetHandle)
{
_texture = texture;
_topLeft = topLeft;
_size = size;
Handle = textureHandle;
_textureCoordinates = textureCoordinates;
}
}
@@ -385,17 +395,23 @@ class TextureProcessor : IAssetProcessor
return new TextureProcessorConfig();
}
public Result<void> Process(ImportedResource importedObject, AssetProcessorConfig config, List<ProcessedResource> outProcessedResources)
public Result<void> Process(ImportedResource importedObject, AssetConfig config, List<ProcessedResource> outProcessedResources)
{
Log.EngineLogger.AssertDebug(config is TextureProcessorConfig);
Log.EngineLogger.AssertDebug(importedObject is ImportedTexture);
return Try!(ProcessTexture(importedObject as ImportedTexture, config as TextureProcessorConfig, outProcessedResources));
TextureProcessorConfig textureProcessorConfig = config.ProcessorConfig as TextureProcessorConfig;
if (textureProcessorConfig == null)
{
config.ProcessorConfig = textureProcessorConfig = new TextureProcessorConfig();
}
return Try!(ProcessTexture(importedObject as ImportedTexture, config, textureProcessorConfig, outProcessedResources));
}
private Result<void> ProcessTexture(ImportedTexture importedTexture, TextureProcessorConfig config, List<ProcessedResource> outProcessedResources)
private Result<void> ProcessTexture(ImportedTexture importedTexture, AssetConfig assetConfig, TextureProcessorConfig textureConfig, List<ProcessedResource> outProcessedResources)
{
ProcessedTexture processedTexture = new ProcessedTexture(new AssetIdentifier(importedTexture.AssetIdentifier.FullIdentifier));
ProcessedTexture processedTexture = new ProcessedTexture(new AssetIdentifier(importedTexture.AssetIdentifier.FullIdentifier), assetConfig.AssetHandle);
processedTexture.Dimension = importedTexture.TextureInfo.Dimension;
processedTexture.PixelFormat = (.)importedTexture.TextureInfo.PixelFormat;
@@ -404,7 +420,7 @@ class TextureProcessor : IAssetProcessor
processedTexture.Height = importedTexture.TextureInfo.Height;
processedTexture.Depth = importedTexture.TextureInfo.Depth;
processedTexture.SamplerStateDescription = config.SamplerStateDescription;
processedTexture.SamplerStateDescription = textureConfig.SamplerStateDescription;
processedTexture.SetSurfaceCount(importedTexture.TextureInfo.ArraySize, importedTexture.TextureInfo.MipMapCount);
@@ -416,22 +432,25 @@ class TextureProcessor : IAssetProcessor
processedTexture.Surfaces[loadedSurface.ArrayIndex * (processedTexture.IsCubeMap ? 6 : 1) + loadedSurface.CubeFace, loadedSurface.MipLevel] = surface;
}
if (!(config.GenerateMipMaps case .No))
if (!(textureConfig.GenerateMipMaps case .No))
{
// TODO: Unpack BC-Formats to RGBA
GenerateMipMaps(processedTexture, config);
GenerateMipMaps(processedTexture, textureConfig);
}
outProcessedResources.Add(processedTexture);
// TODO: Pack to BC-Format or what ever was selected.
if (config.TextureType == .Sprite)
if (textureConfig.TextureType == .Sprite)
{
CreateSprites(processedTexture, textureConfig, outProcessedResources);
}
return .Ok;
}
private void CreateSprites(ProcessedTexture processedTexture, TextureProcessorConfig config, List<ProcessedResource> outProcessedResources)
private void CreateSprites(ProcessedTexture processedTexture, TextureProcessorConfig textureConfig, List<ProcessedResource> outProcessedResources)
{
if (processedTexture.Dimension != .Texture2D)
{
@@ -439,15 +458,41 @@ class TextureProcessor : IAssetProcessor
return;
}
if (config.Sprites.Count == 0)
if (textureConfig.Sprites.Count == 0)
{
/*ProcessedSprite sprite = new ProcessedSprite(processedTexture.);
processedTexture.Sprites.Add(new SpriteDesc(){
textureConfig.AddSprite(new SpriteDesc(){
Name = new String("Sprite"),
TopLeft = .(0, 0),
Size = .((.)processedTexture.Width, (.)processedTexture.Height)
});*/
// TODO: Maybe add a switch for pixel perfect or relative texture coordinates
TextureCoordinates = .Pixel(.(0, 0), .((.)processedTexture.Width, (.)processedTexture.Height)),
// TODO: Get handle from central authority (contentmanager?)
AssetHandle = AssetHandle()
});
}
float2 textureResolution = .(processedTexture.Width, processedTexture.Height);
for (SpriteDesc spriteDesc in textureConfig.Sprites)
{
float4 textureCoordinates = .();
if (spriteDesc.TextureCoordinates case .Pixel(let min, let max))
{
textureCoordinates = float4((float2)min / textureResolution, (float2)max / textureResolution);
}
else if (spriteDesc.TextureCoordinates case .Relative(let offset, let size))
{
textureCoordinates = .(offset, size);
}
else
{
Log.EngineLogger.Error($"Unknown texture coordinate type {spriteDesc.TextureCoordinates}");
return;
}
ProcessedSprite sprite = new ProcessedSprite(new AssetIdentifier(processedTexture.AssetIdentifier, spriteDesc.Name), spriteDesc.AssetHandle, processedTexture.AssetHandle,
textureCoordinates);
outProcessedResources.Add(sprite);
}
}