Handles barely work now, mostly no crashes

This commit is contained in:
Simon Lübeß
2023-03-16 17:57:23 +01:00
parent c3fb9bbd5d
commit b22f73a156
20 changed files with 780 additions and 627 deletions
@@ -1,7 +1,10 @@
{ {
Effect = "content/Shaders/myEffect.hlsl", Effect = "Shaders/myEffect.hlsl",
Textures = [ Textures = [
"AlbedoTexture": "Textures/TestMat/rustediron2_albedo.png" "AlbedoTexture": "Textures/TestMat/rustediron2_albedo.png",
"NormalTexture": "Textures\\TestMat\\rustediron2_normal.png",
"MetallicTexture": "",
"RoughnessTexture": ""
], ],
Variables = [ Variables = [
"AlbedoColor": .ColorRGBA{ "AlbedoColor": .ColorRGBA{
+2 -2
View File
@@ -31,7 +31,7 @@ class AssetFile
private bool _isDirectory; private bool _isDirectory;
private Object _loadedAsset; private Asset _loadedAsset;
public bool IsDirectory => _isDirectory; public bool IsDirectory => _isDirectory;
@@ -42,7 +42,7 @@ class AssetFile
public AssetConfig AssetConfig => _assetConfig; public AssetConfig AssetConfig => _assetConfig;
public Object LoadedAsset => _loadedAsset; public Asset LoadedAsset => _loadedAsset;
[AllowAppend] [AllowAppend]
public this(EditorContentManager contentManager, StringView identifier, StringView path, bool isDirectory) public this(EditorContentManager contentManager, StringView identifier, StringView path, bool isDirectory)
@@ -87,7 +87,7 @@ class MaterialAssetPropertiesEditor : AssetPropertiesEditor
AssetHandle<Texture2D> newTexture = Content.LoadAsset(path);//new Texture2D(path, true)) AssetHandle<Texture2D> newTexture = Content.LoadAsset(path);//new Texture2D(path, true))
newTexture.Get().SamplerState = SamplerStateManager.AnisotropicWrap; newTexture.Get().SamplerState = SamplerStateManager.AnisotropicWrap;
//material.SetTexture(texture.key, newTexture); material.SetTexture(texture.key, newTexture);
// TODO!!! // TODO!!!
} }
@@ -344,14 +344,14 @@ class MaterialAssetLoader : IAssetLoader, IAssetSaver //, IReloadingAssetLoader
// TODO: return error material // TODO: return error material
} }
Effect fx = new Effect(materialFile.Effect); Effect fx = Content.GetAsset<Effect>(contentManager.LoadAsset(materialFile.Effect), contentManager);//new Effect(materialFile.Effect);
Material material = new Material(fx); Material material = new Material(fx);
for (let (slotName, textureIdentifier) in materialFile.Textures) for (let (slotName, textureIdentifier) in materialFile.Textures)
{ {
using (Texture texture = contentManager.LoadAsset(textureIdentifier) as Texture) Texture texture = Content.GetAsset<Texture>(contentManager.LoadAsset(textureIdentifier), contentManager);
{
if (texture == null) if (texture == null)
{ {
Log.EngineLogger.Error($"Failed to load texture \"{textureIdentifier}\"."); Log.EngineLogger.Error($"Failed to load texture \"{textureIdentifier}\".");
@@ -360,9 +360,6 @@ class MaterialAssetLoader : IAssetLoader, IAssetSaver //, IReloadingAssetLoader
material.SetTexture(slotName, texture); material.SetTexture(slotName, texture);
} }
}
fx.ReleaseRef();
for (let (slotName, variableValue) in materialFile.Variables) for (let (slotName, variableValue) in materialFile.Variables)
{ {
@@ -409,10 +406,9 @@ class MaterialAssetLoader : IAssetLoader, IAssetSaver //, IReloadingAssetLoader
//material.SetTexture(); //material.SetTexture();
for (let (slotName, textureViewBinding) in material.[Friend]_textures) for (let (slotName, texture) in material.[Friend]_textures)
{ {
//materialFile.Textures.Add(slotName, textureViewBinding.) materialFile.Textures.Add(new String(slotName), new String(texture?.Identifier ?? ""));
} }
Effect effect = material.Effect; Effect effect = material.Effect;
@@ -513,7 +509,7 @@ class MaterialAssetLoader : IAssetLoader, IAssetSaver //, IReloadingAssetLoader
}*/ }*/
} }
materialFile.Variables.Add(name, variableValue); materialFile.Variables.Add(new String(name), variableValue);
} }
String text = scope .(); String text = scope .();
@@ -164,7 +164,7 @@ class EditorTextureAssetLoaderConfig : AssetLoaderConfig
} }
} }
class EditorTextureAssetLoader : IAssetLoader, IReloadingAssetLoader class EditorTextureAssetLoader : IAssetLoader//, IReloadingAssetLoader
{ {
private static readonly List<StringView> _fileExtensions = new .(){".png", ".dds"} ~ delete _; // ".jpg", ".bmp" private static readonly List<StringView> _fileExtensions = new .(){".png", ".dds"} ~ delete _; // ".jpg", ".bmp"
@@ -19,7 +19,7 @@ class PropertiesWindow : EditorWindow
private append String _selectedFileName = .(); private append String _selectedFileName = .();
private AssetHandle _currentAssetHandle; private AssetHandle _currentAssetHandle;
private Asset _currentAsset; //private Asset _currentAsset;
public this(Editor editor) public this(Editor editor)
{ {
@@ -75,13 +75,21 @@ class PropertiesWindow : EditorWindow
if (assetFile == null) if (assetFile == null)
return; return;
Asset asset = _editor.ContentManager.GetAsset(null, _currentAssetHandle);
// We need the actual asset for preview and sometimes for editing // We need the actual asset for preview and sometimes for editing
if (_currentAsset?.Identifier != assetFile.Identifier) if (asset?.Identifier != assetFile.Identifier)
{
_currentAssetHandle = _editor.ContentManager.LoadAsset(assetFile.Identifier);
}
/*if (asset != _currentAsset)
{ {
_currentAsset?.ReleaseRef(); _currentAsset?.ReleaseRef();
_currentAssetHandle = _editor.ContentManager.LoadAsset(assetFile.Identifier); _currentAsset = asset;
_currentAsset = _editor.ContentManager.GetAsset(null, _currentAssetHandle); _currentAsset?.AddRef();
} }*/
// TODO: allow changing AssetLoader // TODO: allow changing AssetLoader
// assetFile.AssetConfig.AssetLoade // assetFile.AssetConfig.AssetLoade
@@ -108,7 +116,8 @@ class PropertiesWindow : EditorWindow
if (ImGui.Button("Save Asset")) if (ImGui.Button("Save Asset"))
{ {
_editor.ContentManager.SaveAsset(_currentAsset); Asset asset = _editor.ContentManager.GetAsset(null, _currentAssetHandle);
_editor.ContentManager.SaveAsset(asset);
} }
if (!assetFile.AssetConfig.Config.Changed) if (!assetFile.AssetConfig.Config.Changed)
+140 -46
View File
@@ -81,7 +81,7 @@ class EditorContentManager : IContentManager
//private append List<String> _identifiers = .() ~ _.ClearAndDeleteItems(); //private append List<String> _identifiers = .() ~ _.ClearAndDeleteItems();
private append Dictionary<StringView, AssetHandle> _handles = .(); // TODO: Check if all resources are unloaded private append Dictionary<StringView, AssetHandle> _identiferToHandle = .(); // TODO: Check if all resources are unloaded
private append Dictionary<AssetHandle, Asset> _handleToAsset = .(); private append Dictionary<AssetHandle, Asset> _handleToAsset = .();
@@ -89,6 +89,8 @@ class EditorContentManager : IContentManager
public AssetHierarchy AssetHierarchy => _assetHierarchy; public AssetHierarchy AssetHierarchy => _assetHierarchy;
private append List<AssetHandle> _reloadQueue = .();
public this() public this()
{ {
_assetHierarchy.OnFileContentChanged.Add(new => OnFileContentChanged); _assetHierarchy.OnFileContentChanged.Add(new => OnFileContentChanged);
@@ -109,7 +111,9 @@ class EditorContentManager : IContentManager
if (assetNode.AssetFile.LoadedAsset == null) if (assetNode.AssetFile.LoadedAsset == null)
return; return;
String neededAssetLoaderName = assetNode.AssetFile.AssetConfig?.AssetLoader; _reloadQueue.Add(assetNode.AssetFile.LoadedAsset.Handle);
/*String neededAssetLoaderName = assetNode.AssetFile.AssetConfig?.AssetLoader;
if (String.IsNullOrWhiteSpace(neededAssetLoaderName)) if (String.IsNullOrWhiteSpace(neededAssetLoaderName))
return; return;
@@ -133,16 +137,18 @@ class EditorContentManager : IContentManager
{ {
Log.EngineLogger.Error($"Could not find asset loader \"{neededAssetLoaderName}\""); Log.EngineLogger.Error($"Could not find asset loader \"{neededAssetLoaderName}\"");
return; return;
} }*/
if (var assetReloader = assetLoader as IReloadingAssetLoader) /*if (var assetReloader = assetLoader as IReloadingAssetLoader)
{ {
Stream stream = GetStream(assetNode.Path); Stream stream = GetStream(assetNode.Path);
assetReloader.ReloadAsset(assetNode.AssetFile, stream); // TODO: reload asset
//assetReloader.ReloadAsset(assetNode.AssetFile, stream);
delete stream; delete stream;
} }*/
} }
public void SetContentDirectory(StringView contentDirectory) public void SetContentDirectory(StringView contentDirectory)
@@ -156,6 +162,15 @@ class EditorContentManager : IContentManager
public void Update() public void Update()
{ {
if (!_reloadQueue.IsEmpty)
{
for (AssetHandle handle in _reloadQueue)
{
ReloadAsset(handle);
}
_reloadQueue.Clear();
}
_assetHierarchy.Update(); _assetHierarchy.Update();
} }
@@ -241,7 +256,7 @@ class EditorContentManager : IContentManager
public bool IsLoaded(StringView identifier) public bool IsLoaded(StringView identifier)
{ {
return _handles.ContainsKey(identifier); return _identiferToHandle.ContainsKey(identifier);
} }
public Asset GetAsset(Type assetType, AssetHandle handle) public Asset GetAsset(Type assetType, AssetHandle handle)
@@ -254,7 +269,7 @@ class EditorContentManager : IContentManager
{ {
return asset; return asset;
} }
else if (asset.GetType() == assetType) else if (asset?.GetType().IsSubtypeOf(assetType) ?? false)
{ {
return asset; return asset;
} }
@@ -266,9 +281,74 @@ class EditorContentManager : IContentManager
} }
} }
private void ReloadAsset(AssetHandle handle)
{
Asset asset = null;
if (!_handleToAsset.TryGetValue(handle, out asset))
{
Log.EngineLogger.Error("Can't reload! No asset exists for handle.");
return;
}
Log.EngineLogger.AssertDebug(asset != null);
StringView oldIdentifier = asset.Identifier;
// Find subasset name
int poundIndex = oldIdentifier.IndexOf('#');
StringView resourceName = poundIndex == -1 ? oldIdentifier : oldIdentifier.Substring(0, poundIndex);
StringView? subassetName = oldIdentifier.Substring(poundIndex + 1);
String filePath = scope String(resourceName.Length + _contentDirectory.Length + 2);
Path.Combine(filePath, _contentDirectory, resourceName);
Path.Fixup(filePath);
//filePath.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
Result<TreeNode<AssetNode>> resultNode = AssetHierarchy.GetNodeFromPath(filePath);
if (resultNode case .Err)
{
Log.EngineLogger.Error($"Could not find asset \"{filePath}\".");
return;
}
AssetFile file = resultNode->Value.AssetFile;
IAssetLoader assetLoader = GetAssetLoader(file);
Log.EngineLogger.AssertDebug(assetLoader != null);
Stream stream = GetStream(filePath);
Asset loadedAsset = assetLoader.LoadAsset(stream, file.AssetConfig.Config, resourceName, subassetName, this);
delete stream;
if (loadedAsset == null)
return;
loadedAsset.Identifier = oldIdentifier;
loadedAsset.[Friend]_handle = handle;
// Remove asset
_identiferToHandle.Remove(oldIdentifier);
Asset oldAsset = _handleToAsset[handle];
oldAsset.ReleaseRef();
_handleToAsset[handle] = loadedAsset;
_identiferToHandle.Add(loadedAsset.Identifier, handle);
file.[Friend]_loadedAsset = loadedAsset;
}
public AssetHandle LoadAsset(StringView identifier) public AssetHandle LoadAsset(StringView identifier)
{ {
if (_handles.TryGetValue(identifier, let asset)) if (_identiferToHandle.TryGetValue(identifier, let asset))
{ {
return asset; return asset;
} }
@@ -296,20 +376,7 @@ class EditorContentManager : IContentManager
AssetFile file = resultNode->Value.AssetFile; AssetFile file = resultNode->Value.AssetFile;
IAssetLoader assetLoader = null; IAssetLoader assetLoader = GetAssetLoader(file);
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); Log.EngineLogger.AssertDebug(assetLoader != null);
@@ -329,12 +396,38 @@ class EditorContentManager : IContentManager
loadedAsset.Identifier = identifier; loadedAsset.Identifier = identifier;
AssetHandle handle = ManageAsset(loadedAsset); AssetHandle handle = ManageAsset(loadedAsset);
// ManageAsset increases RefCount
loadedAsset.ReleaseRef();
// Add to Identifier -> Handle map
_identiferToHandle.Add(loadedAsset.Identifier, handle);
file.[Friend]_loadedAsset = loadedAsset; file.[Friend]_loadedAsset = loadedAsset;
return handle; return handle;
} }
/// Gets the asset loader that has to be used for the given file.
IAssetLoader GetAssetLoader(AssetFile file)
{
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;
}
}
return assetLoader;
}
/// Saves the asset. /// Saves the asset.
public Result<void> SaveAsset(Asset asset) public Result<void> SaveAsset(Asset asset)
{ {
@@ -355,20 +448,7 @@ class EditorContentManager : IContentManager
AssetFile file = assetNode->AssetFile; AssetFile file = assetNode->AssetFile;
IAssetLoader assetLoader = null; IAssetLoader assetLoader = GetAssetLoader(file);
String loaderTypeName = scope .(128);
for (IAssetLoader loader in _assetLoaders)
{
loader.GetType().GetName(loaderTypeName..Clear());
if (loaderTypeName == file.AssetConfig.AssetLoader)
{
assetLoader = loader;
break;
}
}
IAssetSaver assetSaver = assetLoader as IAssetSaver; IAssetSaver assetSaver = assetLoader as IAssetSaver;
@@ -382,6 +462,7 @@ class EditorContentManager : IContentManager
assetSaver.EditorSaveAsset(stream, asset, file.AssetConfig.Config, resourceName, subassetName, this); assetSaver.EditorSaveAsset(stream, asset, file.AssetConfig.Config, resourceName, subassetName, this);
stream.SetLength(stream.Position);
delete stream; delete stream;
return .Ok; return .Ok;
@@ -403,8 +484,8 @@ class EditorContentManager : IContentManager
FileMode fileMode = openOnly ? FileMode.Open : FileMode.OpenOrCreate; FileMode fileMode = openOnly ? FileMode.Open : FileMode.OpenOrCreate;
if (truncate) /*if (truncate)
fileMode |= .Truncate; fileMode |= .Truncate;*/
var result = fs.Open(assetIdentifier, fileMode, openOnly ? .Read : .ReadWrite, .ReadWrite); var result = fs.Open(assetIdentifier, fileMode, openOnly ? .Read : .ReadWrite, .ReadWrite);
@@ -440,26 +521,39 @@ class EditorContentManager : IContentManager
public AssetHandle ManageAsset(Asset asset) public AssetHandle ManageAsset(Asset asset)
{ {
AssetHandle handle = .(asset.Identifier); Log.EngineLogger.AssertDebug(asset.Handle == .Invalid, "Asset is already managed.");
Log.EngineLogger.AssertDebug(asset.ContentManager == null, "Asset is already managed.");
// TODO: to ensure that no two assets with the same handle exist. AssetHandle handle = .();
_handles.Add(asset.Identifier, handle); // Generate until we find a unique key (shouldn't happen too often)
while (_handleToAsset.ContainsKey(handle))
{
handle = .();
// TODO: perhaps test how often this happens.
// If this happens too often we could use a different random generator
}
//_handles.Add(asset.Identifier, handle);
_handleToAsset.Add(handle, asset); _handleToAsset.Add(handle, asset);
asset.[Friend]_contentManager = this; asset.[Friend]_contentManager = this;
asset.[Friend]_handle = handle; asset.[Friend]_handle = handle;
asset.AddRef();
return handle; return handle;
} }
public void UnmanageAsset(AssetHandle handle) public void UnmanageAsset(AssetHandle handle)
{ {
Log.EngineLogger.AssertDebug(_handles.ContainsValue(handle), "Handle isn't managed by this content manager."); //Log.EngineLogger.AssertDebug(_handles.ContainsValue(handle), "Handle isn't managed by this content manager.");
Log.EngineLogger.AssertDebug(_handleToAsset.ContainsKey(handle), "Handle doesn't correspond to an asset."); Log.EngineLogger.AssertDebug(_handleToAsset.ContainsKey(handle), "Handle doesn't correspond to an asset.");
Asset asset = _handleToAsset[handle]; Asset asset = _handleToAsset[handle];
_handles.Remove(asset.Identifier);
if (_identiferToHandle.ContainsKey(asset.Identifier))
_identiferToHandle.Remove(asset.Identifier);
_handleToAsset.Remove(handle); _handleToAsset.Remove(handle);
asset.[Friend]_contentManager = null; asset.[Friend]_contentManager = null;
@@ -470,7 +564,7 @@ class EditorContentManager : IContentManager
/// Note: This will not release any assets. /// Note: This will not release any assets.
private void UnmanageAllAssets() private void UnmanageAllAssets()
{ {
for (let (_, assetHandle) in _handles) for (let (_, assetHandle) in _identiferToHandle)
{ {
UnmanageAsset(assetHandle); UnmanageAsset(assetHandle);
} }
@@ -485,7 +579,7 @@ class EditorContentManager : IContentManager
if (oldIdentifier == newIdentifier) if (oldIdentifier == newIdentifier)
return; return;
Log.EngineLogger.Assert(_handles.ContainsKey(newIdentifier), "An asset with the same identifier is already managed by this content manager."); Log.EngineLogger.Assert(_identiferToHandle.ContainsKey(newIdentifier), "An asset with the same identifier is already managed by this content manager.");
// Since all we do in order to track assets is add them to a dictionary we can simply unmanage and manage it again. // Since all we do in order to track assets is add them to a dictionary we can simply unmanage and manage it again.
//UnmanageAsset(asset); //UnmanageAsset(asset);
+4 -7
View File
@@ -10,7 +10,7 @@ namespace GlitchyEngine.Content;
[BonTarget] [BonTarget]
class Asset : RefCounter class Asset : RefCounter
{ {
internal AssetHandle _handle; internal AssetHandle _handle = .Invalid;
private append String _identifier; private append String _identifier;
@@ -60,16 +60,13 @@ class Asset : RefCounter
static Result<void> AssetDeserialize(BonReader reader, ValueView value, BonEnvironment environment, DeserializeValueState state) static Result<void> AssetDeserialize(BonReader reader, ValueView value, BonEnvironment environment, DeserializeValueState state)
{ {
// TODO!!! Log.EngineLogger.Assert(value.type == typeof(Asset));
return .Err;
/*Log.EngineLogger.Assert(value.type == typeof(Asset));
String identifier = scope .(); String identifier = scope .();
Deserialize.String!(reader, ref identifier, environment); Deserialize.String!(reader, ref identifier, environment);
Asset asset = Application.Get().ContentManager.LoadAsset(identifier); Asset asset = Content.GetAsset<Asset>(Content.LoadAsset(identifier));
if (asset != null) if (asset != null)
{ {
@@ -82,7 +79,7 @@ class Asset : RefCounter
else else
{ {
Deserialize.Error!("Invalid resource path", reader, value.type); Deserialize.Error!("Invalid resource path", reader, value.type);
}*/ }
} }
//gBonEnv.typeHandlers.Add(typeof(Resource<>), //gBonEnv.typeHandlers.Add(typeof(Resource<>),
+28 -12
View File
@@ -3,16 +3,25 @@ using xxHash;
using System.Collections; using System.Collections;
using System.Reflection; using System.Reflection;
using System.Diagnostics; using System.Diagnostics;
using GlitchyEngine.Core;
namespace GlitchyEngine.Content; namespace GlitchyEngine.Content;
struct AssetHandle : uint64 struct AssetHandle : IHashable
{ {
/// Defines an asset that is invalid. E.g. because it couldn't be loaded. private UUID _uuid;
public const AssetHandle Invalid = (.)0;
public this(StringView name) /// Defines an asset that is invalid.
public const AssetHandle Invalid = .(UUID(0xAAAA'AAAA'AAAA'AAAA));
/// Create a new random AssetHandle
public this()
{ {
this = (uint64)xxHash.ComputeHash(name); _uuid = UUID();
}
private this(UUID uuid)
{
_uuid = uuid;
} }
[Inline] [Inline]
@@ -20,6 +29,8 @@ struct AssetHandle : uint64
{ {
return Content.GetAsset<T>(this, contentManager); return Content.GetAsset<T>(this, contentManager);
} }
public int GetHashCode() => _uuid.GetHashCode();
} }
struct AssetHandle<T> where T : Asset struct AssetHandle<T> where T : Asset
@@ -30,25 +41,27 @@ struct AssetHandle<T> where T : Asset
* We don't increment/decrement the reference counter since we guarantee that we query for the asset every frame. * We don't increment/decrement the reference counter since we guarantee that we query for the asset every frame.
*/ */
private T _asset; private T _asset;
private uint8 _currentFrame; //private uint8 _currentFrame;
//private uint64 _actualCurrentFrame = 0;
public const Self Invalid = .(); public const Self Invalid = .();
public this(AssetHandle handle, IContentManager contentManager = null) public this(AssetHandle handle, IContentManager contentManager = null)
{ {
_handle = handle; _handle = handle;
_contentManager = contentManager;
_asset = handle.Get<T>(contentManager); _asset = handle.Get<T>(contentManager);
_contentManager = _asset.ContentManager; _contentManager = _asset?.ContentManager;
_currentFrame = (uint8)Application.Get().GameTime.FrameCount; if (_contentManager == null)
_contentManager = contentManager;
//_currentFrame = (uint8)Application.Get().GameTime.FrameCount;
} }
// Creates a new invalid asset handle // Creates a new invalid asset handle
private this() private this()
{ {
_handle = .Invalid; _handle = .Invalid;
_currentFrame = 0; //_currentFrame = 0;
_contentManager = null; _contentManager = null;
_asset = null; _asset = null;
} }
@@ -71,11 +84,14 @@ struct AssetHandle<T> where T : Asset
public T Get(IContentManager contentManager = null) mut public T Get(IContentManager contentManager = null) mut
{ {
// We only care whether we are in a different frame -> we only compare the lower 8 bits. // We only care whether we are in a different frame -> we only compare the lower 8 bits.
uint8 actualFrame = (uint8)Application.Get().GameTime.FrameCount; //uint8 actualFrame = (uint8)Application.Get().GameTime.FrameCount;
//var actualActualFrame = Application.Get().GameTime.FrameCount;
if (actualFrame != _currentFrame) //if (actualFrame != _currentFrame)
{ {
_asset = Content.GetAsset<T>(_handle, contentManager == null ? _contentManager : contentManager); _asset = Content.GetAsset<T>(_handle, contentManager == null ? _contentManager : contentManager);
//_currentFrame = actualFrame;
//_actualCurrentFrame = Application.Get().GameTime.FrameCount;
} }
return _asset; return _asset;
@@ -86,6 +86,26 @@ namespace GlitchyEngine.Content
return (T)asset; return (T)asset;
} }
public static AssetHandle ManageAsset(Asset asset, IContentManager contentManager = null)
{
var contentManager;
if (contentManager == null)
contentManager = Application.Get().ContentManager;
return contentManager.ManageAsset(asset);
}
/*public static AssetHandle<T> ManageAsset<T>(T asset, IContentManager contentManager = null) where T : Asset
{
var contentManager;
if (contentManager == null)
contentManager = Application.Get().ContentManager;
contentManager.ManageAsset(asset);
}*/
} }
interface IContentManager interface IContentManager
+12 -8
View File
@@ -229,7 +229,7 @@ namespace GlitchyEngine.Content
return .Success; return .Success;
} }
public static EcsEntity LoadModel(String filename, Material material, EcsWorld world, /*public static EcsEntity LoadModel(String filename, Material material, EcsWorld world,
List<AnimationClip> outClips, StringView entityName = StringView()) List<AnimationClip> outClips, StringView entityName = StringView())
{ {
CGLTF.Options options = .(); CGLTF.Options options = .();
@@ -252,7 +252,7 @@ namespace GlitchyEngine.Content
CGLTF.Free(data); CGLTF.Free(data);
return entity; return entity;
} }*/
private static (EcsEntity Entity, TransformComponent* Transform) CreateEntity(EcsWorld world, StringView? name, EcsEntity parent) private static (EcsEntity Entity, TransformComponent* Transform) CreateEntity(EcsWorld world, StringView? name, EcsEntity parent)
{ {
@@ -280,7 +280,7 @@ namespace GlitchyEngine.Content
return (entity, childTransform); return (entity, childTransform);
} }
private static void NodesToEntities(CGLTF.Data* data, CGLTF.Node* node, EcsEntity parentEntity, EcsWorld world, Material material, List<AnimationClip> clips) /*private static void NodesToEntities(CGLTF.Data* data, CGLTF.Node* node, EcsEntity parentEntity, EcsWorld world, Material material, List<AnimationClip> clips)
{ {
(EcsEntity entity, TransformComponent* childTransform) = CreateEntity(world, node.Name == null ? null : StringView(node.Name), parentEntity); (EcsEntity entity, TransformComponent* childTransform) = CreateEntity(world, node.Name == null ? null : StringView(node.Name), parentEntity);
@@ -328,13 +328,13 @@ namespace GlitchyEngine.Content
using (var geo = PrimitiveToGeoBinding(node.Mesh.Primitives[0])) using (var geo = PrimitiveToGeoBinding(node.Mesh.Primitives[0]))
{ {
mesh.Mesh = geo; mesh.Mesh = Content.ManageAsset(geo);
} }
if(skeleton == null) if(skeleton == null)
{ {
var meshRenderer = world.AssignComponent<MeshRendererComponent>(entity); var meshRenderer = world.AssignComponent<MeshRendererComponent>(entity);
meshRenderer.Material = material; meshRenderer.Material = material.Handle;
} }
else else
{ {
@@ -354,12 +354,16 @@ namespace GlitchyEngine.Content
meshParent.Entity = entity; meshParent.Entity = entity;
var mesh = world.AssignComponent<MeshComponent>(meshEntity); var mesh = world.AssignComponent<MeshComponent>(meshEntity);
mesh.Mesh = PrimitiveToGeoBinding(primitive);
using (var geo = PrimitiveToGeoBinding(primitive))
{
mesh.Mesh = Content.ManageAsset(geo);
}
if(skeleton == null) if(skeleton == null)
{ {
var meshRenderer = world.AssignComponent<MeshRendererComponent>(meshEntity); var meshRenderer = world.AssignComponent<MeshRendererComponent>(meshEntity);
meshRenderer.Material = material; meshRenderer.Material = material.Handle;
} }
else else
{ {
@@ -377,7 +381,7 @@ namespace GlitchyEngine.Content
{ {
NodesToEntities(data, child, entity, world, material, clips); NodesToEntities(data, child, entity, world, material, clips);
} }
} }*/
public static GeometryBinding PrimitiveToGeoBinding(CGLTF.Primitive primitive) public static GeometryBinding PrimitiveToGeoBinding(CGLTF.Primitive primitive)
{ {
+3
View File
@@ -212,6 +212,9 @@ public class Effect : Asset
{ {
Debug.Profiler.ProfileRendererFunction!(); Debug.Profiler.ProfileRendererFunction!();
if (texture == null)
return;
[Inline]InternalSetTexture(name, texture.GetViewBinding()); [Inline]InternalSetTexture(name, texture.GetViewBinding());
} }
+10 -8
View File
@@ -14,7 +14,7 @@ public class Material : Asset
private uint8[] _rawVariables ~ delete _; private uint8[] _rawVariables ~ delete _;
private Dictionary<String, TextureViewBinding> _textures = new .(); private Dictionary<String, Texture> _textures = new .();
private Dictionary<String, (uint32 Offset, BufferVariable Variable)> _variables = new .() ~ delete _; private Dictionary<String, (uint32 Offset, BufferVariable Variable)> _variables = new .() ~ delete _;
@@ -26,12 +26,14 @@ public class Material : Asset
// TODO: get variables from effect // TODO: get variables from effect
// Get texture slots from effect
for(let (name, entry) in _effect.Textures) for(let (name, entry) in _effect.Textures)
{ {
var texture = entry.BoundTexture; // TODO: Do we want to be able to define textures in the shader?
texture.AddRef(); /*var texture = entry.BoundTexture;
texture.AddRef();*/
_textures.Add(name, texture); _textures.Add(name, null);
} }
InitRawData(); InitRawData();
@@ -41,7 +43,7 @@ public class Material : Asset
{ {
for(let (name, texture) in _textures) for(let (name, texture) in _textures)
{ {
texture.Release(); texture?.ReleaseRef();
} }
delete _textures; delete _textures;
@@ -92,9 +94,9 @@ public class Material : Asset
{ {
if(_textures.TryGetValue(name, var entry)) if(_textures.TryGetValue(name, var entry))
{ {
entry.Release(); entry?.ReleaseRef();
_textures[name] = texture.GetViewBinding(); _textures[name] = texture;
//texture?.AddRef(); texture?.AddRef();
} }
else else
{ {
+1 -1
View File
@@ -6,7 +6,7 @@ namespace GlitchyEngine.Renderer
{ {
public struct MeshComponent// : IDisposableComponent public struct MeshComponent// : IDisposableComponent
{ {
public AssetHandle<GeometryBinding> Mesh {get; set mut;} public AssetHandle<GeometryBinding> Mesh {get; set mut;} = .Invalid;
/* /*
private GeometryBinding _mesh; private GeometryBinding _mesh;
public AssetHandle<GeometryBinding> Mesh public AssetHandle<GeometryBinding> Mesh
+3
View File
@@ -469,6 +469,9 @@ namespace GlitchyEngine.Renderer
{ {
Debug.Profiler.ProfileRendererFunction!(); Debug.Profiler.ProfileRendererFunction!();
if (geometry == null || material == null)
return;
_queue.Add(SubmittedMesh(geometry, material, transform, entity.[Friend]Index)); _queue.Add(SubmittedMesh(geometry, material, transform, entity.[Friend]Index));
} }
+2 -2
View File
@@ -876,9 +876,9 @@ namespace GlitchyEngine.Renderer
public static void DrawSprite(Matrix transform, SpriterRendererComponent* spriteRenderer, uint32 entityId) public static void DrawSprite(Matrix transform, SpriterRendererComponent* spriteRenderer, uint32 entityId)
{ {
if (spriteRenderer.IsCircle) if (spriteRenderer.IsCircle)
DrawCircle(transform, spriteRenderer.Sprite ?? s_whiteTexture, spriteRenderer.Color, 1.0f, spriteRenderer.UvTransform, entityId); DrawCircle(transform, spriteRenderer.Sprite.Get() ?? s_whiteTexture, spriteRenderer.Color, 1.0f, spriteRenderer.UvTransform, entityId);
else else
DrawQuad(transform, spriteRenderer.Sprite ?? s_whiteTexture, spriteRenderer.Color, spriteRenderer.UvTransform, entityId); DrawQuad(transform, spriteRenderer.Sprite.Get() ?? s_whiteTexture, spriteRenderer.Color, spriteRenderer.UvTransform, entityId);
} }
// Textured quad pivot // Textured quad pivot
@@ -7,7 +7,7 @@ namespace GlitchyEngine.World
/// A component that allows to render a mesh. /// A component that allows to render a mesh.
public struct MeshRendererComponent// : IDisposableComponent public struct MeshRendererComponent// : IDisposableComponent
{ {
private AssetHandle<Material> _material; private AssetHandle<Material> _material = .Invalid;
public AssetHandle<Material> Material public AssetHandle<Material> Material
{ {
+1 -1
View File
@@ -445,7 +445,7 @@ namespace GlitchyEngine.World
for (var (entity, transform, mesh, meshRenderer) in _ecsWorld.Enumerate<TransformComponent, MeshComponent, MeshRendererComponent>()) for (var (entity, transform, mesh, meshRenderer) in _ecsWorld.Enumerate<TransformComponent, MeshComponent, MeshRendererComponent>())
{ {
if (mesh.Mesh == null || meshRenderer.Material == null) if (mesh.Mesh == .Invalid || meshRenderer.Material == .Invalid)
continue; continue;
Renderer.Submit(mesh.Mesh, meshRenderer.Material, entity, transform.WorldTransform); Renderer.Submit(mesh.Mesh, meshRenderer.Material, entity, transform.WorldTransform);
+24 -19
View File
@@ -9,12 +9,12 @@ using System.Collections;
using GlitchyEngine.Renderer; using GlitchyEngine.Renderer;
using GlitchyEngine.Content; using GlitchyEngine.Content;
namespace GlitchyEngine.World namespace GlitchyEngine.World;
{
using internal GlitchyEngine.World;
class SceneSerializer using internal GlitchyEngine.World;
{
class SceneSerializer
{
private Scene _scene; private Scene _scene;
// Maps from ParentID to ChildEntity // Maps from ParentID to ChildEntity
@@ -270,7 +270,7 @@ namespace GlitchyEngine.World
private Result<void> DeserializeEntity(BonReader reader) private Result<void> DeserializeEntity(BonReader reader)
{ {
mixin DeserializeAsset<T>(StringView identifier) where T : Asset /*mixin DeserializeAsset<T>(StringView identifier) where T : Asset
{ {
Asset asset = null; Asset asset = null;
@@ -283,6 +283,21 @@ namespace GlitchyEngine.World
} }
(T)asset (T)asset
}*/
mixin DeserializeAssetHandle<T>(StringView identifier) where T : Asset
{
Asset asset = null;
Try!(Deserialize.Value(reader, identifier, out asset));
if (asset != null && !(asset is T))
{
Log.EngineLogger.Error($"Asset {asset.Identifier} is not a {nameof(T)}.");
return .Err;
}
asset?.Handle ?? .Invalid
} }
Try!(reader.ObjectBlock()); Try!(reader.ObjectBlock());
@@ -322,10 +337,7 @@ namespace GlitchyEngine.World
Try!(Deserialize.Value(reader, "IsCircle", out component.IsCircle)); Try!(Deserialize.Value(reader, "IsCircle", out component.IsCircle));
reader.EntryEnd(); reader.EntryEnd();
using (Texture2D sprite = DeserializeAsset!<Texture2D>("Sprite")) component.Sprite = DeserializeAssetHandle!<Texture2D>("Sprite");
{
component.Sprite = (Texture2D)sprite;
}
reader.EntryEnd(); reader.EntryEnd();
Try!(Deserialize.Value(reader, "UvTransform", out component.UvTransform)); Try!(Deserialize.Value(reader, "UvTransform", out component.UvTransform));
@@ -474,20 +486,14 @@ namespace GlitchyEngine.World
case "MeshComponent": case "MeshComponent":
Try!(DeserializeComponent<MeshComponent>(reader, entity, scope (component) => Try!(DeserializeComponent<MeshComponent>(reader, entity, scope (component) =>
{ {
using (GeometryBinding mesh = DeserializeAsset!<GeometryBinding>("Mesh")) component.Mesh = DeserializeAssetHandle!<GeometryBinding>("Mesh");
{
component.Mesh = mesh;
}
return .Ok; return .Ok;
})); }));
case "MeshRendererComponent": case "MeshRendererComponent":
Try!(DeserializeComponent<MeshRendererComponent>(reader, entity, scope (component) => Try!(DeserializeComponent<MeshRendererComponent>(reader, entity, scope (component) =>
{ {
using (Material material = DeserializeAsset!<Material>("Material")) component.Material = DeserializeAssetHandle!<Material>("Material");
{
component.Material = material;
}
return .Ok; return .Ok;
})); }));
@@ -595,5 +601,4 @@ namespace GlitchyEngine.World
{ {
Runtime.NotImplemented(); Runtime.NotImplemented();
} }
}
} }
+3 -2
View File
@@ -1,4 +1,4 @@
using System; /*using System;
using GlitchyEngine; using GlitchyEngine;
using GlitchyEngine.Events; using GlitchyEngine.Events;
using System.Diagnostics; using System.Diagnostics;
@@ -12,6 +12,7 @@ using GlitchyEngine.Renderer.Text;
using System.IO; using System.IO;
using msdfgen; using msdfgen;
using System.Collections; using System.Collections;
using GlitchyEngine.Content;
namespace Sandbox namespace Sandbox
{ {
@@ -282,4 +283,4 @@ namespace Sandbox
return false; return false;
} }
} }
} }*/
+1 -1
View File
@@ -21,7 +21,7 @@ namespace Sandbox
#if GAMMA_TEST #if GAMMA_TEST
PushLayer(new GammaTestLayer()); PushLayer(new GammaTestLayer());
#elif SANDBOX_2D #elif SANDBOX_2D
PushLayer(new ExampleLayer2D()); //PushLayer(new ExampleLayer2D());
#else #else
PushLayer(new ExampleLayer()); PushLayer(new ExampleLayer());
#endif #endif