mirror of
https://github.com/aharabada/glitchy-engine-beef.git
synced 2026-09-05 13:01:52 +00:00
EditorContentManager Part 1
This commit is contained in:
@@ -5,6 +5,9 @@ using System.Collections;
|
||||
using GlitchyEngine.Renderer;
|
||||
using System.Threading;
|
||||
using GlitchyEngine.Content;
|
||||
using GlitchyEditor.Assets;
|
||||
using GlitchyEngine;
|
||||
using System.Linq;
|
||||
|
||||
namespace GlitchyEditor;
|
||||
|
||||
@@ -70,52 +73,71 @@ namespace GlitchyEditor;
|
||||
}
|
||||
}*/
|
||||
|
||||
class EditorContentManager
|
||||
public class AssetNode
|
||||
{
|
||||
// TODO: Get from project
|
||||
const String ContentDirectory = "./content";
|
||||
public String Name ~ delete _;
|
||||
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 ~ {
|
||||
_.StopRaisingEvents();
|
||||
delete _;
|
||||
};
|
||||
|
||||
bool _fileSystemDirty = true;
|
||||
|
||||
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();
|
||||
}
|
||||
bool _fileSystemDirty = false;
|
||||
|
||||
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 void SetContentDirectory(StringView contentDirectory)
|
||||
{
|
||||
_contentDirectory.Clear();
|
||||
_contentDirectory.Append(contentDirectory);
|
||||
_fileSystemDirty = true;
|
||||
|
||||
SetupFileSystemWatcher();
|
||||
}
|
||||
|
||||
/// Initializes the FSW for the current ContentDirectory and registers the events.
|
||||
private void SetupFileSystemWatcher()
|
||||
{
|
||||
delete fsw;
|
||||
fsw = new FileSystemWatcher(ContentDirectory);
|
||||
fsw.IncludeSubdirectories = true;
|
||||
|
||||
@@ -140,6 +162,7 @@ class EditorContentManager
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// TODO: do we really need to do this in the update loop?
|
||||
if (_fileSystemDirty)
|
||||
{
|
||||
UpdateFiles();
|
||||
@@ -148,24 +171,26 @@ class EditorContentManager
|
||||
|
||||
private void UpdateFiles()
|
||||
{
|
||||
// TODO: we don't need to rebuild the entire tree!
|
||||
DeleteTreeAndChildren!(_assetHierarchy);
|
||||
|
||||
_assetHierarchy = new TreeNode<AssetNode>(new AssetNode());
|
||||
_assetHierarchy->Path = new String(ContentDirectory);
|
||||
_assetHierarchy->Name = new String("Content");
|
||||
|
||||
String str = scope .(ContentDirectory);
|
||||
|
||||
void GrabSubAssets(TreeNode<AssetNode> assetNode)
|
||||
/*void GrabSubAssets(TreeNode<AssetNode> assetNode)
|
||||
{
|
||||
// TODO: Dedicated asset loaders that register their extensions, etc....!
|
||||
|
||||
if (assetNode->Name.EndsWith(".png", .OrdinalIgnoreCase))
|
||||
{
|
||||
assetNode->SubAssets = new List<Asset>();
|
||||
assetNode->SubAssets.Add(new Asset()
|
||||
assetNode->SubAssets = new:allocator List<Asset>();
|
||||
assetNode->SubAssets.Add(new:allocator Asset()
|
||||
{
|
||||
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))
|
||||
@@ -173,11 +198,11 @@ class EditorContentManager
|
||||
List<String> meshNames = scope List<String>();
|
||||
ModelLoader.GetMeshNames(assetNode->Path, meshNames);
|
||||
|
||||
assetNode->SubAssets = new List<Asset>();
|
||||
assetNode->SubAssets = new:allocator List<Asset>();
|
||||
|
||||
for (var meshName in meshNames)
|
||||
{
|
||||
assetNode->SubAssets.Add(new Asset()
|
||||
assetNode->SubAssets.Add(new:allocator Asset()
|
||||
{
|
||||
Asset = assetNode.Value,
|
||||
// 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)
|
||||
@@ -192,11 +222,18 @@ class EditorContentManager
|
||||
String filter = scope $"{directory->Path}/*";
|
||||
|
||||
String buffer = scope String();
|
||||
String extensionBuffer = scope String();
|
||||
|
||||
for (var entry in Directory.Enumerate(filter, .Files))
|
||||
{
|
||||
entry.GetFilePath(buffer..Clear());
|
||||
|
||||
Path.GetExtension(buffer, extensionBuffer..Clear());
|
||||
|
||||
// Don't add meta-files
|
||||
if (extensionBuffer == ".ass")
|
||||
continue;
|
||||
|
||||
AssetNode e = new AssetNode();
|
||||
e.Name = new String();
|
||||
Path.GetFileName(buffer, e.Name);
|
||||
@@ -206,7 +243,8 @@ class EditorContentManager
|
||||
e.IsDirectory = entry.IsDirectory;
|
||||
|
||||
var node = directory.AddChild(e);
|
||||
GrabSubAssets(node);
|
||||
//GrabSubAssets(node);
|
||||
HandleFile(node.Value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -244,4 +282,111 @@ class EditorContentManager
|
||||
|
||||
_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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user