TextureAsset properties, start of better asset pipeline detection

This commit is contained in:
Simon Lübeß
2024-06-12 16:51:52 +02:00
parent b3dac4a338
commit 36e98311c6
12 changed files with 267 additions and 48 deletions
+10 -8
View File
@@ -140,7 +140,9 @@ class AssetFile
GenerateAssetHandle();
var assetPipeline = _contentManager.GetDefaultProcessors(fileExtension);
IAssetImporter assetImporter = _contentManager.GetAssetImporter(fileExtension);
IAssetProcessor assetProcessor = ?; //_contentManager.GetAssetProcessor(assetImporter.);
IAssetExporter assetExporter = ?; //_contentManager.GetAssetProcessor(assetImporter.);
// TODO!
//if (assetPipeline case .Err)
@@ -149,7 +151,7 @@ class AssetFile
var assetLoader = _contentManager.GetDefaultAssetLoader(fileExtension);
// We don't have a loader -> we don't need a config
if (assetLoader == null && assetPipeline case .Err)
if (assetLoader == null && assetImporter == null)
return;
if (assetLoader != null)
@@ -162,16 +164,16 @@ class AssetFile
}
_assetConfig.Importer = new String();
assetPipeline?.Importer?.GetType()?.GetName(_assetConfig.Importer);
_assetConfig.ImporterConfig = assetPipeline?.Importer.CreateDefaultConfig();
assetImporter?.GetType()?.GetName(_assetConfig.Importer);
_assetConfig.ImporterConfig = assetImporter?.CreateDefaultConfig();
_assetConfig.Processor = new String();
assetPipeline?.Processor?.GetType()?.GetName(_assetConfig.Processor);
_assetConfig.ProcessorConfig = assetPipeline?.Processor.CreateDefaultConfig();
assetProcessor?.GetType()?.GetName(_assetConfig.Processor);
_assetConfig.ProcessorConfig = assetProcessor.CreateDefaultConfig();
_assetConfig.Exporter = new String();
assetPipeline?.Exporter?.GetType()?.GetName(_assetConfig.Exporter);
_assetConfig.ExporterConfig = assetPipeline?.Exporter.CreateDefaultConfig();
assetExporter?.GetType()?.GetName(_assetConfig.Exporter);
_assetConfig.ExporterConfig = assetExporter.CreateDefaultConfig();
SaveAssetConfig();
}
+32 -15
View File
@@ -5,6 +5,8 @@ using System;
using System.IO;
using GlitchyEngine.Content;
using GlitchyEditor.Assets.Processors;
using System.Threading;
using System.Threading.Tasks;
namespace GlitchyEditor.Assets;
@@ -14,6 +16,8 @@ class AssetConverter
private EditorContentManager _contentManager;
private Dictionary<AssetFile, Task> _processingAssets ~ delete _;
public this(EditorContentManager contentManager)
{
_contentManager = contentManager;
@@ -21,10 +25,10 @@ class AssetConverter
public void QueueForProcessing(AssetFile assetFile, bool isBlocking = false)
{
if (!isBlocking)
_queue.Add(assetFile);
else
if (isBlocking)
Process(assetFile);
else
_queue.Add(assetFile);
}
public void Update()
@@ -44,7 +48,6 @@ class AssetConverter
{
IAssetImporter importer = _contentManager.GetAssetImporter(assetFile);
IAssetProcessor processor = _contentManager.GetAssetProcessor(assetFile);
IAssetExporter exporter = _contentManager.GetAssetExporter(assetFile);
if (importer == null)
{
@@ -58,12 +61,6 @@ class AssetConverter
return;
}
if (exporter == null)
{
Log.EngineLogger.Error("Exporter is null!");
return;
}
Result<ImportedResource> importResult = importer.Import(assetFile.AssetFile.Path,
assetFile.AssetFile.Identifier, assetFile.AssetConfig.ImporterConfig);
@@ -75,7 +72,10 @@ class AssetConverter
defer { delete importResult.Value; }
Result<ProcessedResource> processResult = processor.Process(importResult.Value, assetFile.AssetConfig.ProcessorConfig);
List<ProcessedResource> resources = scope .();
defer { ClearAndDeleteItems!(resources); }
Result<void> processResult = processor.Process(importResult.Value, assetFile.AssetConfig.ProcessorConfig, resources);
if (processResult case .Err)
{
@@ -83,16 +83,30 @@ class AssetConverter
return;
}
defer { delete processResult.Value; }
for (ProcessedResource resource in resources)
{
TrySilent!(ExportResource(assetFile, resource));
}
}
private Result<void> ExportResource(AssetFile assetFile, ProcessedResource resource)
{
IAssetExporter exporter = _contentManager.GetAssetExporter(resource.AssetType);
if (exporter == null)
{
Log.EngineLogger.Error($"No exporter for asset type {resource.AssetType}!");
return .Err;
}
MemoryStream memoryStream = scope .();
Result<void> exportResult = exporter.Export(memoryStream, processResult.Value, assetFile.AssetConfig.ExporterConfig);
Result<void> exportResult = exporter.Export(memoryStream, resource, assetFile.AssetConfig.ExporterConfig);
if (exportResult case .Err)
{
Log.EngineLogger.Error("Failed to export asset!");
return;
return .Err;
}
CachedAsset assetInfo = scope CachedAsset();
@@ -100,11 +114,14 @@ class AssetConverter
assetInfo.CreationTimestamp = DateTime.UtcNow;
assetInfo.Compression = assetFile.AssetConfig.ExporterConfig.Compression;
assetInfo.AssetIdentifier = new AssetIdentifier(assetFile.AssetFile.Identifier);
assetInfo.AssetType = processResult.Value.AssetType;
assetInfo.AssetType = resource.AssetType;
if (_contentManager.AssetCache.SaveAsset(assetInfo, memoryStream.Memory) case .Err)
{
Log.EngineLogger.Error("Failed to write asset to cache.");
return .Err;
}
return .Ok;
}
}
+1 -1
View File
@@ -27,7 +27,7 @@ public class SubAsset
{
public AssetNode Asset;
public String Name ~ delete _;
//public String AssetInternalPath ~ delete _;
public AssetIdentifier Identifier ~ delete _;
public Texture2D PreviewImage ~ _?.ReleaseRef();
}
@@ -4,11 +4,14 @@ using GlitchyEngine.Renderer;
using GlitchyEditor.Assets.Processors;
using GlitchyEngine;
using GlitchyEditor.Assets.Importers;
using GlitchyEngine.Content;
namespace GlitchyEditor.Assets.Exporters;
class TextureExporter : IAssetExporter
{
public static AssetType ExportedAssetType => .Texture;
public AssetExporterConfig CreateDefaultConfig()
{
return new AssetExporterConfig();
+4 -4
View File
@@ -23,13 +23,13 @@ abstract class Config
return true;
}
public abstract void ShowEditor();
public abstract void ShowEditor(AssetFile assetFile);
}
[BonTarget, BonPolyRegister]
class AssetImporterConfig : Config
{
public override void ShowEditor()
public override void ShowEditor(AssetFile assetFile)
{
}
@@ -38,7 +38,7 @@ class AssetImporterConfig : Config
[BonTarget, BonPolyRegister]
class AssetProcessorConfig : Config
{
public override void ShowEditor()
public override void ShowEditor(AssetFile assetFile)
{
}
@@ -56,7 +56,7 @@ class AssetExporterConfig : Config
set => SetIfChanged(ref _compression, value);
}
public override void ShowEditor()
public override void ShowEditor(AssetFile assetFile)
{
ImGui.PropertyTableStartNewProperty("Compression");
ImGui.AttachTooltip("Specifies the compression method used to compress the processed asset.");
@@ -12,6 +12,9 @@ interface IAssetImporter
AssetImporterConfig CreateDefaultConfig();
/// The type that ImportedResource returns.
static Type ProcessedAssetType { get; }
Result<ImportedResource> Import(StringView fullFileName, AssetIdentifier assetIdentifier, AssetImporterConfig config);
}
@@ -19,12 +22,18 @@ interface IAssetProcessor
{
AssetProcessorConfig CreateDefaultConfig();
Result<ProcessedResource> Process(ImportedResource importedResource, AssetProcessorConfig config);
/// The asset type that this processor can process.
static Type ProcessedAssetType { get; }
Result<void> Process(ImportedResource importedResource, AssetProcessorConfig config, List<ProcessedResource> outProcessedResources);
}
interface IAssetExporter
{
AssetExporterConfig CreateDefaultConfig();
/// The asset type that this exporter can export.
static AssetType ExportedAssetType { get; }
Result<void> Export(Stream stream, ProcessedResource processedObject, AssetExporterConfig config);
}
@@ -40,7 +40,7 @@ class TextureImporterConfig : AssetImporterConfig
set => SetIfChanged(ref _isSrgb, value);
}
public override void ShowEditor()
public override void ShowEditor(AssetFile assetFile)
{
ImGui.PropertyTableStartNewProperty("Is sRGB");
ImGui.AttachTooltip("If checked, the texture will be forced to be imported as sRGB. Refer to the documentation for an detailed explanation what you should do here.");
@@ -5,6 +5,8 @@ using GlitchyEngine.Renderer;
using GlitchyEngine.Content;
using GlitchyEngine;
using ImGui;
using System.Collections;
using GlitchyEngine.Math;
namespace GlitchyEditor.Assets.Processors;
@@ -16,15 +18,28 @@ enum GenerateMipMaps
Kaiser
}
enum TextureType
{
Texture,
Sprite
}
[BonTarget, BonPolyRegister]
class TextureProcessorConfig : AssetProcessorConfig
{
[BonInclude]
private GenerateMipMaps _generateMipMaps;
private GenerateMipMaps _generateMipMaps = .No;
[BonInclude]
private SamplerStateDescription _samplerStateDescription = .();
[BonInclude]
private TextureType _textureType = .Texture;
[BonInclude]
private List<SpriteDesc> _sprites = new .() ~ DeleteContainerAndItems!(_);
public GenerateMipMaps GenerateMipMaps
{
get => _generateMipMaps;
@@ -37,8 +52,63 @@ class TextureProcessorConfig : AssetProcessorConfig
set => SetIfChanged(ref _samplerStateDescription, value);
}
public override void ShowEditor()
public TextureType TextureType
{
get => _textureType;
set => SetIfChanged(ref _textureType, value);
}
public List<SpriteDesc> Sprites => _sprites;
public override void ShowEditor(AssetFile assetFile)
{
if (ImGui.BeginPopupModal("Apply Changes", null, .AlwaysAutoResize))
{
ImGui.Text("The changes have to be applied before you can open the sprite editor.\nDo you want to apply the changes and continue?");
if (ImGui.Button("Apply"))
{
assetFile.SaveAssetConfig();
ImGui.CloseCurrentPopup();
new SpriteEditor(Editor.Instance, assetFile.AssetConfig.AssetHandle);
}
ImGui.SameLine();
if (ImGui.Button("Cancel"))
{
ImGui.CloseCurrentPopup();
}
ImGui.EndPopup();
}
ImGui.PropertyTableStartNewProperty("Texture Type");
TextureType textureType = _textureType;
if (ImGui.EnumCombo("##textureType", ref textureType))
{
TextureType = textureType;
}
ImGui.PropertyTableStartNewRow();
if (textureType == .Sprite)
{
if (ImGui.Button("Open Sprite Editor..."))
{
if (_changed)
{
ImGui.OpenPopup("Apply Changes");
}
else
{
new SpriteEditor(Editor.Instance, assetFile.AssetConfig.AssetHandle);
}
}
}
ImGui.PropertyTableStartNewProperty("Generate Mip Maps", "Specifies the algorithm used to generate mip maps for this texture.");
ImGui.BeginDisabled();
@@ -157,6 +227,14 @@ class TextureProcessorConfig : AssetProcessorConfig
}
}
public class SpriteDesc
{
public String Name ~ delete _;
public int2 TopLeft;
public int2 Size;
public AssetHandle AssetHandle;
}
class ProcessedTexture : ProcessedResource
{
public Format PixelFormat = .Unknown;
@@ -276,22 +354,46 @@ class ProcessedTexture : ProcessedResource
}
}
class ProcessedSprite : ProcessedResource
{
public override AssetType AssetType => .Sprite;
private AssetHandle _texture;
private int2 _topLeft;
private int2 _size;
public AssetHandle Texture => _texture;
public int2 TopLeft => _topLeft;
public int2 Size => _size;
public this(AssetIdentifier ownAssetIdentifier, AssetHandle texture, int2 topLeft, int2 size) : base(ownAssetIdentifier)
{
_texture = texture;
_topLeft = topLeft;
_size = size;
}
}
class TextureProcessor : IAssetProcessor
{
public static Type ProcessedAssetType => typeof(ImportedTexture);
public AssetProcessorConfig CreateDefaultConfig()
{
return new TextureProcessorConfig();
}
public Result<ProcessedResource> Process(ImportedResource importedObject, AssetProcessorConfig config)
public Result<void> Process(ImportedResource importedObject, AssetProcessorConfig 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));
return Try!(ProcessTexture(importedObject as ImportedTexture, config as TextureProcessorConfig, outProcessedResources));
}
private Result<ProcessedTexture> ProcessTexture(ImportedTexture importedTexture, TextureProcessorConfig config)
private Result<void> ProcessTexture(ImportedTexture importedTexture, TextureProcessorConfig config, List<ProcessedResource> outProcessedResources)
{
ProcessedTexture processedTexture = new ProcessedTexture(new AssetIdentifier(importedTexture.AssetIdentifier.FullIdentifier));
@@ -322,8 +424,31 @@ class TextureProcessor : IAssetProcessor
}
// TODO: Pack to BC-Format or what ever was selected.
if (config.TextureType == .Sprite)
{
}
return processedTexture;
return .Ok;
}
private void CreateSprites(ProcessedTexture processedTexture, TextureProcessorConfig config, List<ProcessedResource> outProcessedResources)
{
if (processedTexture.Dimension != .Texture2D)
{
Log.ClientLogger.Error("Only 2D textures can be used as sprites.");
return;
}
if (config.Sprites.Count == 0)
{
/*ProcessedSprite sprite = new ProcessedSprite(processedTexture.);
processedTexture.Sprites.Add(new SpriteDesc(){
Name = new String("Sprite"),
TopLeft = .(0, 0),
Size = .((.)processedTexture.Width, (.)processedTexture.Height)
});*/
}
}
private int CalculateMipMapCount(int width, int height, int depth)
+21
View File
@@ -0,0 +1,21 @@
using System;
using GlitchyEditor.EditWindows;
using GlitchyEngine.Content;
using ImGui;
namespace GlitchyEditor.Assets;
class SpriteEditor : ClosableWindow
{
AssetHandle _assetHandle;
public this(Editor editor, AssetHandle assetHandle) : base(editor, "Sprite Editor")
{
_assetHandle = assetHandle;
}
protected override void InternalShow()
{
ImGui.Text("Nothing to see here, yet...");
}
}
@@ -137,9 +137,9 @@ class InspectorWindow : EditorWindow
if (ImGui.BeginPropertyTable("asset_properties", ImGui.GetID("asset_properties")))
{
assetFile.AssetConfig?.ImporterConfig?.ShowEditor();
assetFile.AssetConfig?.ProcessorConfig?.ShowEditor();
assetFile.AssetConfig?.ExporterConfig?.ShowEditor();
assetFile.AssetConfig?.ImporterConfig?.ShowEditor(assetFile);
assetFile.AssetConfig?.ProcessorConfig?.ShowEditor(assetFile);
assetFile.AssetConfig?.ExporterConfig?.ShowEditor(assetFile);
ImGui.EndTable();
+47 -6
View File
@@ -219,10 +219,14 @@ class EditorContentManager : IContentManager
};
private append List<IAssetImporter> _assetImporters = .() ~ ClearAndDeleteItems!(_);
private append Dictionary<StringView, IAssetImporter> _extensionToAssetImporter = .();
private append List<IAssetProcessor> _assetProcessors = .() ~ ClearAndDeleteItems!(_);
private append List<IAssetExporter> _assetExporters = .() ~ ClearAndDeleteItems!(_);
private append Dictionary<Type, IAssetProcessor> _importedResourceToAssetProcessor = .();
//private append List<IAssetExporter> _assetExporters = .() ~ ClearAndDeleteItems!(_);
private append Dictionary<StringView, (IAssetImporter Importer, IAssetProcessor Processor, IAssetExporter Exporter)> _defaultAssetProcessors = .() ~ delete:append _;
private append Dictionary<AssetType, IAssetExporter> _assetExporters = .() ~ ClearDictionaryAndDeleteValues!(_);
public void RegisterAssetLoader<T>() where T : new, class, IAssetLoader
{
// Log.EngineLogger.AssertDebug(!_assetLoaders.Any((l) => l.GetType() == typeof(T)), "Asset loader already registered.");
@@ -242,7 +246,11 @@ class EditorContentManager : IContentManager
_assetImporters.Add(assetImporter);
for (StringView ext in T.FileExtensions)
_supportedExtensions.Add(new String(ext));
{
String fileExtension = new String(ext);
_supportedExtensions.Add(fileExtension);
_extensionToAssetImporter.Add(fileExtension, assetImporter);
}
}
public void RegisterAssetProcessor<T>() where T : new, class, IAssetProcessor
@@ -256,7 +264,29 @@ class EditorContentManager : IContentManager
{
T assetExporter = new T();
_assetExporters.Add(assetExporter);
Log.EngineLogger.AssertDebug(_assetExporters.ContainsKey(T.ExportedAssetType), "Cannot register multiple exporters for one asset type.");
_assetExporters.Add(T.ExportedAssetType, assetExporter);
}
public IAssetImporter GetAssetImporter(StringView fileExtension)
{
if (_extensionToAssetImporter.TryGetValue(fileExtension, let importer))
{
return importer;
}
return null;
}
public IAssetImporter GetAssetProcessor(Type importedResourceType)
{
if (_extensionToAssetImporter.TryGetValue(fileExtension, let importer))
{
return importer;
}
return null;
}
public void SetAsDefaultAssetLoader<T>(params Span<StringView> fileExtensions) where T : IAssetLoader
@@ -332,14 +362,15 @@ class EditorContentManager : IContentManager
}
}
for (var i in _assetExporters)
// TODO: How do we get the exporter for the config?
/*for (var i in _assetExporters)
{
if (i.GetType() == typeof(TExport))
{
exporter = i;
break;
}
}
}*/
_defaultAssetProcessors[foundExtension] = (importer, processor, exporter);
}
@@ -756,7 +787,7 @@ class EditorContentManager : IContentManager
return result;
}
/*
public IAssetExporter GetAssetExporter(AssetFile file)
{
IAssetExporter result = null;
@@ -776,6 +807,16 @@ class EditorContentManager : IContentManager
return result;
}
*/
public IAssetExporter GetAssetExporter(AssetType assetType)
{
if (_assetExporters.TryGetValue(assetType, let exporter))
{
return exporter;
}
return null;
}
public enum SaveAssetError
{
+2 -1
View File
@@ -3,5 +3,6 @@ namespace GlitchyEngine.Content;
enum AssetType : uint16
{
Unknown,
Texture
Texture,
Sprite
}