EditorContentManager Part 1

This commit is contained in:
Simon Lübeß
2023-01-01 16:53:45 +01:00
parent dffd43a36f
commit c389a77274
29 changed files with 3774 additions and 81 deletions
+9 -6
View File
@@ -13,13 +13,14 @@
B = 0.328787, B = 0.328787,
A = 1 A = 1
}, },
IsCircle = false,
Sprite = null,
UvTransform = { UvTransform = {
X = 0, X = 0,
Y = 0, Y = 0,
Z = 1, Z = 1,
W = 1 W = 1
}, }
IsCircle = false
}, },
TransformComponent = { TransformComponent = {
Position = { Position = {
@@ -75,13 +76,14 @@
B = 0.401485, B = 0.401485,
A = 1 A = 1
}, },
IsCircle = false,
Sprite = null,
UvTransform = { UvTransform = {
X = 0, X = 0,
Y = 0, Y = 0,
Z = 1, Z = 1,
W = 1 W = 1
}, }
IsCircle = false
}, },
TransformComponent = { TransformComponent = {
Position = { Position = {
@@ -178,13 +180,14 @@
B = 0, B = 0,
A = 1 A = 1
}, },
IsCircle = true,
Sprite = "Textures//rocket.dds",
UvTransform = { UvTransform = {
X = 0, X = 0,
Y = 0, Y = 0,
Z = 1, Z = 1,
W = 1 W = 1
}, }
IsCircle = true
}, },
TransformComponent = { TransformComponent = {
Position = { Position = {
@@ -0,0 +1,23 @@
{
AssetLoader = "EditorTextureAssetLoader",
Config = (GlitchyEditor.Assets.EditorTextureAssetLoaderConfig){
_samplerStateDescription = {
MinFilter = .Linear,
MagFilter = .Linear,
MipFilter = .Linear,
ComparisonFunction = .Never,
AddressModeU = .Clamp,
AddressModeV = .Clamp,
AddressModeW = .Clamp,
MipMinLOD = -340282346638528859811704183484516925440,
MipMaxLOD = 340282346638528859811704183484516925440,
MaxAnisotropy = 1,
BorderColor = {
R = 1,
G = 1,
B = 1,
A = 1
}
}
}
}
@@ -0,0 +1,23 @@
{
AssetLoader = "EditorTextureAssetLoader",
Config = (GlitchyEditor.Assets.EditorTextureAssetLoaderConfig){
_samplerStateDescription = {
MinFilter = .Linear,
MagFilter = .Linear,
MipFilter = .Linear,
ComparisonFunction = .Never,
AddressModeU = .Clamp,
AddressModeV = .Clamp,
AddressModeW = .Clamp,
MipMinLOD = -340282346638528859811704183484516925440,
MipMaxLOD = 340282346638528859811704183484516925440,
MaxAnisotropy = 1,
BorderColor = {
R = 1,
G = 1,
B = 1,
A = 1
}
}
}
}
@@ -0,0 +1,23 @@
{
AssetLoader = "EditorTextureAssetLoader",
Config = (GlitchyEditor.Assets.EditorTextureAssetLoaderConfig){
_samplerStateDescription = {
MinFilter = .Linear,
MagFilter = .Linear,
MipFilter = .Linear,
ComparisonFunction = .Never,
AddressModeU = .Clamp,
AddressModeV = .Clamp,
AddressModeW = .Clamp,
MipMinLOD = -340282346638528859811704183484516925440,
MipMaxLOD = 340282346638528859811704183484516925440,
MaxAnisotropy = 1,
BorderColor = {
R = 1,
G = 1,
B = 1,
A = 1
}
}
}
}
@@ -0,0 +1,23 @@
{
AssetLoader = "EditorTextureAssetLoader",
Config = (GlitchyEditor.Assets.EditorTextureAssetLoaderConfig){
_samplerStateDescription = {
MinFilter = .Linear,
MagFilter = .Linear,
MipFilter = .Linear,
ComparisonFunction = .Never,
AddressModeU = .Clamp,
AddressModeV = .Clamp,
AddressModeW = .Clamp,
MipMinLOD = -340282346638528859811704183484516925440,
MipMaxLOD = 340282346638528859811704183484516925440,
MaxAnisotropy = 1,
BorderColor = {
R = 1,
G = 1,
B = 1,
A = 1
}
}
}
}
@@ -0,0 +1,23 @@
{
AssetLoader = "EditorTextureAssetLoader",
Config = (GlitchyEditor.Assets.EditorTextureAssetLoaderConfig){
_samplerStateDescription = {
MinFilter = .Linear,
MagFilter = .Linear,
MipFilter = .Linear,
ComparisonFunction = .Never,
AddressModeU = .Clamp,
AddressModeV = .Clamp,
AddressModeW = .Clamp,
MipMinLOD = -340282346638528859811704183484516925440,
MipMaxLOD = 340282346638528859811704183484516925440,
MaxAnisotropy = 1,
BorderColor = {
R = 1,
G = 1,
B = 1,
A = 1
}
}
}
}
@@ -0,0 +1,23 @@
{
AssetLoader = "EditorTextureAssetLoader",
Config = (GlitchyEditor.Assets.EditorTextureAssetLoaderConfig){
_samplerStateDescription = {
MinFilter = .Linear,
MagFilter = .Linear,
MipFilter = .Linear,
ComparisonFunction = .Never,
AddressModeU = .Clamp,
AddressModeV = .Clamp,
AddressModeW = .Clamp,
MipMinLOD = -340282346638528859811704183484516925440,
MipMaxLOD = 340282346638528859811704183484516925440,
MaxAnisotropy = 1,
BorderColor = {
R = 1,
G = 1,
B = 1,
A = 1
}
}
}
}
@@ -0,0 +1,23 @@
{
AssetLoader = "EditorTextureAssetLoader",
Config = (GlitchyEditor.Assets.EditorTextureAssetLoaderConfig){
_samplerStateDescription = {
MinFilter = .Linear,
MagFilter = .Linear,
MipFilter = .Linear,
ComparisonFunction = .Never,
AddressModeU = .Clamp,
AddressModeV = .Clamp,
AddressModeW = .Clamp,
MipMinLOD = -340282346638528859811704183484516925440,
MipMaxLOD = 340282346638528859811704183484516925440,
MaxAnisotropy = 1,
BorderColor = {
R = 1,
G = 1,
B = 1,
A = 1
}
}
}
}
@@ -0,0 +1,23 @@
{
AssetLoader = "EditorTextureAssetLoader",
Config = (GlitchyEditor.Assets.EditorTextureAssetLoaderConfig){
_samplerStateDescription = {
MinFilter = .Linear,
MagFilter = .Linear,
MipFilter = .Linear,
ComparisonFunction = .Never,
AddressModeU = .Clamp,
AddressModeV = .Clamp,
AddressModeW = .Clamp,
MipMinLOD = -340282346638528859811704183484516925440,
MipMaxLOD = 340282346638528859811704183484516925440,
MaxAnisotropy = 1,
BorderColor = {
R = 1,
G = 1,
B = 1,
A = 1
}
}
}
}
@@ -0,0 +1,23 @@
{
AssetLoader = "EditorTextureAssetLoader",
Config = (GlitchyEditor.Assets.EditorTextureAssetLoaderConfig){
_samplerStateDescription = {
MinFilter = .Linear,
MagFilter = .Point,
MipFilter = .Linear,
ComparisonFunction = .Never,
AddressModeU = .Clamp,
AddressModeV = .Clamp,
AddressModeW = .Clamp,
MipMinLOD = -340282346638528859811704183484516925440,
MipMaxLOD = 340282346638528859811704183484516925440,
MaxAnisotropy = 1,
BorderColor = {
R = 1,
G = 1,
B = 1,
A = 1
}
}
}
}
@@ -0,0 +1,23 @@
{
AssetLoader = "EditorTextureAssetLoader",
Config = (GlitchyEditor.Assets.EditorTextureAssetLoaderConfig){
_samplerStateDescription = {
MinFilter = .Linear,
MagFilter = .Linear,
MipFilter = .Linear,
ComparisonFunction = .Never,
AddressModeU = .Clamp,
AddressModeV = .Clamp,
AddressModeW = .Clamp,
MipMinLOD = -340282346638528859811704183484516925440,
MipMaxLOD = 340282346638528859811704183484516925440,
MaxAnisotropy = 1,
BorderColor = {
R = 1,
G = 1,
B = 1,
A = 1
}
}
}
}
+111
View File
@@ -0,0 +1,111 @@
using System;
using GlitchyEngine;
using System.IO;
using Bon;
using GlitchyEngine.Content;
namespace GlitchyEditor;
[BonTarget]
class AssetConfig
{
[BonIgnore]
public bool IgnoreFile = false;
[BonInclude]
public String AssetLoader ~ delete _;
[BonInclude]
public AssetLoaderConfig Config ~ delete _;
}
class AssetFile
{
private EditorContentManager _contentManager;
private String _path;
private String _assetConfigPath;
private AssetConfig _assetConfig ~ delete _;
private bool _isDirectory;
public bool IsDirectory => _isDirectory;
public StringView FilePath => _path;
public const String ConfigFileExtension = ".ass";
public AssetConfig AssetConfig => _assetConfig;
[AllowAppend]
public this(EditorContentManager contentManager, StringView path, bool isDirectory)
{
String pathBuffer = append String(path);
String configPathBuffer = append String(path.Length + ConfigFileExtension.Length);
_path = pathBuffer;
configPathBuffer..Append(path).Append(ConfigFileExtension);
_assetConfigPath = configPathBuffer;
_contentManager = contentManager;
_isDirectory = isDirectory;
Log.EngineLogger.AssertDebug(File.Exists(_path), "File doesn't exist.");
FindAssetConfig();
}
// Loads the asset config (.ass) file or creates it.
private void FindAssetConfig()
{
if (File.Exists(_assetConfigPath))
{
LoadAssetConfig();
}
else
{
CreateDefaultAssetLoader();
}
}
private void CreateDefaultAssetLoader()
{
String fileExtension = Path.GetExtension(_path, .. scope .());
_assetConfig = new AssetConfig();
var assetLoader = _contentManager.GetDefaultAssetLoader(fileExtension);
// We don't have a loader -> we don't need a config
if (assetLoader == null)
return;
_assetConfig.AssetLoader = new String();
assetLoader.GetType().GetName(_assetConfig.AssetLoader);
_assetConfig.Config = assetLoader?.GetDefaultConfig();
_assetConfig.Config?.[Friend]_changed = true;
SaveAssetConfig();
}
private void LoadAssetConfig()
{
if (Bon.DeserializeFromFile(ref _assetConfig, _assetConfigPath) case .Err)
{
Log.EngineLogger.Error($"Failed to load asset config {_assetConfigPath}");
// TODO: Handle failure of asset config loading
Runtime.NotImplemented();
}
}
private void SaveAssetConfig()
{
gBonEnv.serializeFlags |= .Verbose;
Bon.SerializeIntoFile(_assetConfig, _assetConfigPath);
}
}
@@ -0,0 +1,154 @@
using System;
using System.Collections;
using Bon;
using System.IO;
using GlitchyEngine;
using GlitchyEngine.Content;
using GlitchyEngine.Renderer;
using GlitchyEngine.Math;
using DirectXTK;
namespace GlitchyEditor.Assets;
[BonTarget, BonPolyRegister]
class EditorTextureAssetLoaderConfig : AssetLoaderConfig
{
[BonInclude]
private bool _generateMipMaps;
[BonInclude]
private SamplerStateDescription _samplerStateDescription = .();
public bool GenerateMipMaps
{
get => _generateMipMaps;
set => SetIfChanged(ref _generateMipMaps, value);
}
public SamplerStateDescription SamplerStateDescription
{
get => _samplerStateDescription;
set => SetIfChanged(ref _samplerStateDescription, value);
}
}
class EditorTextureAssetLoader : IAssetLoader
{
private static readonly List<StringView> _fileExtensions = new .(){".png", ".dds"} ~ delete _; // ".jpg", ".bmp"
public static List<StringView> FileExtensions => _fileExtensions;
public AssetLoaderConfig GetDefaultConfig()
{
return new EditorTextureAssetLoaderConfig();
}
public IRefCounted LoadAsset(Stream data, AssetLoaderConfig config)
{
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 ";
private static Texture LoadTexture(Stream data, EditorTextureAssetLoaderConfig config)
{
Debug.Profiler.ProfileResourceFunction!();
var readResult = data.Read<char8[8]>();
data.Position = 0;
char8[8] magicWord;
Texture texture = null;
if (readResult case .Ok(out magicWord))
{
StringView strView = .(&magicWord, magicWord.Count);
if (strView.StartsWith(PngMagicWord))
{
texture = LoadPng(data, config);
}
else if (strView.StartsWith(DdsMagicWord))
{
texture = LoadDds(data, config);
}
else
{
Runtime.FatalError("Unknown image format.");
}
}
Log.EngineLogger.AssertDebug(texture != null);
/*SamplerStateDescription samplerDesc = .()
{
MinFilter = config.MinFilter,
MagFilter = config.MagFilter,
MipFilter = config.MipFilter,
AddressModeU = config.WrapModeU,
AddressModeV = config.WrapModeV,
AddressModeW = config.WrapModeW
};*/
SamplerState sam = SamplerStateManager.GetSampler(config.SamplerStateDescription);
texture.SamplerState = sam;
sam.ReleaseRef();
return texture;
}
private static Texture LoadPng(Stream data, EditorTextureAssetLoaderConfig config)
{
Debug.Profiler.ProfileResourceFunction!();
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}");
}
uint8* rawData = ?;
uint32 width = 0, height = 0;
uint32 errorCode = LodePng.LodePng.Decode32(&rawData, &width, &height, pngData.Ptr, (.)pngData.Count);
Log.EngineLogger.Assert(errorCode == 0, "Failed to load png File");
// TODO: load as SRGB because PNGs are usually not stored as linear
//Texture2DDesc desc = .(width, height, srgb? .R8G8B8A8_UNorm_SRGB : .R8G8B8A8_UNorm, 1, 1, .Immutable);
Texture2DDesc desc = .(width, height, .R8G8B8A8_UNorm, 1, 1, .Immutable);
Texture2D texture = new Texture2D(desc);
texture.SetData<Color>((.)rawData);
// TODO: Generate mip maps
LodePng.LodePng.Free(rawData);
return texture;
}
private static Texture LoadDds(Stream data, EditorTextureAssetLoaderConfig config)
{
Texture2D texture = new [Friend]Texture2D(data);
return texture;
}
}
@@ -268,7 +268,7 @@ namespace GlitchyEditor.EditWindows
StringView path = .((char8*)payload.Data, (int)payload.DataSize); StringView path = .((char8*)payload.Data, (int)payload.DataSize);
Texture2D texture = new Texture2D(path, true); Texture2D texture = Content.LoadAsset<Texture2D>(path);//new Texture2D(path, true);
spriteRendererComponent.Sprite?.ReleaseRef(); spriteRendererComponent.Sprite?.ReleaseRef();
spriteRendererComponent.Sprite = texture; spriteRendererComponent.Sprite = texture;
@@ -319,7 +319,7 @@ namespace GlitchyEditor.EditWindows
StringView path = .((char8*)payload.Data, (int)payload.DataSize); StringView path = .((char8*)payload.Data, (int)payload.DataSize);
using (Texture2D newTexture = new Texture2D(path, true)) using (Texture2D newTexture = Content.LoadAsset<Texture2D>(path))//new Texture2D(path, true))
{ {
newTexture.SamplerState = SamplerStateManager.AnisotropicWrap; newTexture.SamplerState = SamplerStateManager.AnisotropicWrap;
material.SetTexture(texture.key, newTexture); material.SetTexture(texture.key, newTexture);
@@ -16,16 +16,16 @@ namespace GlitchyEditor.EditWindows
const String ContentDirectory = "./content"; const String ContentDirectory = "./content";
//private String _currentDirectory ~ delete _; //private String _currentDirectory ~ delete _;
private TreeNode<EditorContentManager.AssetNode> _currentDirectoryNode; private TreeNode<AssetNode> _currentDirectoryNode;
public static SubTexture2D s_FolderTexture; public static SubTexture2D s_FolderTexture;
public static SubTexture2D s_FileTexture; public static SubTexture2D s_FileTexture;
public EditorContentManager _manager ~ delete _; public EditorContentManager _manager;
public this() public this(EditorContentManager contentManager)
{ {
_manager = new EditorContentManager(); _manager = contentManager;
} }
protected override void InternalShow() protected override void InternalShow()
+4 -1
View File
@@ -5,6 +5,7 @@ using System.Collections;
using GlitchyEngine.Collections; using GlitchyEngine.Collections;
using GlitchyEditor.EditWindows; using GlitchyEditor.EditWindows;
using GlitchyEngine; using GlitchyEngine;
using GlitchyEditor.Assets;
namespace GlitchyEditor namespace GlitchyEditor
{ {
@@ -15,7 +16,7 @@ namespace GlitchyEditor
private EntityHierarchyWindow _entityHierarchyWindow ~ delete _; private EntityHierarchyWindow _entityHierarchyWindow ~ delete _;
private ComponentEditWindow _componentEditWindow ~ delete _; private ComponentEditWindow _componentEditWindow ~ delete _;
private SceneViewportWindow _sceneViewportWindow = new .(this) ~ delete _; private SceneViewportWindow _sceneViewportWindow = new .(this) ~ delete _;
private ContentBrowserWindow _contentBrowserWindow = new .() ~ delete _; private ContentBrowserWindow _contentBrowserWindow ~ delete _;
public EntityHierarchyWindow EntityHierarchyWindow => _entityHierarchyWindow; public EntityHierarchyWindow EntityHierarchyWindow => _entityHierarchyWindow;
public ComponentEditWindow ComponentEditWindow => _componentEditWindow; public ComponentEditWindow ComponentEditWindow => _componentEditWindow;
@@ -43,6 +44,8 @@ namespace GlitchyEditor
CurrentScene = scene; CurrentScene = scene;
_componentEditWindow = new ComponentEditWindow(_entityHierarchyWindow); _componentEditWindow = new ComponentEditWindow(_entityHierarchyWindow);
_contentBrowserWindow = new ContentBrowserWindow((.)Application.Get().ContentManager);
} }
public void Update() public void Update()
+180 -35
View File
@@ -5,6 +5,9 @@ using System.Collections;
using GlitchyEngine.Renderer; using GlitchyEngine.Renderer;
using System.Threading; using System.Threading;
using GlitchyEngine.Content; using GlitchyEngine.Content;
using GlitchyEditor.Assets;
using GlitchyEngine;
using System.Linq;
namespace GlitchyEditor; namespace GlitchyEditor;
@@ -70,52 +73,71 @@ namespace GlitchyEditor;
} }
}*/ }*/
class EditorContentManager public class AssetNode
{ {
// TODO: Get from project public String Name ~ delete _;
const String ContentDirectory = "./content"; public String Path ~ delete _;
public bool IsDirectory;
public AssetFile AssetFile ~ delete _;
public List<Asset> SubAssets ~ {
SubAssets?.ClearAndDeleteItems();
delete SubAssets;
}
public Texture2D PreviewImage ~ _?.ReleaseRef();
}
public class Asset
{
public AssetNode Asset;
public String Name ~ delete _;
//public String AssetInternalPath ~ delete _;
public Texture2D PreviewImage ~ _?.ReleaseRef();
}
class EditorContentManager : IContentManager
{
// TODO: Get from workspace
//const String ContentDirectory = "./content";
FileSystemWatcher fsw ~ { FileSystemWatcher fsw ~ {
_.StopRaisingEvents(); _.StopRaisingEvents();
delete _; delete _;
}; };
bool _fileSystemDirty = true; bool _fileSystemDirty = false;
public class AssetNode
{
public String Name ~ delete _;
public String Path ~ delete _;
public bool IsDirectory;
public List<Asset> SubAssets ~ {
SubAssets?.ClearAndDeleteItems();
delete SubAssets;
}
public Texture2D PreviewImage ~ _?.ReleaseRef();
}
public class Asset
{
public AssetNode Asset;
public String Name ~ delete _;
//public String AssetInternalPath ~ delete _;
public Texture2D PreviewImage ~ _?.ReleaseRef();
}
internal TreeNode<AssetNode> _assetHierarchy = new TreeNode<AssetNode>() ~ DeleteTreeAndChildren!(_); internal TreeNode<AssetNode> _assetHierarchy = new TreeNode<AssetNode>() ~ DeleteTreeAndChildren!(_);
private append String _contentDirectory = .();
public StringView ContentDirectory => _contentDirectory;
private append List<String> _identifiers = .() ~ _.ClearAndDeleteItems();
private append Dictionary<StringView, IRefCounted> _loadedAssets = .(); // Check if all resources are unloaded
public this() public this()
{ {
}
public void SetContentDirectory(StringView contentDirectory)
{
_contentDirectory.Clear();
_contentDirectory.Append(contentDirectory);
_fileSystemDirty = true;
SetupFileSystemWatcher(); SetupFileSystemWatcher();
} }
/// Initializes the FSW for the current ContentDirectory and registers the events. /// Initializes the FSW for the current ContentDirectory and registers the events.
private void SetupFileSystemWatcher() private void SetupFileSystemWatcher()
{ {
delete fsw;
fsw = new FileSystemWatcher(ContentDirectory); fsw = new FileSystemWatcher(ContentDirectory);
fsw.IncludeSubdirectories = true; fsw.IncludeSubdirectories = true;
@@ -140,6 +162,7 @@ class EditorContentManager
public void Update() public void Update()
{ {
// TODO: do we really need to do this in the update loop?
if (_fileSystemDirty) if (_fileSystemDirty)
{ {
UpdateFiles(); UpdateFiles();
@@ -148,24 +171,26 @@ class EditorContentManager
private void UpdateFiles() private void UpdateFiles()
{ {
// TODO: we don't need to rebuild the entire tree!
DeleteTreeAndChildren!(_assetHierarchy); DeleteTreeAndChildren!(_assetHierarchy);
_assetHierarchy = new TreeNode<AssetNode>(new AssetNode()); _assetHierarchy = new TreeNode<AssetNode>(new AssetNode());
_assetHierarchy->Path = new String(ContentDirectory); _assetHierarchy->Path = new String(ContentDirectory);
_assetHierarchy->Name = new String("Content"); _assetHierarchy->Name = new String("Content");
String str = scope .(ContentDirectory); String str = scope .(ContentDirectory);
void GrabSubAssets(TreeNode<AssetNode> assetNode) /*void GrabSubAssets(TreeNode<AssetNode> assetNode)
{ {
// TODO: Dedicated asset loaders that register their extensions, etc....! // TODO: Dedicated asset loaders that register their extensions, etc....!
if (assetNode->Name.EndsWith(".png", .OrdinalIgnoreCase)) if (assetNode->Name.EndsWith(".png", .OrdinalIgnoreCase))
{ {
assetNode->SubAssets = new List<Asset>(); assetNode->SubAssets = new:allocator List<Asset>();
assetNode->SubAssets.Add(new Asset() assetNode->SubAssets.Add(new:allocator Asset()
{ {
Asset = assetNode.Value, Asset = assetNode.Value,
Name = new String(assetNode->Name) Name = new:allocator String(assetNode->Name)
}); });
} }
else if (assetNode->Name.EndsWith(".gltf", .OrdinalIgnoreCase) || assetNode->Name.EndsWith(".glb", .OrdinalIgnoreCase)) else if (assetNode->Name.EndsWith(".gltf", .OrdinalIgnoreCase) || assetNode->Name.EndsWith(".glb", .OrdinalIgnoreCase))
@@ -173,11 +198,11 @@ class EditorContentManager
List<String> meshNames = scope List<String>(); List<String> meshNames = scope List<String>();
ModelLoader.GetMeshNames(assetNode->Path, meshNames); ModelLoader.GetMeshNames(assetNode->Path, meshNames);
assetNode->SubAssets = new List<Asset>(); assetNode->SubAssets = new:allocator List<Asset>();
for (var meshName in meshNames) for (var meshName in meshNames)
{ {
assetNode->SubAssets.Add(new Asset() assetNode->SubAssets.Add(new:allocator Asset()
{ {
Asset = assetNode.Value, Asset = assetNode.Value,
// Pass ownership of meshName to SubAsset -> save a copy and delete // Pass ownership of meshName to SubAsset -> save a copy and delete
@@ -185,6 +210,11 @@ class EditorContentManager
}); });
} }
} }
}*/
void HandleFile(AssetNode node)
{
node.AssetFile = new AssetFile(this, node.Path, node.IsDirectory);
} }
void AddFilesOfDirectory(TreeNode<AssetNode> directory) void AddFilesOfDirectory(TreeNode<AssetNode> directory)
@@ -192,11 +222,18 @@ class EditorContentManager
String filter = scope $"{directory->Path}/*"; String filter = scope $"{directory->Path}/*";
String buffer = scope String(); String buffer = scope String();
String extensionBuffer = scope String();
for (var entry in Directory.Enumerate(filter, .Files)) for (var entry in Directory.Enumerate(filter, .Files))
{ {
entry.GetFilePath(buffer..Clear()); entry.GetFilePath(buffer..Clear());
Path.GetExtension(buffer, extensionBuffer..Clear());
// Don't add meta-files
if (extensionBuffer == ".ass")
continue;
AssetNode e = new AssetNode(); AssetNode e = new AssetNode();
e.Name = new String(); e.Name = new String();
Path.GetFileName(buffer, e.Name); Path.GetFileName(buffer, e.Name);
@@ -206,7 +243,8 @@ class EditorContentManager
e.IsDirectory = entry.IsDirectory; e.IsDirectory = entry.IsDirectory;
var node = directory.AddChild(e); var node = directory.AddChild(e);
GrabSubAssets(node); //GrabSubAssets(node);
HandleFile(node.Value);
} }
} }
@@ -244,4 +282,111 @@ class EditorContentManager
_fileSystemDirty = false; _fileSystemDirty = false;
} }
public IAssetLoader GetDefaultAssetLoader(StringView fileExtension)
{
if (_defaultAssetLoaders.TryGetValue(fileExtension, let value))
return value;
return null;
}
private append List<String> _supportedExtensions = .() ~ ClearAndDeleteItems!(_);
private append List<IAssetLoader> _assetLoaders = .() ~ ClearAndDeleteItems!(_);
private append Dictionary<StringView, IAssetLoader> _defaultAssetLoaders = .();
public void RegisterAssetLoader<T>() where T : new, class, IAssetLoader
{
//Log.EngineLogger.AssertDebug(!_assetLoaders.Any((l) => l.GetType() == typeof(T)), "Asset loader already registered.");
_assetLoaders.Add(new T());
for (StringView ext in T.FileExtensions)
_supportedExtensions.Add(new String(ext));
}
public void SetAsDefaultAssetLoader<T>(params StringView[] fileExtensions) where T : IAssetLoader
{
for (var ext in fileExtensions)
{
// Find file extension in registered file extensions
String foundExtension = null;
for (var supportedExt in _supportedExtensions)
{
if (supportedExt == ext)
{
foundExtension = supportedExt;
break;
}
}
Log.EngineLogger.Assert(foundExtension != null, "File Extension is not registered.");
for (var loader in _assetLoaders)
{
if (loader.GetType() == typeof(T))
{
_defaultAssetLoaders[foundExtension] = loader;
break;
}
}
}
}
public bool IsLoaded(StringView identifier)
{
return _loadedAssets.ContainsKey(identifier);
}
public IRefCounted LoadAsset(StringView identifier)
{
if (_loadedAssets.TryGetValue(identifier, let asset))
{
return asset..AddRef();
}
String filePath = scope String(identifier.Length + _contentDirectory.Length + 2);
Path.InternalCombine(filePath, _contentDirectory, identifier);
AssetFile file = scope .(this, filePath, false);
IAssetLoader assetLoader = null;
String loaderTypeName = scope .(128);
for (IAssetLoader loader in _assetLoaders)
{
loader.GetType().GetName(loaderTypeName..Clear());
if (loaderTypeName == file.AssetConfig.AssetLoader)
{
assetLoader = loader;
break;
}
}
Log.EngineLogger.AssertDebug(assetLoader != null);
Stream stream = GetStream(filePath);
IRefCounted loadedAsset = assetLoader.LoadAsset(stream, file.AssetConfig.Config);
String identifierString = new .(identifier);
_identifiers.Add(identifierString);
_loadedAssets[identifierString] = loadedAsset;
delete stream;
return loadedAsset;
}
// TODO: probably not needed
public Stream GetStream(StringView assetIdentifier)
{
FileStream fs = new FileStream();
var result = fs.Open(assetIdentifier, .Open, .Read, .ReadWrite);
return fs;
}
} }
+1 -1
View File
@@ -24,7 +24,7 @@ namespace GlitchyEditor
public this(String texturePath, Vector2 iconSize) public this(String texturePath, Vector2 iconSize)
{ {
_texture = new Texture2D(texturePath); _texture = Content.LoadAsset<Texture2D>(texturePath);//new Texture2D(texturePath);
Vector2 pen = .(); Vector2 pen = .();
+16 -2
View File
@@ -12,6 +12,7 @@ using System.Collections;
using GlitchyEngine.Renderer.Animation; using GlitchyEngine.Renderer.Animation;
using System.IO; using System.IO;
using GlitchyEngine.Core; using GlitchyEngine.Core;
using GlitchyEditor.Assets;
namespace GlitchyEditor namespace GlitchyEditor
{ {
@@ -70,6 +71,8 @@ namespace GlitchyEditor
{ {
Application.Get().Window.IsVSync = false; Application.Get().Window.IsVSync = false;
InitContentLoader();
InitGraphics(); InitGraphics();
_camera = EditorCamera(Vector3(3.5f, 1.25f, 2.75f), Quaternion.FromEulerAngles(MathHelper.ToRadians(40), MathHelper.ToRadians(25), 0), MathHelper.ToRadians(75), 0.1f, 1); _camera = EditorCamera(Vector3(3.5f, 1.25f, 2.75f), Quaternion.FromEulerAngles(MathHelper.ToRadians(40), MathHelper.ToRadians(25), 0), MathHelper.ToRadians(75), 0.1f, 1);
@@ -80,6 +83,17 @@ namespace GlitchyEditor
NewScene(); NewScene();
} }
private void InitContentLoader()
{
EditorContentManager contentManager = new EditorContentManager();
contentManager.SetContentDirectory("./content");
contentManager.RegisterAssetLoader<EditorTextureAssetLoader>();
contentManager.SetAsDefaultAssetLoader<EditorTextureAssetLoader>(".png", ".dds");
Application.Get().[Friend]_contentManager = contentManager;
}
private void InitGraphics() private void InitGraphics()
{ {
_context = Application.Get().Window.Context..AddRef(); _context = Application.Get().Window.Context..AddRef();
@@ -327,7 +341,7 @@ namespace GlitchyEditor
// Just for testing // Just for testing
private void TestEntitiesWithModels() private void TestEntitiesWithModels()
{ {
{ /*{
var lightNtt = _scene.CreateEntity("My Sexy Sun 2"); var lightNtt = _scene.CreateEntity("My Sexy Sun 2");
let transform = lightNtt.GetComponent<TransformComponent>(); let transform = lightNtt.GetComponent<TransformComponent>();
transform.Position = .(0, 0, 0); transform.Position = .(0, 0, 0);
@@ -449,7 +463,7 @@ namespace GlitchyEditor
} }
ClearAndReleaseItems!(clips); ClearAndReleaseItems!(clips);
} }*/
} }
/// Creates a new scene. /// Creates a new scene.
+1 -1
View File
@@ -60,7 +60,7 @@ namespace GlitchyEngine
_rendererApi = new RendererAPI(); _rendererApi = new RendererAPI();
_rendererApi.Context = _window.Context; _rendererApi.Context = _window.Context;
_contentManager = new ContentManager("./content"); //_contentManager = new ContentManager("./content");
SamplerStateManager.Init(); SamplerStateManager.Init();
+86 -6
View File
@@ -1,6 +1,8 @@
using System; using System;
using System.IO; using System.IO;
using xxHash; using xxHash;
using System.Collections;
using Bon;
namespace GlitchyEngine.Content namespace GlitchyEngine.Content
{ {
@@ -23,16 +25,94 @@ namespace GlitchyEngine.Content
} }
} }
interface IContentManager [BonTarget, BonPolyRegister]
abstract class AssetLoaderConfig
{ {
void GetFilePath(String outFilename, String filename); [BonIgnore]
protected bool _changed;
Stream GetFile(String filename); public bool Changed => _changed;
protected bool SetIfChanged<T>(ref T field, T value)
{
if (field == value)
return false;
field = value;
_changed = true;
return true;
}
} }
class ContentManager : IContentManager interface IAssetLoader
{ {
private String _contentRoot; static List<StringView> FileExtensions { get; }
AssetLoaderConfig GetDefaultConfig();
/// Loads the asset from the given data stream with the specified config.
/// @param file The stream containing the asset.
/// @param config The configuration which specifies the settings used to load the asset.
/// @returns The loaded asset.
IRefCounted LoadAsset(Stream file, AssetLoaderConfig config);
}
static
{
/// Loads the specified asset with the given contentManager or the current applications content manager.
public static T LoadAsset<T>(StringView assetIdentifier, IContentManager contentManager = null) where T : IRefCounted
{
var contentManager;
if (contentManager == null)
contentManager = Application.Get().ContentManager;
Object o = contentManager.LoadAsset(assetIdentifier);
Log.EngineLogger.AssertDebug(o is T);
return (T)o;
}
}
interface IContentManager
{
/// Loads the given asset.
IRefCounted LoadAsset(StringView assetIdentifier);
/// Returns a data stream for the given asset.
Stream GetStream(StringView assetIdentifier);
void RegisterAssetLoader<T>() where T : new, class, IAssetLoader;
void SetAsDefaultAssetLoader<T>(params StringView[] fileExtensions) where T : IAssetLoader;
//void GetFilePath(String outFilename, String filename);
//Stream GetFile(String filename);
}
class RuntimeContentManager : IContentManager
{
public IRefCounted LoadAsset(StringView identifier)
{
Runtime.NotImplemented();
}
public Stream GetStream(StringView assetIdentifier)
{
Runtime.NotImplemented();
}
public void RegisterAssetLoader<T>() where T : IAssetLoader where T : class where T : new
{
Runtime.NotImplemented();
}
public void SetAsDefaultAssetLoader<T>(params StringView[] fileExtensions) where T : IAssetLoader
{
Runtime.NotImplemented();
}
/*private String _contentRoot;
[AllowAppend] [AllowAppend]
public this(String contentRoot) public this(String contentRoot)
@@ -65,6 +145,6 @@ namespace GlitchyEngine.Content
} }
return stream; return stream;
} }*/
} }
} }
File diff suppressed because it is too large Load Diff
+7 -4
View File
@@ -96,16 +96,19 @@ namespace GlitchyEngine.ImGui
ImGui.GetIO().Fonts.Clear(); ImGui.GetIO().Fonts.Clear();
String fullpath = scope String(); // TODO: Fix fonts
Application.Get().ContentManager.GetFilePath(fullpath, settings.FontName); //String fullpath = scope String();
//Application.Get().ContentManager.GetFilePath(fullpath, settings.FontName);
/*Application.Get().ContentManager.GetStream(settings.FontName);
if (File.Exists(fullpath)) if (File.Exists(fullpath))
{ {
ImGui.GetIO().Fonts.AddFontFromMemoryTTF();
ImGui.GetIO().Fonts.AddFontFromFileTTF(fullpath, settings.FontSize); ImGui.GetIO().Fonts.AddFontFromFileTTF(fullpath, settings.FontSize);
} }
else else
{ {*/
ImGui.GetIO().Fonts.AddFontDefault(); ImGui.GetIO().Fonts.AddFontDefault();
} //}
#if GE_GRAPHICS_DX11 #if GE_GRAPHICS_DX11
ImGuiImplDX11.CreateDeviceObjects(); ImGuiImplDX11.CreateDeviceObjects();
@@ -2,12 +2,14 @@ using System;
using GlitchyEngine.Core; using GlitchyEngine.Core;
using GlitchyEngine.Math; using GlitchyEngine.Math;
using System.Collections; using System.Collections;
using Bon;
namespace GlitchyEngine.Renderer namespace GlitchyEngine.Renderer
{ {
/** /**
* Defines the filter function used when sampling from a texture. * Defines the filter function used when sampling from a texture.
*/ */
[BonTarget, Reflect]
public enum FilterFunction public enum FilterFunction
{ {
/// Use point filtering (nearest neighbor) for sampling. /// Use point filtering (nearest neighbor) for sampling.
@@ -18,6 +20,7 @@ namespace GlitchyEngine.Renderer
Anisotropic Anisotropic
} }
[BonTarget, Reflect]
public enum FilterMode public enum FilterMode
{ {
/// Just sample the texture. /// Just sample the texture.
@@ -30,6 +33,7 @@ namespace GlitchyEngine.Renderer
Maximum Maximum
} }
[BonTarget, Reflect]
public enum ComparisonFunction public enum ComparisonFunction
{ {
/** /**
@@ -66,6 +70,7 @@ namespace GlitchyEngine.Renderer
Always = 8 Always = 8
} }
[BonTarget, Reflect]
public enum TextureAddressMode public enum TextureAddressMode
{ {
/// Tile the texture at every (u,v) integer junction. /// Tile the texture at every (u,v) integer junction.
@@ -93,6 +98,7 @@ namespace GlitchyEngine.Renderer
MirrorOnce MirrorOnce
} }
[BonTarget]
public struct SamplerStateDescription : IHashable public struct SamplerStateDescription : IHashable
{ {
public FilterFunction MinFilter = .Linear; public FilterFunction MinFilter = .Linear;
+9 -3
View File
@@ -65,12 +65,18 @@ namespace GlitchyEngine.Renderer
//public override extern uint32 ArraySize {get;} //public override extern uint32 ArraySize {get;}
//public override extern uint32 MipLevels {get;} //public override extern uint32 MipLevels {get;}
public this(StringView path, bool pngSrgb = false) private this(StringView path, bool pngSrgb = false)
{ {
_path = new String(path); _path = new String(path);
LoadTexture(pngSrgb); LoadTexture(pngSrgb);
} }
// TODO: remove
private this(Stream data)
{
LoadDds(data);
}
const String PngMagicWord = "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A"; const String PngMagicWord = "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A";
const String DdsMagicWord = "DDS "; const String DdsMagicWord = "DDS ";
@@ -78,7 +84,7 @@ namespace GlitchyEngine.Renderer
{ {
Debug.Profiler.ProfileResourceFunction!(); Debug.Profiler.ProfileResourceFunction!();
Stream data = Application.Get().ContentManager.GetFile(_path); Stream data = Application.Get().ContentManager.GetStream(_path);
defer delete data; defer delete data;
var readResult = data.Read<char8[8]>(); var readResult = data.Read<char8[8]>();
@@ -214,7 +220,7 @@ namespace GlitchyEngine.Renderer
{ {
Debug.Profiler.ProfileResourceFunction!(); Debug.Profiler.ProfileResourceFunction!();
Stream data = Application.Get().ContentManager.GetFile(_path); Stream data = Application.Get().ContentManager.GetStream(_path);
defer delete data; defer delete data;
LoadTexturePlatform(data); LoadTexturePlatform(data);
+16 -5
View File
@@ -6,6 +6,8 @@ using System.IO;
using GlitchyEngine.Math; using GlitchyEngine.Math;
using GlitchyEngine.Core; using GlitchyEngine.Core;
using System.Collections; using System.Collections;
using GlitchyEngine.Renderer;
using GlitchyEngine.Content;
namespace GlitchyEngine.World namespace GlitchyEngine.World
{ {
@@ -84,11 +86,10 @@ namespace GlitchyEngine.World
SerializeComponent<SpriterRendererComponent>(writer, entity, "SpriterRendererComponent", scope (component) => SerializeComponent<SpriterRendererComponent>(writer, entity, "SpriterRendererComponent", scope (component) =>
{ {
// TODO: Texture
Serialize.Value(writer, "Color", component.Color); Serialize.Value(writer, "Color", component.Color);
Serialize.Value(writer, "UvTransform", component.UvTransform);
Serialize.Value(writer, "IsCircle", component.IsCircle); Serialize.Value(writer, "IsCircle", component.IsCircle);
Serialize.Value(writer, "Sprite", component.Sprite);
Serialize.Value(writer, "UvTransform", component.UvTransform);
}); });
SerializeComponent<TransformComponent>(writer, entity, "TransformComponent", scope (component) => SerializeComponent<TransformComponent>(writer, entity, "TransformComponent", scope (component) =>
@@ -308,9 +309,19 @@ namespace GlitchyEngine.World
Try!(Deserialize.Value(reader, "Color", out component.Color)); Try!(Deserialize.Value(reader, "Color", out component.Color));
reader.EntryEnd(); reader.EntryEnd();
Try!(Deserialize.Value(reader, "UvTransform", out component.UvTransform));
reader.EntryEnd();
Try!(Deserialize.Value(reader, "IsCircle", out component.IsCircle)); Try!(Deserialize.Value(reader, "IsCircle", out component.IsCircle));
reader.EntryEnd();
String spriteName;
Try!(Deserialize.Value(reader, "Sprite", out spriteName));
if (spriteName != null)
component.Sprite = Content.LoadAsset<Texture2D>(spriteName);
delete spriteName;
reader.EntryEnd();
Try!(Deserialize.Value(reader, "UvTransform", out component.UvTransform));
return .Ok; return .Ok;
})); }));
+2 -2
View File
@@ -174,8 +174,8 @@ namespace Sandbox
rsDesc.FrontCounterClockwise = false; rsDesc.FrontCounterClockwise = false;
_rasterizerStateClockWise = new RasterizerState(rsDesc); _rasterizerStateClockWise = new RasterizerState(rsDesc);
_texture = new Texture2D("content/Textures/Checkerboard.dds"); _texture = Content.LoadAsset<Texture2D>("content/Textures/Checkerboard.dds");//new Texture2D("content/Textures/Checkerboard.dds");
_ge_logo = new Texture2D("content/Textures/GE_Logo.dds"); _ge_logo = Content.LoadAsset<Texture2D>("content/Textures/GE_Logo.dds");//new Texture2D("content/Textures/GE_Logo.dds");
let sampler = SamplerStateManager.GetSampler( let sampler = SamplerStateManager.GetSampler(
SamplerStateDescription() SamplerStateDescription()
+2 -2
View File
@@ -96,7 +96,7 @@ namespace Sandbox
_depthTarget = new DepthStencilTarget(_context.SwapChain.Width, _context.SwapChain.Height); _depthTarget = new DepthStencilTarget(_context.SwapChain.Width, _context.SwapChain.Height);
_checkerTexture = new Texture2D("content/Textures/Checkerboard.dds"); _checkerTexture = Content.LoadAsset<Texture2D>("content/Textures/Checkerboard.dds");//new Texture2D("content/Textures/Checkerboard.dds");
let sampler = SamplerStateManager.GetSampler( let sampler = SamplerStateManager.GetSampler(
SamplerStateDescription() SamplerStateDescription()
@@ -125,7 +125,7 @@ namespace Sandbox
_depthStencilState = new DepthStencilState(dssDesc); _depthStencilState = new DepthStencilState(dssDesc);
_spriteSheet = new Texture2D("content/Rpg/textures/spritesheet.png"); _spriteSheet = Content.LoadAsset<Texture2D>("content/Rpg/textures/spritesheet.png");//new Texture2D("content/Rpg/textures/spritesheet.png");
_spriteSheet.SamplerState = SamplerStateManager.PointClamp; _spriteSheet.SamplerState = SamplerStateManager.PointClamp;
_treeSprite = SubTexture2D.CreateFromGrid(_spriteSheet, Vector2(5, 10), Vector2(128), .(1, 2)); _treeSprite = SubTexture2D.CreateFromGrid(_spriteSheet, Vector2(5, 10), Vector2(128), .(1, 2));
+4 -4
View File
@@ -43,11 +43,11 @@ namespace Sandbox
_depthTarget = new DepthStencilTarget(_context.SwapChain.Width, _context.SwapChain.Height); _depthTarget = new DepthStencilTarget(_context.SwapChain.Width, _context.SwapChain.Height);
_checkerTexture = new Texture2D("content/Textures/Checkerboard.dds"); //_checkerTexture = new Texture2D("content/Textures/Checkerboard.dds");
_smallLines = new Texture2D("content/GammaTest/SmallLines.png"); //_smallLines = new Texture2D("content/GammaTest/SmallLines.png");
_gammaCorrectionBrightness = new Texture2D("content/GammaTest/gamma_correction_brightness.png"); //_gammaCorrectionBrightness = new Texture2D("content/GammaTest/gamma_correction_brightness.png");
_zeroPointFive = new Texture2D("content/GammaTest/zeroPointFive.png"); //_zeroPointFive = new Texture2D("content/GammaTest/zeroPointFive.png");
let sampler = SamplerStateManager.GetSampler( let sampler = SamplerStateManager.GetSampler(
SamplerStateDescription() SamplerStateDescription()