From 108b31399a157c75e4205f7d27d3f28954e4a69f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20L=C3=BCbe=C3=9F?= Date: Mon, 3 Jun 2024 00:45:25 +0200 Subject: [PATCH] Use asset pipeline for blocking asset loading, remove old texture loader --- .gitignore | 2 + .../resources/Textures/EditorIcons.dds.ass | 19 +- GlitchyEditor/src/AssetFile.bf | 15 +- GlitchyEditor/src/Assets/AssetCache.bf | 63 +- GlitchyEditor/src/Assets/AssetConverter.bf | 7 +- GlitchyEditor/src/Assets/AssetHierarchy.bf | 4 +- .../src/Assets/TextureAssetLoader.bf | 596 ------------------ GlitchyEditor/src/EditorApp.bf | 10 +- GlitchyEditor/src/EditorContentManager.bf | 50 +- GlitchyEditor/src/EditorLayer.bf | 2 +- GlitchyEngine/src/Content/AssetIdentifier.bf | 9 + 11 files changed, 134 insertions(+), 643 deletions(-) delete mode 100644 GlitchyEditor/src/Assets/TextureAssetLoader.bf diff --git a/.gitignore b/.gitignore index 44d0eff..7fd146b 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,5 @@ GlitchyEditor/MonoDebugger.log # Ignore files in build-directory of ScriptCore GlitchyEditor/Resources/Scripts/* + +.cache diff --git a/GlitchyEditor/resources/Textures/EditorIcons.dds.ass b/GlitchyEditor/resources/Textures/EditorIcons.dds.ass index 0a04a8a..efb64cf 100644 --- a/GlitchyEditor/resources/Textures/EditorIcons.dds.ass +++ b/GlitchyEditor/resources/Textures/EditorIcons.dds.ass @@ -1,14 +1,23 @@ { - AssetLoader = "EditorTextureAssetLoader", - Config = (GlitchyEditor.Assets.EditorTextureAssetLoaderConfig){ + AssetLoader = null, + Config = null, + Importer = "TextureImporter", + ImporterConfig = (GlitchyEditor.Assets.Importers.TextureImporterConfig){ + _isSrgb = false + }, + Processor = "TextureProcessor", + ProcessorConfig = (GlitchyEditor.Assets.Importers.TextureProcessorConfig){ + _generateMipMaps = .No, _samplerStateDescription = { MinFilter = .Linear, MagFilter = .Linear, MipFilter = .Linear, + FilterMode = .Default, ComparisonFunction = .Never, AddressModeU = .Clamp, AddressModeV = .Clamp, AddressModeW = .Clamp, + MipLODBias = 0, MipMinLOD = -3.40282347e+38, MipMaxLOD = 3.40282347e+38, MaxAnisotropy = 1, @@ -20,5 +29,9 @@ } } }, - AssetHandle = 16828117378770367285 + Exporter = "TextureExporter", + ExporterConfig = { + _compression = .LZ4 + }, + AssetHandle = 17972970543152031508 } \ No newline at end of file diff --git a/GlitchyEditor/src/AssetFile.bf b/GlitchyEditor/src/AssetFile.bf index 4dacea6..1f5cb7c 100644 --- a/GlitchyEditor/src/AssetFile.bf +++ b/GlitchyEditor/src/AssetFile.bf @@ -149,14 +149,17 @@ class AssetFile var assetLoader = _contentManager.GetDefaultAssetLoader(fileExtension); // We don't have a loader -> we don't need a config - if (assetLoader == null) + if (assetLoader == null && assetPipeline case .Err) return; - _assetConfig.AssetLoader = new String(); - assetLoader.GetType().GetName(_assetConfig.AssetLoader); - - _assetConfig.Config = assetLoader?.GetDefaultConfig(); - _assetConfig.Config?.[Friend]_changed = true; + if (assetLoader != null) + { + _assetConfig.AssetLoader = new String(); + assetLoader.GetType().GetName(_assetConfig.AssetLoader); + + _assetConfig.Config = assetLoader?.GetDefaultConfig(); + _assetConfig.Config?.[Friend]_changed = true; + } _assetConfig.Importer = new String(); assetPipeline?.Importer?.GetType()?.GetName(_assetConfig.Importer); diff --git a/GlitchyEditor/src/Assets/AssetCache.bf b/GlitchyEditor/src/Assets/AssetCache.bf index 82f219d..453a2f9 100644 --- a/GlitchyEditor/src/Assets/AssetCache.bf +++ b/GlitchyEditor/src/Assets/AssetCache.bf @@ -35,11 +35,13 @@ class AssetCache /// Current format version of loose asset file (.laf) file reader and writer. public const uint16 FormatVersion = 1; - private append String _directory = .();// ~ delete:append _; + private append String _projectCacheDirectory = .();// ~ delete:append _; + private append String _globalCacheDirectory = .();// ~ delete:append _; private append Dictionary _assets = .();// ~ delete:append _; - public StringView CacheDirectory => _directory; + public StringView ProjectCacheDirectory => _projectCacheDirectory; + public StringView GlobalCacheDirectory => _globalCacheDirectory; private bool _cacheLoaded; @@ -60,11 +62,18 @@ class AssetCache _cacheLoaded = false; ClearDictionaryAndDeleteValues!(_assets); } + + /// Sets the directory in which the processed assets are cached. + public void SetGlobalCacheDirectory(StringView directory) + { + _globalCacheDirectory.Set(directory); + ReloadCache(); + } /// Sets the directory in which the processed assets are cached. - public void SetDirectory(StringView directory) + public void SetProjectCacheDirectory(StringView directory) { - _directory.Set(directory); + _projectCacheDirectory.Set(directory); ReloadCache(); } @@ -73,13 +82,24 @@ class AssetCache { ClearCache(); - if (!Directory.Exists(_directory)) - { - Log.EngineLogger.Info($"Asset cache directory doesn't exist, creating directory \"{_directory}\"..."); + LoadCache(_globalCacheDirectory); + LoadCache(_projectCacheDirectory); - if (Directory.CreateDirectory(_directory) case .Err(let error)) + _cacheLoaded = true; + } + + private void LoadCache(StringView directory) + { + if (directory.IsWhiteSpace) + return; + + if (!Directory.Exists(directory)) + { + Log.EngineLogger.Info($"Asset cache directory doesn't exist, creating directory \"{directory}\"..."); + + if (Directory.CreateDirectory(directory) case .Err(let error)) { - Log.EngineLogger.Critical($"Failed to create cache directory \"{_directory}\". Reason: {error}."); + Log.EngineLogger.Critical($"Failed to create cache directory \"{directory}\". Reason: {error}."); Log.EngineLogger.Critical($"The engine will not function properly without the asset cache directory. Save your project and restart the engine."); } @@ -87,9 +107,9 @@ class AssetCache // or we failed and can't do anything anyway. return; } - + String filePath = scope .(); - for (FileFindEntry file in Directory.EnumerateFiles(_directory)) + for (FileFindEntry file in Directory.EnumerateFiles(directory)) { filePath.Clear(); file.GetFilePath(filePath); @@ -108,8 +128,6 @@ class AssetCache _assets.Add(cachedAsset.Handle, cachedAsset); } - - _cacheLoaded = true; } private Result ReadAssetFile(StringView filePath, CachedAsset cachedAsset) @@ -170,9 +188,17 @@ class AssetCache return null; } - private void GetCacheFilePath(AssetHandle handle, String outFilePath) + private void GetProjectCacheFilePath(AssetHandle handle, String outFilePath) { - outFilePath.Append(_directory); + outFilePath.Append(_projectCacheDirectory); + outFilePath.Append(Path.DirectorySeparatorChar); + outFilePath.Append(handle); + outFilePath.Append(CachedAsset.CacheFileExtension); + } + + private void GetGlobalCacheFilePath(AssetHandle handle, String outFilePath) + { + outFilePath.Append(_globalCacheDirectory); outFilePath.Append(Path.DirectorySeparatorChar); outFilePath.Append(handle); outFilePath.Append(CachedAsset.CacheFileExtension); @@ -187,7 +213,12 @@ class AssetCache asset = new CachedAsset(); asset.Handle = assetInfo.Handle; asset.FilePath = new String(128); - GetCacheFilePath(asset.Handle, asset.FilePath); + + if (assetInfo.AssetIdentifier.IsResource) + GetGlobalCacheFilePath(asset.Handle, asset.FilePath); + else + GetProjectCacheFilePath(asset.Handle, asset.FilePath); + _assets[asset.Handle] = asset; } diff --git a/GlitchyEditor/src/Assets/AssetConverter.bf b/GlitchyEditor/src/Assets/AssetConverter.bf index 6438f15..115e7ab 100644 --- a/GlitchyEditor/src/Assets/AssetConverter.bf +++ b/GlitchyEditor/src/Assets/AssetConverter.bf @@ -18,9 +18,12 @@ class AssetConverter _contentManager = contentManager; } - public void QueueForProcessing(AssetFile assetFile) + public void QueueForProcessing(AssetFile assetFile, bool isBlocking = false) { - _queue.Add(assetFile); + if (!isBlocking) + _queue.Add(assetFile); + else + Process(assetFile); } public void Update() diff --git a/GlitchyEditor/src/Assets/AssetHierarchy.bf b/GlitchyEditor/src/Assets/AssetHierarchy.bf index f092339..627bb2c 100644 --- a/GlitchyEditor/src/Assets/AssetHierarchy.bf +++ b/GlitchyEditor/src/Assets/AssetHierarchy.bf @@ -375,12 +375,12 @@ class AssetHierarchy if (assetNode.IsInSubtree(_resourcesDirectoryNode)) { Path.GetRelativePath(assetNode->Path, _resourcesDirectoryNode->Path, identifier); - identifier.Insert(0, "Resources/"); + identifier.Insert(0, AssetIdentifier.ResourcesPrefix); } else if (assetNode.IsInSubtree(_assetsDirectoryNode)) { Path.GetRelativePath(assetNode->Path, _assetsDirectoryNode->Path, identifier); - identifier.Insert(0, "Assets/"); + identifier.Insert(0, AssetIdentifier.AssetsPrefix); } delete assetNode->Identifier; diff --git a/GlitchyEditor/src/Assets/TextureAssetLoader.bf b/GlitchyEditor/src/Assets/TextureAssetLoader.bf deleted file mode 100644 index 196dcef..0000000 --- a/GlitchyEditor/src/Assets/TextureAssetLoader.bf +++ /dev/null @@ -1,596 +0,0 @@ -using System; -using System.Collections; -using Bon; -using System.IO; -using GlitchyEngine; -using GlitchyEngine.Content; -using GlitchyEngine.Renderer; -using GlitchyEngine.Math; -using DirectXTK; -using ImGui; -using GlitchyEditor.Assets.Importers; -using System.Diagnostics; - -namespace GlitchyEditor.Assets; - -class TextureAssetPropertiesEditor : AssetPropertiesEditor -{ - EditorTextureAssetLoaderConfig _textureConfig; - - public this(AssetFile asset) : base(asset) - { - _textureConfig = asset.AssetConfig.Config as EditorTextureAssetLoaderConfig; - } - - static char8*[3] _filterFuncNames = char8*[]("Point", "Linear", "Anisotropic"); - - public override void ShowEditor() - { - return; - - if (_textureConfig == null) - return; - - bool generateMips = _textureConfig.GenerateMipMaps; - if (ImGui.Checkbox("Generate Mip Maps", &generateMips)) - _textureConfig.GenerateMipMaps = generateMips; - - bool isSrgb = _textureConfig.IsSRGB; - if (ImGui.Checkbox("Is sRGB", &isSrgb)) - _textureConfig.IsSRGB = isSrgb; - - SamplerStateDescription samplerStateDescription = _textureConfig.SamplerStateDescription; - - void ShowFilterCombo(String label, ref FilterFunction filterFunction) - { - int32 selectedFilter = filterFunction.Underlying; - if (ImGui.Combo(label, &selectedFilter, &_filterFuncNames, 3)) - filterFunction = (.)selectedFilter; - } - - ImGui.Separator(); - ImGui.TextUnformatted("Texture Filtering:"); - ImGui.Separator(); - - ImGui.EnumCombo("Min Filter", ref samplerStateDescription.MinFilter); - ImGui.AttachTooltip(""" - Sampling method used for minification. - If set to "Anisotropic" all Filters are set to "Anisotropic" internally. - """); - ImGui.EnumCombo("Mag Filter", ref samplerStateDescription.MagFilter); - ImGui.AttachTooltip(""" - Sampling method used for magnification. - If set to "Anisotropic" all Filters are set to "Anisotropic" internally. - """); - ImGui.EnumCombo("Mip Map Filter", ref samplerStateDescription.MipFilter); - ImGui.AttachTooltip(""" - Method used for mip-level sampling. - If set to "Anisotropic" all Filters are set to "Anisotropic" internally. - """); - - if (samplerStateDescription.MagFilter == .Anisotropic || - samplerStateDescription.MinFilter == .Anisotropic || - samplerStateDescription.MipFilter == .Anisotropic) - { - ImGui.SliderScalar("Anisotropy Level", ref samplerStateDescription.MaxAnisotropy, 1, 16); - } - - ImGui.NewLine(); - - ImGui.EnumCombo("Filter Mode", ref samplerStateDescription.FilterMode); - ImGui.AttachTooltip("Filtering method to use when sampling a texture."); - - if (samplerStateDescription.FilterMode == .Comparison) - { - ImGui.EnumCombo("Comparison Function", ref samplerStateDescription.ComparisonFunction); - ImGui.AttachTooltip(""" - The function that is used to compare the sampled data against the existing sampled data. - Only applies if Filter Mode is set to FilterMode.Comparison. - """); - } - - ImGui.Separator(); - ImGui.TextUnformatted("Wrapping"); - ImGui.Separator(); - - ImGui.EnumCombo("Wrap Mode U", ref samplerStateDescription.AddressModeU); - ImGui.AttachTooltip("Method to use for resolving a u texture coordinate that is outside the 0 to 1 range."); - - ImGui.EnumCombo("Wrap Mode V", ref samplerStateDescription.AddressModeV); - ImGui.AttachTooltip("Method to use for resolving a v texture coordinate that is outside the 0 to 1 range."); - - ImGui.EnumCombo("Wrap Mode W", ref samplerStateDescription.AddressModeW); - ImGui.AttachTooltip("Method to use for resolving a w texture coordinate that is outside the 0 to 1 range."); - - if (samplerStateDescription.AddressModeU == .Border || - samplerStateDescription.AddressModeV == .Border || - samplerStateDescription.AddressModeW == .Border) - { - ImGui.ColorEdit4("Border Color", ref samplerStateDescription.BorderColor); - } - - ImGui.Separator(); - ImGui.TextUnformatted("Mip Maps"); - ImGui.Separator(); - - ImGui.DragFloat("Mip LOD Bias", &samplerStateDescription.MipLODBias, 0.1f); - ImGui.AttachTooltip(""" - Offset from the calculated mipmap level. - For example, if the GPU calculates that a texture should be sampled at mipmap level 3 and "Mip LOD Bias" is 2, then the texture will be sampled at mipmap level 5. - """); - - ImGui.DragFloat("Min Mip LOD", &samplerStateDescription.MipMinLOD); - ImGui.AttachTooltip("Lower end of the mipmap range to clamp access to, where 0 is the largest and most detailed mipmap level and any level higher than that is less detailed."); - - ImGui.DragFloat("Max LOD Bias", &samplerStateDescription.MipMaxLOD); - ImGui.AttachTooltip(""" - Upper end of the mipmap range to clamp access to, where 0 is the largest and most detailed mipmap level and any level higher than that is less detailed. - This value must be greater than or equal to "Min Mip LOD". To have no upper limit on LOD set this to a large value. - """); - - _textureConfig.SamplerStateDescription = samplerStateDescription; - } - - public static AssetPropertiesEditor Factory(AssetFile assetFile) - { - return new TextureAssetPropertiesEditor(assetFile); - } -} - -[BonTarget, BonPolyRegister] -class EditorTextureAssetLoaderConfig : AssetLoaderConfig -{ - [BonInclude] - private bool _generateMipMaps; - - [BonInclude] - private bool _isSrgb; - - [BonInclude] - private SamplerStateDescription _samplerStateDescription = .(); - - public bool GenerateMipMaps - { - get => _generateMipMaps; - set => SetIfChanged(ref _generateMipMaps, value); - } - - public bool IsSRGB - { - get => _isSrgb; - set => SetIfChanged(ref _isSrgb, value); - } - - public SamplerStateDescription SamplerStateDescription - { - get => _samplerStateDescription; - set => SetIfChanged(ref _samplerStateDescription, value); - } -} - -using internal GlitchyEngine.Renderer; -using internal GlitchyEngine.Platform.DX11; - -class EditorTextureAssetLoader : IAssetLoader//, IReloadingAssetLoader -{ - private static readonly List _fileExtensions = new .(){".png", ".dds"} ~ delete _; // ".jpg", ".bmp" - - public static List FileExtensions => _fileExtensions; - - public AssetLoaderConfig GetDefaultConfig() - { - return new EditorTextureAssetLoaderConfig(); - } - - public Asset LoadAsset(Stream data, AssetLoaderConfig config, StringView assetIdentifier, StringView? subAsset, IContentManager contentManager) - { - var config; - - if (config == null) - { - config = GetDefaultConfig(); - defer:: delete config; - } - - Log.EngineLogger.AssertDebug(config is EditorTextureAssetLoaderConfig, "config has wrong type."); - - return LoadTexture(data, (EditorTextureAssetLoaderConfig)config); - } - - const String PngMagicWord = "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A"; - const String DdsMagicWord = "DDS "; - - enum TextureType - { - Unknown, - DDS, - PNG - } - - private static TextureType GetTextureType(Stream data) - { - int64 position = data.Position; - - var readResult = data.Read(); - - data.Position = position; - - char8[8] magicWord; - if (readResult case .Ok(out magicWord)) - { - StringView strView = .(&magicWord, magicWord.Count); - - if (strView.StartsWith(PngMagicWord)) - { - return .PNG; - } - else if (strView.StartsWith(DdsMagicWord)) - { - return .DDS; - } - else - { - Runtime.FatalError("Unknown image format."); - } - } - - return .Unknown; - } - - /** \brief Loads the texture from the specified path. - * @param path The path of the texture to load. - * @param texture The reference to the pointer that will hold the texture. - * @returns true if the texture was loaded successfully; false otherwise. - */ - protected static bool LoadDdsResourcePlatform(Stream stream) - { - Debug.Profiler.ProfileResourceFunction!(); - - uint8[] ddsData = new:ScopedAlloc! uint8[stream.Length]; - - var result = stream.TryRead(ddsData); - - if (result case .Err(let err)) - { - Log.EngineLogger.Error($"Failed to read texture data from stream. Error: {err}"); - } - - DirectX.D3D11.ID3D11Texture2D* texture = null; - DirectX.D3D11.ID3D11ShaderResourceView* view = null; - - DirectX.Common.HResult loadResult = DDSTextureLoader.CreateDDSTextureFromMemory(GlitchyEngine.Platform.DX11.NativeDevice, - ddsData.Ptr, (uint)ddsData.Count, (.)&texture, &view); - - view.Release(); - - return true; - } - - private static Texture LoadTexture(Stream data, EditorTextureAssetLoaderConfig config) - { - Debug.Profiler.ProfileResourceFunction!(); - - List surfaces = scope .(); - LoadedTextureInfo textureInfo; - - // Make sure we clean up the pixel data - defer { delete textureInfo.PixelData; } - - - switch(GetTextureType(data)) - { - case .DDS: - - var v = data.Position; - - //LoadDdsResourcePlatform(data); - - data.Position = v; - - Result result = LoadDds(data, config, surfaces, out textureInfo); - - if (result case .Err) - return null; - - case .PNG: - Result result = LoadPng(data, config, surfaces, out textureInfo); - - if (result case .Err) - return null; - - case .Unknown: - Log.EngineLogger.Error("Unknown texture format."); - return null; - } - - // Make the format SRGB or non-SRGB - if (config.IsSRGB) - textureInfo.PixelFormat = textureInfo.PixelFormat.GetSRGB(); - else - textureInfo.PixelFormat = textureInfo.PixelFormat.GetNonSRGB(); - - Texture texture = CreateTexture(surfaces, textureInfo); - - if (texture != null) - { - SetSampler(texture, config); - texture.[Friend]Complete = true; - } - - return texture; - } - - private static Texture CreateTexture(List surfaces, LoadedTextureInfo textureInfo) - { - TextureSliceData[] slices = scope TextureSliceData[surfaces.Count]; - - for (int i < slices.Count) - { - slices[i] = .(surfaces[i].Data.Ptr, surfaces[i].Pitch, surfaces[i].SlicePitch); - } - - //slices[0].SlicePitch = (.)(surfaces[0].Pitch * textureInfo.Height); - - switch (textureInfo.Dimension) - { - //case .Texture1D: - case .Texture2D: - if (textureInfo.IsCubeMap) - { - Texture2DDesc staging = .(); - - staging.Width = (.)textureInfo.Width; - staging.Height = (.)textureInfo.Height; - - staging.MipLevels = (.)textureInfo.MipMapCount; - staging.ArraySize = (.)textureInfo.ArraySize; - - staging.Format = (.)textureInfo.PixelFormat; - - // TODO: allow enabling read/write - staging.CpuAccess = .None; - staging.Usage = .Default; - - TextureCube cubeTexture = new TextureCube(staging); - - //cubeTexture.SetData(); - - for (let surface in surfaces) - { - cubeTexture.SetData(surface.Data.Ptr, surface.Pitch / staging.Width, (TextureCubeFace)surface.CubeFace, (.)surface.ArrayIndex, (.)surface.MipLevel); - } - - return cubeTexture; - } - else - { - Texture2DDesc staging = .(); - - staging.Width = (.)textureInfo.Width; - staging.Height = (.)textureInfo.Height; - - staging.MipLevels = (.)textureInfo.MipMapCount; - staging.ArraySize = (.)textureInfo.ArraySize; - - staging.Format = (.)textureInfo.PixelFormat; - - // TODO: allow enabling read/write - staging.CpuAccess = .None; - staging.Usage = .Immutable; - - Texture2D stagingTexture = new Texture2D(staging); - - stagingTexture.SetData(slices); - - /*for (let surface in surfaces) - { - stagingTexture.[Friend]PlatformSetData(surface.Data.Ptr, surface.Pitch / staging.Width, 0, 0, staging.Width, staging.Height, (.)surface.ArrayIndex, (.)surface.MipLevel, .Write); - }*/ - - return stagingTexture; - } - default: - Runtime.NotImplemented(); - } - - return null; - } - - private static Result LoadPng(Stream data, EditorTextureAssetLoaderConfig config, List surfaces, out LoadedTextureInfo textureInfo) - { - Debug.Profiler.ProfileResourceFunction!(); - - textureInfo = .(); - - uint8[] pngData = new:ScopedAlloc! uint8[data.Length]; - - var result = data.TryRead(pngData); - - if (result case .Err(let err)) - { - Log.EngineLogger.Error($"Failed to read data from stream. Texture: Error: {err}"); - return .Err; - } - - uint8* rawData = null; - defer - { - if (rawData != null) - LodePng.LodePng.Free(rawData); - } - - uint32 width = 0, height = 0; - - { - Debug.Profiler.ProfileResourceScope!("LodePng.LodePng.Decode32"); - uint32 errorCode = LodePng.LodePng.Decode32(&rawData, &width, &height, pngData.Ptr, (.)pngData.Count); - if (errorCode != 0) - { - Log.EngineLogger.Error($"Failed to decode PNG file {errorCode}."); - return .Err; - } - } - - uint8[] pixelData = new uint8[4 * width * height]; - Internal.MemCpy(pixelData.Ptr, rawData, pixelData.Count); - - LoadedSurface surface = .(); - surface.Data = Span(pixelData); - surface.Pitch = 4 * width; - surface.SlicePitch = 0; - surface.ArrayIndex = 0; - surface.MipLevel = 0; - - surfaces.Add(surface); - - //Texture2DDesc desc = .(width, height, config.IsSRGB ? .R8G8B8A8_UNorm_SRGB : .R8G8B8A8_UNorm, 1, 1, .Immutable); - //Texture2D texture = new Texture2D(desc); - //texture.SetData((.)rawData); - - // TODO: Generate mip maps - - textureInfo.PixelData = pixelData; - textureInfo.Width = width; - textureInfo.Height = height; - textureInfo.Depth = 1; - - textureInfo.ArraySize = 1; - textureInfo.MipMapCount = 1; - - textureInfo.Dimension = .Texture2D; - - textureInfo.IsCubeMap = false; - - textureInfo.PixelFormat = config.IsSRGB ? .R8G8B8A8_UNorm_SRGB : .R8G8B8A8_UNorm; - - return .Ok; - - //return texture; - } - - private static Result LoadDds(Stream data, EditorTextureAssetLoaderConfig config, List surfaces, out LoadedTextureInfo textureInfo) - { - var result = DdsImporter.LoadDds(data, config.IsSRGB, surfaces, out textureInfo); - - if (result case .Err) - return .Err; - - return .Ok; - } - - private static void SetSampler(Texture texture, EditorTextureAssetLoaderConfig config) - { - using (SamplerState samplerState = SamplerStateManager.GetSampler(config.SamplerStateDescription)) - { - texture.SamplerState = samplerState; - } - } - - private static Texture2D _placeholder2D; - private static TextureCube _placeholderCube; - - private static Texture2D _error2D; - private static TextureCube _errorCube; - - public Asset GetPlaceholderAsset(Type assetType) - { - switch (assetType) - { - case typeof(TextureCube): - if (_placeholderCube == null) - { - // TODO: immutable - Texture2DDesc desc = .(1, 1, .R8G8B8A8_UNorm, 1, 1, .Default, .None); - - _placeholderCube = new TextureCube(desc); - _placeholderCube.SamplerState = SamplerStateManager.PointWrap; - Color color = Color.Cyan; - _placeholderCube.SetData(&color, .PositiveX); - _placeholderCube.SetData(&color, .NegativeX); - _placeholderCube.SetData(&color, .PositiveY); - _placeholderCube.SetData(&color, .NegativeY); - _placeholderCube.SetData(&color, .PositiveZ); - _placeholderCube.SetData(&color, .NegativeZ); - - Content.ManageAsset(_placeholderCube); - _placeholderCube.ReleaseRef(); - - _placeholderCube.[Friend]Complete = false; - } - - return _placeholderCube; - case typeof(Texture2D): - fallthrough; - default: - if (_placeholder2D == null) - { - Texture2DDesc desc = .(1, 1, .R8G8B8A8_UNorm, 1, 1, .Immutable, .None); - - _placeholder2D = new Texture2D(desc); - _placeholder2D.SamplerState = SamplerStateManager.PointWrap; - Color color = Color.Cyan; - _placeholder2D.SetData(&color); - - Content.ManageAsset(_placeholder2D); - _placeholder2D.ReleaseRef(); - - _placeholder2D.[Friend]Complete = false; - } - - return _placeholder2D; - } - } - - public Asset GetErrorAsset(Type assetType) - { - switch (assetType) - { - case typeof(TextureCube): - if (_placeholderCube == null) - { - // TODO: immutable - Texture2DDesc desc = .(2, 2, .R8G8B8A8_UNorm, 1, 1, .Default, .None); - - _errorCube = new TextureCube(desc); - _errorCube.SamplerState = SamplerStateManager.PointWrap; - - Color[4] color = .(Color.HotPink, Color.Black, Color.Black, Color.HotPink); - - _errorCube.SetData(&color, .PositiveX); - _errorCube.SetData(&color, .NegativeX); - _errorCube.SetData(&color, .PositiveY); - _errorCube.SetData(&color, .NegativeY); - _errorCube.SetData(&color, .PositiveZ); - _errorCube.SetData(&color, .NegativeZ); - - Content.ManageAsset(_errorCube); - _errorCube.ReleaseRef(); - - _errorCube.[Friend]Complete = false; - } - - return _placeholderCube; - case typeof(Texture2D): - fallthrough; - default: - if (_error2D == null) - { - Texture2DDesc desc = .(2, 2, .R8G8B8A8_UNorm, 1, 1, .Immutable, .None); - - _error2D = new Texture2D(desc); - _error2D.SamplerState = SamplerStateManager.PointWrap; - - Color[4] color = .(Color.HotPink, Color.Black, Color.Black, Color.HotPink); - - _error2D.SetData(&color); - - Content.ManageAsset(_error2D); - _error2D.ReleaseRef(); - - _placeholder2D.[Friend]Complete = true; - } - - return _error2D; - } - } -} diff --git a/GlitchyEditor/src/EditorApp.bf b/GlitchyEditor/src/EditorApp.bf index 7541128..dd97b68 100644 --- a/GlitchyEditor/src/EditorApp.bf +++ b/GlitchyEditor/src/EditorApp.bf @@ -21,9 +21,6 @@ namespace GlitchyEditor protected override IContentManager InitContentManager() { _contentManager = new EditorContentManager(); - _contentManager.RegisterAssetLoader(); - _contentManager.SetAsDefaultAssetLoader(".png", ".dds"); - _contentManager.SetAssetPropertiesEditor(=> TextureAssetPropertiesEditor.Factory); _contentManager.RegisterAssetLoader(); _contentManager.SetAsDefaultAssetLoader(".glb", ".gltf"); @@ -41,9 +38,10 @@ namespace GlitchyEditor _contentManager.RegisterAssetProcessor(); _contentManager.RegisterAssetExporter(); - _contentManager.ConfigureDefaultProcessing(".png"); - - _contentManager.SetResourcesDirectory("./Resources"); + _contentManager.ConfigureDefaultProcessing(".png", ".dds"); + + _contentManager.SetGlobalAssetCacheDirectory(".cache"); + _contentManager.SetResourcesDirectory("Resources"); return _contentManager; } diff --git a/GlitchyEditor/src/EditorContentManager.bf b/GlitchyEditor/src/EditorContentManager.bf index 0c13a22..536c63a 100644 --- a/GlitchyEditor/src/EditorContentManager.bf +++ b/GlitchyEditor/src/EditorContentManager.bf @@ -94,10 +94,15 @@ class EditorContentManager : IContentManager _assetHierarchy.SetAssetsDirectory(_assetsDirectory); } + + public void SetGlobalAssetCacheDirectory(StringView fileName) + { + _assetCache.SetGlobalCacheDirectory(fileName); + } public void SetAssetCacheDirectory(StringView fileName) { - _assetCache.SetDirectory(fileName); + _assetCache.SetProjectCacheDirectory(fileName); } public void Update() @@ -494,14 +499,11 @@ class EditorContentManager : IContentManager AssetNode assetNode = resultNode->Value; AssetFile file = assetNode.AssetFile; - CachedAsset cacheEntry = _assetCache.GetCacheEntry(handle); - Asset loadedAsset; // TODO: Remove this check once we no longer need the old stuff - if (cacheEntry != null) + if (file.UseNewAssetPipeline) { - // TODO: Load asset with new loaders loadedAsset = LoadFromCache(handle, blocking); } else @@ -522,7 +524,7 @@ class EditorContentManager : IContentManager } // TODO: Support lazy loading for all asset types - if (!(assetLoader is EditorTextureAssetLoader) || blocking) + if (true || blocking) { Stream stream = OpenStream(filePath, true); @@ -948,22 +950,48 @@ class EditorContentManager : IContentManager { CachedAsset asset = _assetCache.GetCacheEntry(handle); + if (asset == null) + { + Result> assetNodeResult = AssetHierarchy.GetNodeFromAssetHandle(handle); + + if (assetNodeResult case .Ok(let assetNode)) + { + _assetConverter.QueueForProcessing(assetNode->AssetFile, isBlocking); + } + + if (isBlocking) + { + asset = _assetCache.GetCacheEntry(handle); + + Log.EngineLogger.Assert(asset != null, "Failed to load asset."); + } + else + { + // TODO: Return placeholder! + return null; + } + } + Result streamResult = _assetCache.OpenStream(asset); - // TODO: Actually return a placeholder, but they probably need rework too... if (streamResult case .Err) + { + // Return error return null; + } Stream dataStream = streamResult.Value; defer { delete dataStream; } IProcessedAssetLoader loader = GetLoader(asset.AssetType); - switch (loader.Load(dataStream)) + if (loader.Load(dataStream) case .Ok(let loadedAsset)) { - case .Ok(let loadedAsset): - return loadedAsset; - case .Err: + return loadedAsset; + } + else + { + // Return error return null; } } diff --git a/GlitchyEditor/src/EditorLayer.bf b/GlitchyEditor/src/EditorLayer.bf index 641a2e2..8ff1e72 100644 --- a/GlitchyEditor/src/EditorLayer.bf +++ b/GlitchyEditor/src/EditorLayer.bf @@ -764,8 +764,8 @@ namespace GlitchyEditor _editor.CurrentProject = _currentProject; String appAssemblyPath = scope String(); - _contentManager.SetAssetDirectory(_currentProject.AssetsFolder); _contentManager.SetAssetCacheDirectory(_currentProject.GetScopedPath!(".cache")); + _contentManager.SetAssetDirectory(_currentProject.AssetsFolder); _currentProject.PathInProject(appAssemblyPath, scope $"bin/{_currentProject.Name}.dll"); diff --git a/GlitchyEngine/src/Content/AssetIdentifier.bf b/GlitchyEngine/src/Content/AssetIdentifier.bf index ca86b4a..d343827 100644 --- a/GlitchyEngine/src/Content/AssetIdentifier.bf +++ b/GlitchyEngine/src/Content/AssetIdentifier.bf @@ -4,14 +4,21 @@ namespace GlitchyEngine.Content; public class AssetIdentifier { + public const String ResourcesPrefix = "Resources/"; + public const String AssetsPrefix = "Assets/"; + private String _fullIdentifier ~ delete:append _; + private bool _isResource; + private int _subassetSeperator; public StringView FullIdentifier => _fullIdentifier; public StringView AssetIdentifier => _subassetSeperator > 0 ? StringView(_fullIdentifier, 0, _subassetSeperator) : _fullIdentifier; public StringView SubassetIdentifier => _subassetSeperator > 0 ? StringView(_fullIdentifier, _subassetSeperator + 1) : .(); + public bool IsResource => _isResource; + [AllowAppend] public this(StringView assetIdentifier) { @@ -21,6 +28,8 @@ public class AssetIdentifier Fixup(_fullIdentifier); _subassetSeperator = _fullIdentifier.IndexOf(':', 0); + + _isResource = _fullIdentifier.StartsWith(ResourcesPrefix); } [AllowAppend]