mirror of
https://github.com/aharabada/glitchy-engine-beef.git
synced 2026-09-05 21:01:52 +00:00
Model and Material loading via content manager
This commit is contained in:
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
AssetLoader = "ModelAssetLoader",
|
||||||
|
Config = (GlitchyEditor.Assets.ModelAssetLoaderConfig){}
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
AssetLoader = "ModelAssetLoader",
|
||||||
|
Config = (GlitchyEditor.Assets.ModelAssetLoaderConfig){}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
Effect = "content/Shaders/myEffect.hlsl",
|
||||||
|
Textures =
|
||||||
|
[
|
||||||
|
"AlbedoTexture": "Textures/TestMat/rustediron2_albedo.png"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
AssetLoader = "MaterialAssetLoader",
|
||||||
|
Config = (GlitchyEditor.Assets.ModelAssetLoaderConfig){}
|
||||||
|
}
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
{
|
{
|
||||||
AssetLoader = "EditorTextureAssetLoader",
|
AssetLoader = "EditorTextureAssetLoader",
|
||||||
Config = (GlitchyEditor.Assets.EditorTextureAssetLoaderConfig){
|
Config = (GlitchyEditor.Assets.EditorTextureAssetLoaderConfig){
|
||||||
|
_isSrgb = true,
|
||||||
_samplerStateDescription = {
|
_samplerStateDescription = {
|
||||||
MinFilter = .Linear,
|
MinFilter = .Linear,
|
||||||
MagFilter = .Point,
|
|
||||||
MipFilter = .Linear,
|
MipFilter = .Linear,
|
||||||
ComparisonFunction = .Never,
|
ComparisonFunction = .Never,
|
||||||
AddressModeU = .Clamp,
|
AddressModeU = .Clamp,
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
{
|
{
|
||||||
AssetLoader = "EditorTextureAssetLoader",
|
AssetLoader = "EditorTextureAssetLoader",
|
||||||
Config = (GlitchyEditor.Assets.EditorTextureAssetLoaderConfig){
|
Config = (GlitchyEditor.Assets.EditorTextureAssetLoaderConfig){
|
||||||
|
_isSrgb = true,
|
||||||
_samplerStateDescription = {
|
_samplerStateDescription = {
|
||||||
MinFilter = .Linear,
|
MinFilter = .Linear,
|
||||||
MagFilter = .Linear,
|
|
||||||
MipFilter = .Linear,
|
|
||||||
ComparisonFunction = .Never,
|
ComparisonFunction = .Never,
|
||||||
AddressModeU = .Clamp,
|
AddressModeU = .Clamp,
|
||||||
AddressModeV = .Clamp,
|
AddressModeV = .Clamp,
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
namespace GlitchyEditor.Assets;
|
||||||
|
|
||||||
|
abstract class AssetPropertiesEditor
|
||||||
|
{
|
||||||
|
private AssetFile _asset;
|
||||||
|
|
||||||
|
public AssetFile Asset => _asset;
|
||||||
|
|
||||||
|
public this(AssetFile asset)
|
||||||
|
{
|
||||||
|
_asset = asset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void ShowEditor();
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace GlitchyEditor.Assets;
|
||||||
|
|
||||||
|
interface IReloadingAssetLoader
|
||||||
|
{
|
||||||
|
public void ReloadAsset(AssetFile assetFile, Stream data);
|
||||||
|
}
|
||||||
@@ -0,0 +1,106 @@
|
|||||||
|
using Bon;
|
||||||
|
using GlitchyEngine.Content;
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.IO;
|
||||||
|
using GlitchyEngine;
|
||||||
|
using GlitchyEngine.Renderer;
|
||||||
|
|
||||||
|
namespace GlitchyEditor.Assets;
|
||||||
|
|
||||||
|
class MaterialAssetPropertiesEditor : AssetPropertiesEditor
|
||||||
|
{
|
||||||
|
public this(AssetFile asset) : base(asset)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void ShowEditor()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AssetPropertiesEditor Factory(AssetFile assetFile)
|
||||||
|
{
|
||||||
|
return new Self(assetFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[BonTarget, BonPolyRegister]
|
||||||
|
class MaterialAssetLoaderConfig : AssetLoaderConfig
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[BonTarget]
|
||||||
|
class MaterialFile
|
||||||
|
{
|
||||||
|
public String Effect ~ delete _;
|
||||||
|
|
||||||
|
public Dictionary<String, String> Textures ~ DeleteDictionaryAndKeysAndValues!(_);
|
||||||
|
//public Dictionary<String, Object> Variables;
|
||||||
|
}
|
||||||
|
|
||||||
|
class MaterialAssetLoader : IAssetLoader //, IReloadingAssetLoader
|
||||||
|
{
|
||||||
|
private static readonly List<StringView> _fileExtensions = new .(){".mat"} ~ delete _;
|
||||||
|
|
||||||
|
public static List<StringView> FileExtensions => _fileExtensions;
|
||||||
|
|
||||||
|
public AssetLoaderConfig GetDefaultConfig()
|
||||||
|
{
|
||||||
|
return new ModelAssetLoaderConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Asset LoadAsset(Stream file, AssetLoaderConfig config, StringView? subAsset, IContentManager contentManager)
|
||||||
|
{
|
||||||
|
StreamReader reader = scope .(file);
|
||||||
|
|
||||||
|
String text = scope .();
|
||||||
|
|
||||||
|
reader.ReadToEnd(text);
|
||||||
|
|
||||||
|
MaterialFile materialFile = scope .();
|
||||||
|
|
||||||
|
var result = Bon.Deserialize<MaterialFile>(ref materialFile, text);
|
||||||
|
|
||||||
|
if (result case .Err)
|
||||||
|
{
|
||||||
|
Log.EngineLogger.Error("Failed to load material.");
|
||||||
|
return null;
|
||||||
|
// TODO: return error material
|
||||||
|
}
|
||||||
|
|
||||||
|
Effect fx = new Effect(materialFile.Effect);
|
||||||
|
|
||||||
|
Material material = new Material(fx);
|
||||||
|
|
||||||
|
for (let (slotName, textureIdentifier) in materialFile.Textures)
|
||||||
|
{
|
||||||
|
Texture texture = contentManager.LoadAsset(textureIdentifier) as Texture;
|
||||||
|
|
||||||
|
if (texture == null)
|
||||||
|
{
|
||||||
|
Log.EngineLogger.Error("Failed to load texture.");
|
||||||
|
// TODO: LoadAsset should return an error texture.
|
||||||
|
}
|
||||||
|
|
||||||
|
material.SetTexture(slotName, texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
fx.ReleaseRef();
|
||||||
|
|
||||||
|
/*for (let (slotName, textureIdentifier) in materialFile.Variables)
|
||||||
|
{
|
||||||
|
if (texture == null)
|
||||||
|
{
|
||||||
|
Log.EngineLogger.Error("Failed to load texture.");
|
||||||
|
// TODO: LoadAsset should return an error texture.
|
||||||
|
}
|
||||||
|
|
||||||
|
material.SetVariable(slotName, );
|
||||||
|
}*/
|
||||||
|
|
||||||
|
return material; //ModelLoader.LoadMesh(file, subAsset.Value, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
using Bon;
|
||||||
|
using GlitchyEngine.Content;
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.IO;
|
||||||
|
using GlitchyEngine;
|
||||||
|
|
||||||
|
namespace GlitchyEditor.Assets;
|
||||||
|
|
||||||
|
class ModelAssetPropertiesEditor : AssetPropertiesEditor
|
||||||
|
{
|
||||||
|
public this(AssetFile asset) : base(asset)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void ShowEditor()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AssetPropertiesEditor Factory(AssetFile assetFile)
|
||||||
|
{
|
||||||
|
return new ModelAssetPropertiesEditor(assetFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[BonTarget, BonPolyRegister]
|
||||||
|
class ModelAssetLoaderConfig : AssetLoaderConfig
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class ModelAssetLoader : IAssetLoader //, IReloadingAssetLoader
|
||||||
|
{
|
||||||
|
private static readonly List<StringView> _fileExtensions = new .(){".gltf", ".glb"} ~ delete _;
|
||||||
|
|
||||||
|
public static List<StringView> FileExtensions => _fileExtensions;
|
||||||
|
|
||||||
|
public AssetLoaderConfig GetDefaultConfig()
|
||||||
|
{
|
||||||
|
return new ModelAssetLoaderConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Asset LoadAsset(Stream file, AssetLoaderConfig config, StringView? subAsset, IContentManager contentManager)
|
||||||
|
{
|
||||||
|
Log.EngineLogger.Assert(subAsset != null);
|
||||||
|
|
||||||
|
return ModelLoader.LoadMesh(file, subAsset.Value, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,21 +11,6 @@ using ImGui;
|
|||||||
|
|
||||||
namespace GlitchyEditor.Assets;
|
namespace GlitchyEditor.Assets;
|
||||||
|
|
||||||
abstract class AssetPropertiesEditor
|
|
||||||
{
|
|
||||||
private AssetFile _asset;
|
|
||||||
|
|
||||||
public AssetFile Asset => _asset;
|
|
||||||
|
|
||||||
public this(AssetFile asset)
|
|
||||||
{
|
|
||||||
_asset = asset;
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract void ShowEditor();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class TextureAssetPropertiesEditor : AssetPropertiesEditor
|
class TextureAssetPropertiesEditor : AssetPropertiesEditor
|
||||||
{
|
{
|
||||||
EditorTextureAssetLoaderConfig _textureConfig;
|
EditorTextureAssetLoaderConfig _textureConfig;
|
||||||
@@ -179,11 +164,6 @@ class EditorTextureAssetLoaderConfig : AssetLoaderConfig
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IReloadingAssetLoader
|
|
||||||
{
|
|
||||||
public void ReloadAsset(AssetFile assetFile, Stream data);
|
|
||||||
}
|
|
||||||
|
|
||||||
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"
|
||||||
@@ -195,7 +175,7 @@ class EditorTextureAssetLoader : IAssetLoader, IReloadingAssetLoader
|
|||||||
return new EditorTextureAssetLoaderConfig();
|
return new EditorTextureAssetLoaderConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
public IRefCounted LoadAsset(Stream data, AssetLoaderConfig config)
|
public Asset LoadAsset(Stream data, AssetLoaderConfig config, StringView? subAsset, IContentManager contentManager)
|
||||||
{
|
{
|
||||||
var config;
|
var config;
|
||||||
|
|
||||||
|
|||||||
@@ -287,9 +287,30 @@ namespace GlitchyEditor.EditWindows
|
|||||||
{
|
{
|
||||||
// TODO: Editing material options obviously shouldn't be part of the meshrenderer-ui
|
// TODO: Editing material options obviously shouldn't be part of the meshrenderer-ui
|
||||||
|
|
||||||
|
ImGui.Button("Drag Material here!");
|
||||||
|
if (ImGui.BeginDragDropTarget())
|
||||||
|
{
|
||||||
|
ImGui.Payload* payload = ImGui.AcceptDragDropPayload("CONTENT_BROWSER_ITEM");
|
||||||
|
|
||||||
|
if (payload != null)
|
||||||
|
{
|
||||||
|
StringView fullpath = .((char8*)payload.Data, (int)payload.DataSize);
|
||||||
|
|
||||||
|
using (Material material = Content.LoadAsset<Material>(fullpath))
|
||||||
|
{
|
||||||
|
meshRendererComponent.Material = material;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.EndDragDropTarget();
|
||||||
|
}
|
||||||
|
|
||||||
Material material = meshRendererComponent.Material;
|
Material material = meshRendererComponent.Material;
|
||||||
|
|
||||||
Effect effect = material.Effect;
|
Effect effect = material?.Effect;
|
||||||
|
|
||||||
|
if (effect == null)
|
||||||
|
return;
|
||||||
|
|
||||||
bool TryGetValue(Dictionary<String, Variant> parameters, String name, out Variant value)
|
bool TryGetValue(Dictionary<String, Variant> parameters, String name, out Variant value)
|
||||||
{
|
{
|
||||||
@@ -568,7 +589,7 @@ namespace GlitchyEditor.EditWindows
|
|||||||
{
|
{
|
||||||
StringView fullpath = .((char8*)payload.Data, (int)payload.DataSize);
|
StringView fullpath = .((char8*)payload.Data, (int)payload.DataSize);
|
||||||
|
|
||||||
int idx = fullpath.IndexOf('#');
|
/*int idx = fullpath.IndexOf('#');
|
||||||
|
|
||||||
if (idx == -1)
|
if (idx == -1)
|
||||||
{
|
{
|
||||||
@@ -577,13 +598,18 @@ namespace GlitchyEditor.EditWindows
|
|||||||
}
|
}
|
||||||
|
|
||||||
StringView filePath = fullpath.Substring(0, idx);
|
StringView filePath = fullpath.Substring(0, idx);
|
||||||
StringView meshName = fullpath.Substring(idx + 1);
|
StringView meshName = fullpath.Substring(idx + 1);*/
|
||||||
|
|
||||||
|
using (GeometryBinding geometry = Content.LoadAsset<GeometryBinding>(fullpath))
|
||||||
|
{
|
||||||
|
meshComponent.Mesh = geometry;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: support multiple primitives (treat every primitive as a single mesh?)
|
// TODO: support multiple primitives (treat every primitive as a single mesh?)
|
||||||
using (GeometryBinding binding = ModelLoader.LoadMesh(filePath, meshName, 0))
|
/*using (GeometryBinding binding = ModelLoader.LoadMesh(filePath, meshName, 0))
|
||||||
{
|
{
|
||||||
meshComponent.Mesh = binding;
|
meshComponent.Mesh = binding;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
//ModelLoader.LoadModel(scope .(path), )
|
//ModelLoader.LoadModel(scope .(path), )
|
||||||
|
|
||||||
@@ -648,6 +674,8 @@ namespace GlitchyEditor.EditWindows
|
|||||||
ShowComponentButton<Rigidbody2DComponent>("Rigidbody 2D");
|
ShowComponentButton<Rigidbody2DComponent>("Rigidbody 2D");
|
||||||
ShowComponentButton<BoxCollider2DComponent>("Box collider 2D");
|
ShowComponentButton<BoxCollider2DComponent>("Box collider 2D");
|
||||||
ShowComponentButton<CircleCollider2DComponent>("Circle collider 2D");
|
ShowComponentButton<CircleCollider2DComponent>("Circle collider 2D");
|
||||||
|
ShowComponentButton<MeshComponent>("Mesh");
|
||||||
|
ShowComponentButton<MeshRendererComponent>("Mesh Renderer");
|
||||||
|
|
||||||
ImGui.EndCombo();
|
ImGui.EndCombo();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,7 +73,8 @@ namespace GlitchyEditor.EditWindows
|
|||||||
{
|
{
|
||||||
if (ImGui.MenuItem("Open in file browser..."))
|
if (ImGui.MenuItem("Open in file browser..."))
|
||||||
{
|
{
|
||||||
Path.OpenFolder(_currentDirectory);
|
if (Path.OpenFolder(_currentDirectory) case .Err)
|
||||||
|
Log.EngineLogger.Error("Failed to open directory in file browser.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -294,9 +295,22 @@ namespace GlitchyEditor.EditWindows
|
|||||||
/// Shows the context menu for the given file/folder.
|
/// Shows the context menu for the given file/folder.
|
||||||
private void ShowItemContextMenu(TreeNode<AssetNode> fileOrFolder)
|
private void ShowItemContextMenu(TreeNode<AssetNode> fileOrFolder)
|
||||||
{
|
{
|
||||||
|
bool isFile = !fileOrFolder->IsDirectory;
|
||||||
|
|
||||||
if (ImGui.MenuItem("Show in file browser..."))
|
if (ImGui.MenuItem("Show in file browser..."))
|
||||||
{
|
{
|
||||||
Path.OpenFolderAndSelectItem(fileOrFolder->Path);
|
if (Path.OpenFolderAndSelectItem(fileOrFolder->Path) case .Err)
|
||||||
|
{
|
||||||
|
Log.EngineLogger.Error("Failed to show path in file browser.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isFile && ImGui.MenuItem("Open file with..."))
|
||||||
|
{
|
||||||
|
if (Path.OpenWithDialog(fileOrFolder->Path) case .Err)
|
||||||
|
{
|
||||||
|
Log.EngineLogger.Error("Failed to show \"Open with...\" dialog.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ImGui.MenuItem("Delete"))
|
if (ImGui.MenuItem("Delete"))
|
||||||
@@ -311,6 +325,11 @@ namespace GlitchyEditor.EditWindows
|
|||||||
{
|
{
|
||||||
_currentDirectory.Set(entry->Path);
|
_currentDirectory.Set(entry->Path);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (Path.OpenFolder(entry->Path) case .Err)
|
||||||
|
Log.EngineLogger.Error("Failed to open directory in file browser.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -82,7 +82,7 @@ public class AssetNode
|
|||||||
|
|
||||||
public AssetFile AssetFile ~ delete _;
|
public AssetFile AssetFile ~ delete _;
|
||||||
|
|
||||||
public List<Asset> SubAssets ~ {
|
public List<SubAsset> SubAssets ~ {
|
||||||
SubAssets?.ClearAndDeleteItems();
|
SubAssets?.ClearAndDeleteItems();
|
||||||
delete SubAssets;
|
delete SubAssets;
|
||||||
}
|
}
|
||||||
@@ -90,7 +90,7 @@ public class AssetNode
|
|||||||
public Texture2D PreviewImage ~ _?.ReleaseRef();
|
public Texture2D PreviewImage ~ _?.ReleaseRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Asset
|
public class SubAsset
|
||||||
{
|
{
|
||||||
public AssetNode Asset;
|
public AssetNode Asset;
|
||||||
public String Name ~ delete _;
|
public String Name ~ delete _;
|
||||||
@@ -404,16 +404,13 @@ class AssetHierarchy
|
|||||||
|
|
||||||
class EditorContentManager : IContentManager
|
class EditorContentManager : IContentManager
|
||||||
{
|
{
|
||||||
// TODO: Get from workspace
|
|
||||||
//const String ContentDirectory = "./content";
|
|
||||||
|
|
||||||
private append String _contentDirectory = .();
|
private append String _contentDirectory = .();
|
||||||
|
|
||||||
public StringView ContentDirectory => _contentDirectory;
|
public StringView ContentDirectory => _contentDirectory;
|
||||||
|
|
||||||
private append List<String> _identifiers = .() ~ _.ClearAndDeleteItems();
|
//private append List<String> _identifiers = .() ~ _.ClearAndDeleteItems();
|
||||||
|
|
||||||
private append Dictionary<StringView, IRefCounted> _loadedAssets = .(); // Check if all resources are unloaded
|
private append Dictionary<StringView, Asset> _loadedAssets = .(); // Check if all resources are unloaded
|
||||||
|
|
||||||
private append AssetHierarchy _assetHierarchy = .(this);
|
private append AssetHierarchy _assetHierarchy = .(this);
|
||||||
|
|
||||||
@@ -424,8 +421,15 @@ class EditorContentManager : IContentManager
|
|||||||
_assetHierarchy.OnFileContentChanged.Add(new => OnFileContentChanged);
|
_assetHierarchy.OnFileContentChanged.Add(new => OnFileContentChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ~this()
|
||||||
|
{
|
||||||
|
UnmanageAllAssets();
|
||||||
|
}
|
||||||
|
|
||||||
private void OnFileContentChanged(AssetNode assetNode)
|
private void OnFileContentChanged(AssetNode assetNode)
|
||||||
{
|
{
|
||||||
|
// TODO: Subassets break reloading because we can't find them when we only receive the file that changed...
|
||||||
|
|
||||||
// Asset isn't loaded so we don't need to reload it.
|
// Asset isn't loaded so we don't need to reload it.
|
||||||
if (assetNode.AssetFile.LoadedAsset == null)
|
if (assetNode.AssetFile.LoadedAsset == null)
|
||||||
return;
|
return;
|
||||||
@@ -565,15 +569,21 @@ class EditorContentManager : IContentManager
|
|||||||
return _loadedAssets.ContainsKey(identifier);
|
return _loadedAssets.ContainsKey(identifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IRefCounted LoadAsset(StringView identifier)
|
public Asset LoadAsset(StringView identifier)
|
||||||
{
|
{
|
||||||
if (_loadedAssets.TryGetValue(identifier, let asset))
|
if (_loadedAssets.TryGetValue(identifier, let asset))
|
||||||
{
|
{
|
||||||
return asset..AddRef();
|
return asset..AddRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
String filePath = scope String(identifier.Length + _contentDirectory.Length + 2);
|
// Find subasset name
|
||||||
Path.Combine(filePath, _contentDirectory, identifier);
|
int poundIndex = identifier.IndexOf('#');
|
||||||
|
|
||||||
|
StringView resourceName = poundIndex == -1 ? identifier : identifier.Substring(0, poundIndex);
|
||||||
|
StringView? subassetName = identifier.Substring(poundIndex + 1);
|
||||||
|
|
||||||
|
String filePath = scope String(resourceName.Length + _contentDirectory.Length + 2);
|
||||||
|
Path.Combine(filePath, _contentDirectory, resourceName);
|
||||||
|
|
||||||
Path.Fixup(filePath);
|
Path.Fixup(filePath);
|
||||||
|
|
||||||
@@ -606,14 +616,19 @@ class EditorContentManager : IContentManager
|
|||||||
|
|
||||||
Stream stream = GetStream(filePath);
|
Stream stream = GetStream(filePath);
|
||||||
|
|
||||||
IRefCounted loadedAsset = assetLoader.LoadAsset(stream, file.AssetConfig.Config);
|
Asset loadedAsset = assetLoader.LoadAsset(stream, file.AssetConfig.Config, subassetName, this);
|
||||||
|
|
||||||
String identifierString = new .(identifier);
|
|
||||||
_identifiers.Add(identifierString);
|
|
||||||
_loadedAssets[identifierString] = loadedAsset;
|
|
||||||
|
|
||||||
delete stream;
|
delete stream;
|
||||||
|
|
||||||
|
//String identifierString = new .(identifier);
|
||||||
|
//_identifiers.Add(identifierString);
|
||||||
|
|
||||||
|
//_loadedAssets[identifierString] = loadedAsset;
|
||||||
|
|
||||||
|
|
||||||
|
loadedAsset.Identifier = identifier;
|
||||||
|
ManageAsset(loadedAsset);
|
||||||
|
|
||||||
file.[Friend]_loadedAsset = loadedAsset;
|
file.[Friend]_loadedAsset = loadedAsset;
|
||||||
|
|
||||||
return loadedAsset;
|
return loadedAsset;
|
||||||
@@ -627,4 +642,38 @@ class EditorContentManager : IContentManager
|
|||||||
|
|
||||||
return fs;
|
return fs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ManageAsset(Asset asset)
|
||||||
|
{
|
||||||
|
_loadedAssets.Add(asset.Identifier, asset);
|
||||||
|
asset.[Friend]_contentManager = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UnmanageAsset(Asset asset)
|
||||||
|
{
|
||||||
|
_loadedAssets.Remove(asset.Identifier);
|
||||||
|
asset.[Friend]_contentManager = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This will unregister all assets from this content manager.
|
||||||
|
/// Note: This will not release any assets.
|
||||||
|
private void UnmanageAllAssets()
|
||||||
|
{
|
||||||
|
for (let (_, asset) in _loadedAssets)
|
||||||
|
{
|
||||||
|
UnmanageAsset(asset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateAssetIdentifier(Asset asset, StringView oldIdentifier, StringView newIdentifier)
|
||||||
|
{
|
||||||
|
if (oldIdentifier == newIdentifier)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Log.EngineLogger.Assert(_loadedAssets.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.
|
||||||
|
UnmanageAsset(asset);
|
||||||
|
ManageAsset(asset);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -88,12 +88,20 @@ namespace GlitchyEditor
|
|||||||
private void InitContentManager()
|
private void InitContentManager()
|
||||||
{
|
{
|
||||||
_contentManager = new EditorContentManager();
|
_contentManager = new EditorContentManager();
|
||||||
_contentManager.SetContentDirectory("./content");
|
|
||||||
|
|
||||||
_contentManager.RegisterAssetLoader<EditorTextureAssetLoader>();
|
_contentManager.RegisterAssetLoader<EditorTextureAssetLoader>();
|
||||||
_contentManager.SetAsDefaultAssetLoader<EditorTextureAssetLoader>(".png", ".dds");
|
_contentManager.SetAsDefaultAssetLoader<EditorTextureAssetLoader>(".png", ".dds");
|
||||||
_contentManager.SetAssetPropertiesEditor<EditorTextureAssetLoader>(=> TextureAssetPropertiesEditor.Factory);
|
_contentManager.SetAssetPropertiesEditor<EditorTextureAssetLoader>(=> TextureAssetPropertiesEditor.Factory);
|
||||||
|
|
||||||
|
_contentManager.RegisterAssetLoader<ModelAssetLoader>();
|
||||||
|
_contentManager.SetAsDefaultAssetLoader<ModelAssetLoader>(".glb", ".gltf");
|
||||||
|
_contentManager.SetAssetPropertiesEditor<ModelAssetLoader>(=> ModelAssetPropertiesEditor.Factory);
|
||||||
|
|
||||||
|
_contentManager.RegisterAssetLoader<MaterialAssetLoader>();
|
||||||
|
_contentManager.SetAsDefaultAssetLoader<MaterialAssetLoader>(".mat");
|
||||||
|
_contentManager.SetAssetPropertiesEditor<MaterialAssetLoader>(=> MaterialAssetPropertiesEditor.Factory);
|
||||||
|
|
||||||
|
_contentManager.SetContentDirectory("./content");
|
||||||
|
|
||||||
// Todo: Sketchy...
|
// Todo: Sketchy...
|
||||||
Application.Get().[Friend]_contentManager = _contentManager;
|
Application.Get().[Friend]_contentManager = _contentManager;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
using GlitchyEngine.Core;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace GlitchyEngine.Content;
|
||||||
|
|
||||||
|
class Asset : RefCounter
|
||||||
|
{
|
||||||
|
private append String _identifier;
|
||||||
|
|
||||||
|
internal IContentManager _contentManager;
|
||||||
|
|
||||||
|
/// Gets the identifier of this asset.
|
||||||
|
/// @remarks The identifier is the name with which the asset was registered in the content manager.
|
||||||
|
/// This identifier can be used to request the Asset from the content manager.
|
||||||
|
public StringView Identifier
|
||||||
|
{
|
||||||
|
get => _identifier;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_contentManager?.UpdateAssetIdentifier(this, _identifier, value);
|
||||||
|
|
||||||
|
_identifier.Set(value);
|
||||||
|
// TODO: do we need to tell the content manager, that the name changed?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: do we need unmanaged assets? Probably not...
|
||||||
|
/// Gets the content manager that manages this asset; or null if this asset isn't managed.
|
||||||
|
public IContentManager ContentManager => _contentManager;
|
||||||
|
|
||||||
|
protected ~this()
|
||||||
|
{
|
||||||
|
// TODO: crash when _contentManager is deleted first...
|
||||||
|
// TODO: unregister from content manager
|
||||||
|
_contentManager?.UnmanageAsset(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -54,8 +54,9 @@ namespace GlitchyEngine.Content
|
|||||||
/// Loads the asset from the given data stream with the specified config.
|
/// Loads the asset from the given data stream with the specified config.
|
||||||
/// @param file The stream containing the asset.
|
/// @param file The stream containing the asset.
|
||||||
/// @param config The configuration which specifies the settings used to load the asset.
|
/// @param config The configuration which specifies the settings used to load the asset.
|
||||||
|
/// @param contentManager The content manager used to load the asset.
|
||||||
/// @returns The loaded asset.
|
/// @returns The loaded asset.
|
||||||
IRefCounted LoadAsset(Stream file, AssetLoaderConfig config);
|
Asset LoadAsset(Stream file, AssetLoaderConfig config, StringView? subAsset, IContentManager contentManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
@@ -79,7 +80,17 @@ namespace GlitchyEngine.Content
|
|||||||
interface IContentManager
|
interface IContentManager
|
||||||
{
|
{
|
||||||
/// Loads the given asset.
|
/// Loads the given asset.
|
||||||
IRefCounted LoadAsset(StringView assetIdentifier);
|
Asset LoadAsset(StringView assetIdentifier);
|
||||||
|
|
||||||
|
/// The content manager will manage the asset (e.g. provide it when LoadAsset is called with the assets identifier)
|
||||||
|
void ManageAsset(Asset asset);
|
||||||
|
|
||||||
|
/// The content manager will no longer manage the asset.
|
||||||
|
void UnmanageAsset(Asset asset);
|
||||||
|
|
||||||
|
// TODO: Maybe calling UnmanageAsset -> ManageAsset is enough....
|
||||||
|
/// Provides a method for the asset to tell its content manager that the identifer changed.
|
||||||
|
void UpdateAssetIdentifier(Asset asset, StringView oldIdentifier, StringView newIdentifier);
|
||||||
|
|
||||||
/// Returns a data stream for the given asset.
|
/// Returns a data stream for the given asset.
|
||||||
Stream GetStream(StringView assetIdentifier);
|
Stream GetStream(StringView assetIdentifier);
|
||||||
@@ -93,7 +104,22 @@ namespace GlitchyEngine.Content
|
|||||||
|
|
||||||
class RuntimeContentManager : IContentManager
|
class RuntimeContentManager : IContentManager
|
||||||
{
|
{
|
||||||
public IRefCounted LoadAsset(StringView identifier)
|
public Asset LoadAsset(StringView assetIdentifier)
|
||||||
|
{
|
||||||
|
Runtime.NotImplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ManageAsset(Asset asset)
|
||||||
|
{
|
||||||
|
Runtime.NotImplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UnmanageAsset(Asset asset)
|
||||||
|
{
|
||||||
|
Runtime.NotImplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateAssetIdentifier(Asset asset, StringView oldIdentifier, StringView newIdentifier)
|
||||||
{
|
{
|
||||||
Runtime.NotImplemented();
|
Runtime.NotImplemented();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using GlitchyEngine.Math;
|
|||||||
using GlitchyEngine.Renderer;
|
using GlitchyEngine.Renderer;
|
||||||
using GlitchyEngine.Renderer.Animation;
|
using GlitchyEngine.Renderer.Animation;
|
||||||
using GlitchyEngine.World;
|
using GlitchyEngine.World;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
namespace GlitchyEngine.Content
|
namespace GlitchyEngine.Content
|
||||||
{
|
{
|
||||||
@@ -66,6 +67,168 @@ namespace GlitchyEngine.Content
|
|||||||
return geoBinding;
|
return geoBinding;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static GeometryBinding LoadMesh(Stream data, StringView meshName, int primitiveIndex)
|
||||||
|
{
|
||||||
|
// TODO: add a context to remember which buffers were loaded before so that we don't load the same data multiple times.
|
||||||
|
|
||||||
|
uint8[] rawData = new:ScopedAlloc! uint8[data.Length];
|
||||||
|
|
||||||
|
var dataReadResult = data.TryRead(rawData);
|
||||||
|
|
||||||
|
if (dataReadResult case .Err(let err))
|
||||||
|
{
|
||||||
|
Log.EngineLogger.Error($"Failed to read data from stream. Error: {err}");
|
||||||
|
}
|
||||||
|
|
||||||
|
CGLTF.Options options = .();
|
||||||
|
CGLTF.Data* modelData;
|
||||||
|
CGLTF.Result result = CGLTF.Parse(options, (Span<uint8>)rawData, out modelData);
|
||||||
|
|
||||||
|
if (!(result case .Success))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// TODO: one buffer can be used by multiple primitives, the content manager could manage the buffers
|
||||||
|
|
||||||
|
// TODO: load with content manager
|
||||||
|
|
||||||
|
result = CGLTF.LoadBuffers(options, modelData, (char8*)null);
|
||||||
|
//result = LoadBuffersWithContentManager(options, modelData, meshName, Application.Get().ContentManager);
|
||||||
|
|
||||||
|
GeometryBinding geoBinding = null;
|
||||||
|
|
||||||
|
for (var mesh in modelData.Meshes)
|
||||||
|
{
|
||||||
|
var name = StringView(mesh.Name);
|
||||||
|
|
||||||
|
//if (name == meshName)
|
||||||
|
{
|
||||||
|
Log.EngineLogger.AssertDebug(primitiveIndex >= 0 && primitiveIndex < mesh.Primitives.Length);
|
||||||
|
|
||||||
|
geoBinding = PrimitiveToGeoBinding(mesh.Primitives[primitiveIndex]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CGLTF.Free(modelData);
|
||||||
|
|
||||||
|
return geoBinding;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static CGLTF.Result LoadBuffersWithContentManager(CGLTF.Options options, CGLTF.Data* data, StringView fileName, IContentManager contentManager)
|
||||||
|
{
|
||||||
|
if (data.Buffers.Length > 0 && data.Buffers[0].Data == null && data.Buffers[0].Uri == null && !data.Bin.IsEmpty)
|
||||||
|
{
|
||||||
|
if ((uint)data.Bin.Length < data.Buffers[0].Size)
|
||||||
|
return .DataTooShort;
|
||||||
|
|
||||||
|
data.Buffers[0].Data = data.Bin.Ptr;
|
||||||
|
data.Buffers[0].DataFreeMethod = .None;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ref CGLTF.Buffer buffer in ref data.Buffers)
|
||||||
|
{
|
||||||
|
if (buffer.Data != null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (buffer.Uri == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
StringView uri = StringView(buffer.Uri);
|
||||||
|
|
||||||
|
if (uri.StartsWith("data:"))
|
||||||
|
{
|
||||||
|
int commaIndex = uri.IndexOf(',');
|
||||||
|
|
||||||
|
//char* comma = strchr(uri, ',');
|
||||||
|
|
||||||
|
if (commaIndex == -1 || commaIndex >= 7 || uri.StartsWith(";base64"))
|
||||||
|
return .UnknownFormat;
|
||||||
|
|
||||||
|
StringView dataView = uri.Substring(commaIndex + 1);
|
||||||
|
|
||||||
|
#unwarn
|
||||||
|
CGLTF.Result loadBufferResult = CGLTF.LoadBuffersBase64(&options, buffer.Size, dataView.Ptr, &buffer.Data);
|
||||||
|
buffer.DataFreeMethod = .MemoryFree;
|
||||||
|
|
||||||
|
return loadBufferResult;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Runtime.NotImplemented();
|
||||||
|
|
||||||
|
// TODO: Request Buffer from Content Manager
|
||||||
|
|
||||||
|
//int index = uri.IndexOf("://");
|
||||||
|
|
||||||
|
//if (index == -1)
|
||||||
|
// return .UnknownFormat;
|
||||||
|
|
||||||
|
// TODO: load buffer file...
|
||||||
|
//CGLTF.Result res = //cgltf_load_buffer_file(options, data->buffers[i].size, uri, gltf_path, &data->buffers[i].data);
|
||||||
|
//buffer.DataFreeMethod = cgltf_data_free_method_file_release;
|
||||||
|
|
||||||
|
/*if (res != cgltf_result_success)
|
||||||
|
{
|
||||||
|
return res;
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
for (cgltf_size i = 0; i < data->buffers_count; ++i)
|
||||||
|
{
|
||||||
|
if (data->buffers[i].data)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* uri = data->buffers[i].uri;
|
||||||
|
|
||||||
|
if (uri == NULL)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strncmp(uri, "data:", 5) == 0)
|
||||||
|
{
|
||||||
|
const char* comma = strchr(uri, ',');
|
||||||
|
|
||||||
|
if (comma && comma - uri >= 7 && strncmp(comma - 7, ";base64", 7) == 0)
|
||||||
|
{
|
||||||
|
cgltf_result res = cgltf_load_buffer_base64(options, data->buffers[i].size, comma + 1, &data->buffers[i].data);
|
||||||
|
data->buffers[i].data_free_method = cgltf_data_free_method_memory_free;
|
||||||
|
|
||||||
|
if (res != cgltf_result_success)
|
||||||
|
{
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return cgltf_result_unknown_format;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (strstr(uri, "://") == NULL && gltf_path)
|
||||||
|
{
|
||||||
|
cgltf_result res = cgltf_load_buffer_file(options, data->buffers[i].size, uri, gltf_path, &data->buffers[i].data);
|
||||||
|
data->buffers[i].data_free_method = cgltf_data_free_method_file_release;
|
||||||
|
|
||||||
|
if (res != cgltf_result_success)
|
||||||
|
{
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return cgltf_result_unknown_format;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
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())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -7,11 +7,10 @@ namespace GlitchyEngine.Core
|
|||||||
* Implements the IDisposable interface so that it can be used with a using-Block so that the counter
|
* Implements the IDisposable interface so that it can be used with a using-Block so that the counter
|
||||||
* will be decremented automatically after leaving the block.
|
* will be decremented automatically after leaving the block.
|
||||||
*/
|
*/
|
||||||
public class RefCounter : System.RefCounted, IDisposable
|
public class RefCounter : RefCounted, IDisposable
|
||||||
{
|
{
|
||||||
protected ~this()
|
protected ~this()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
|
|||||||
@@ -1,41 +1,28 @@
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
|
||||||
namespace System.IO;
|
namespace System.IO;
|
||||||
|
|
||||||
extension Path
|
extension Path
|
||||||
{
|
{
|
||||||
/// Opens the file browser and selects the specified file.
|
public static mixin GetScopedFullPath(String path)
|
||||||
/// @param path The path of the file to select.
|
|
||||||
public static void OpenFolderAndSelectItem(String path)
|
|
||||||
{
|
{
|
||||||
String fullPath = scope String(256);
|
String fullPath = scope String(Path.MaxPath);
|
||||||
Path.GetFullPath(path, fullPath);
|
Path.GetFullPath(path, fullPath);
|
||||||
|
|
||||||
#if BF_PLATFORM_WINDOWS
|
fullPath
|
||||||
ProcessStartInfo processInfo = scope .();
|
|
||||||
processInfo.SetFileNameAndArguments(scope $"explorer /select,\"{fullPath}\"");
|
|
||||||
|
|
||||||
scope SpawnedProcess().Start(processInfo);
|
|
||||||
#else
|
|
||||||
Runtime.NotImplemented();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Opens the file browser and selects the specified file.
|
||||||
|
/// @param path The path of the file to select.
|
||||||
|
public static extern Result<void> OpenFolderAndSelectItem(String path);
|
||||||
|
|
||||||
/// Opens the file browser in the given directory.
|
/// Opens the file browser in the given directory.
|
||||||
/// @param directory The directory to show in the file browser.
|
/// @param directory The directory to show in the file browser.
|
||||||
public static void OpenFolder(String directory)
|
public static extern Result<void> OpenFolder(String directory);
|
||||||
{
|
|
||||||
String fullPath = scope String(256);
|
|
||||||
Path.GetFullPath(directory, fullPath);
|
|
||||||
|
|
||||||
#if BF_PLATFORM_WINDOWS
|
/// Shows a dialog in which the user can select which program to open the given file with.
|
||||||
ProcessStartInfo processInfo = scope .();
|
/// @param The Path of the file to open.
|
||||||
processInfo.SetFileNameAndArguments(scope $"explorer \"{fullPath}\"");
|
public static extern Result<void> OpenWithDialog(String filePath);
|
||||||
|
|
||||||
scope SpawnedProcess().Start(processInfo);
|
|
||||||
#else
|
|
||||||
Runtime.NotImplemented();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Fixup(String path)
|
public static void Fixup(String path)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,90 @@
|
|||||||
|
#if BF_PLATFORM_WINDOWS
|
||||||
|
|
||||||
|
using DirectX.Common;
|
||||||
|
using DirectX.Windows;
|
||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using DirectX.Windows.Winuser;
|
||||||
|
|
||||||
|
namespace DirectX.Windows.Winuser
|
||||||
|
{
|
||||||
|
enum OpenAsInfoFlags : uint32
|
||||||
|
{
|
||||||
|
/// Enable the "always use this program" checkbox. If not passed, it will be disabled.
|
||||||
|
AllowRegistration = 0x1,
|
||||||
|
/// Do the registration after the user hits the OK button.
|
||||||
|
RegisterExtension = 0x2,
|
||||||
|
/// Execute file after registering.
|
||||||
|
Exec = 0x4,
|
||||||
|
///Force the Always use this program checkbox to be checked.
|
||||||
|
/// Typically, you won't use the OAIF_ALLOW_REGISTRATION flag when you pass this value.
|
||||||
|
ForceRegistration = 0x8,
|
||||||
|
/// Introduced in Windows Vista. Hide the Always use this program checkbox. If this flag is specified, the OAIF_ALLOW_REGISTRATION and OAIF_FORCE_REGISTRATION flags will be ignored.
|
||||||
|
HideRegistration = 0x20,
|
||||||
|
/// Introduced in Windows Vista. The value for the extension that is passed is actually a protocol, so the Open With dialog box should show applications that are registered as capable of handling that protocol.
|
||||||
|
UrlProtocol = 0x40,
|
||||||
|
/// Introduced in Windows 8. The location pointed to by the pcszFile parameter is given as a URI.
|
||||||
|
FileIsUri = 0x80
|
||||||
|
}
|
||||||
|
|
||||||
|
struct OpenAsInfo
|
||||||
|
{
|
||||||
|
public LPCWSTR File;
|
||||||
|
public LPCWSTR Class;
|
||||||
|
public OpenAsInfoFlags Flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
{
|
||||||
|
[Import("user32.lib"), CallingConvention(.Stdcall), CLink]
|
||||||
|
public extern static HResult SHOpenWithDialog(HWND hwndParent, OpenAsInfo* poainfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace System.IO;
|
||||||
|
|
||||||
|
extension Path
|
||||||
|
{
|
||||||
|
/// Opens the file browser and selects the specified file.
|
||||||
|
/// @param path The path of the file to select.
|
||||||
|
public static override Result<void> OpenFolderAndSelectItem(String path)
|
||||||
|
{
|
||||||
|
String fullPath = GetScopedFullPath!(path);
|
||||||
|
|
||||||
|
ProcessStartInfo processInfo = scope .();
|
||||||
|
processInfo.SetFileNameAndArguments(scope $"explorer /select,\"{fullPath}\"");
|
||||||
|
|
||||||
|
return scope SpawnedProcess().Start(processInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Opens the file browser in the given directory.
|
||||||
|
/// @param directory The directory to show in the file browser.
|
||||||
|
public static override Result<void> OpenFolder(String directory)
|
||||||
|
{
|
||||||
|
String fullPath = GetScopedFullPath!(directory);
|
||||||
|
|
||||||
|
ProcessStartInfo processInfo = scope .();
|
||||||
|
processInfo.SetFileNameAndArguments(scope $"explorer \"{fullPath}\"");
|
||||||
|
|
||||||
|
return scope SpawnedProcess().Start(processInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static override Result<void> OpenWithDialog(String filePath)
|
||||||
|
{
|
||||||
|
String fullPath = GetScopedFullPath!(filePath);
|
||||||
|
|
||||||
|
OpenAsInfo info = .();
|
||||||
|
info.File = fullPath.ToScopedNativeWChar!();
|
||||||
|
info.Class = null;
|
||||||
|
info.Flags = .Exec;
|
||||||
|
|
||||||
|
HResult result = SHOpenWithDialog(0, &info);
|
||||||
|
|
||||||
|
if (result.Succeeded)
|
||||||
|
return .Ok;
|
||||||
|
else
|
||||||
|
return .Err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,10 +1,12 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
|
using GlitchyEngine.Content;
|
||||||
using GlitchyEngine.Core;
|
using GlitchyEngine.Core;
|
||||||
|
|
||||||
namespace GlitchyEngine.Renderer
|
namespace GlitchyEngine.Renderer
|
||||||
{
|
{
|
||||||
public class GeometryBinding : RefCounter
|
// Todo: Rename to Mesh?
|
||||||
|
public class GeometryBinding : Asset
|
||||||
{
|
{
|
||||||
internal List<VertexBufferBinding> _vertexBuffers = new .() ~ delete _;
|
internal List<VertexBufferBinding> _vertexBuffers = new .() ~ delete _;
|
||||||
internal IndexBuffer _indexBuffer ~ _?.ReleaseRef();
|
internal IndexBuffer _indexBuffer ~ _?.ReleaseRef();
|
||||||
|
|||||||
@@ -1,14 +1,15 @@
|
|||||||
using System;
|
using GlitchyEngine.Content;
|
||||||
using System.Collections;
|
|
||||||
using GlitchyEngine.Core;
|
using GlitchyEngine.Core;
|
||||||
using GlitchyEngine.Math;
|
using GlitchyEngine.Math;
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
|
||||||
using internal GlitchyEngine.Renderer;
|
using internal GlitchyEngine.Renderer;
|
||||||
|
|
||||||
namespace GlitchyEngine.Renderer
|
namespace GlitchyEngine.Renderer;
|
||||||
|
|
||||||
|
public class Material : Asset
|
||||||
{
|
{
|
||||||
public class Material : RefCounter
|
|
||||||
{
|
|
||||||
private Effect _effect ~ _?.ReleaseRef();
|
private Effect _effect ~ _?.ReleaseRef();
|
||||||
|
|
||||||
private uint8[] _rawVariables ~ delete _;
|
private uint8[] _rawVariables ~ delete _;
|
||||||
@@ -194,6 +195,19 @@ namespace GlitchyEngine.Renderer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Supporeted types
|
||||||
|
// Float, Float2, Float3, Float4
|
||||||
|
// Color, ColorRGB, ColorRGBA
|
||||||
|
// Int, Int2, Int3, Int4
|
||||||
|
// UInt
|
||||||
|
// Matrix3x3, Matrix4x3, Matrix
|
||||||
|
|
||||||
|
// TODO: Add missing variable types
|
||||||
|
// UInt2, UInt3, UInt4
|
||||||
|
// Bool, Bool2, Bool3, Bool4
|
||||||
|
// Half, Half2, Half3, Half4
|
||||||
|
// Byte, Byte2, Byte3, Byte4
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the raw data of the variable.
|
* Sets the raw data of the variable.
|
||||||
* @param rawData The pointer to the raw data. If rawData is null the raw data will be set to zero.
|
* @param rawData The pointer to the raw data. If rawData is null the raw data will be set to zero.
|
||||||
@@ -206,8 +220,6 @@ namespace GlitchyEngine.Renderer
|
|||||||
Internal.MemSet(&_rawVariables + offset, 0, byteCount);
|
Internal.MemSet(&_rawVariables + offset, 0, byteCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
// public void Set(String name, VALUE)...
|
|
||||||
|
|
||||||
public void GetVariable<T>(String name, out T value) where T : struct
|
public void GetVariable<T>(String name, out T value) where T : struct
|
||||||
{
|
{
|
||||||
Debug.Profiler.ProfileRendererFunction!();
|
Debug.Profiler.ProfileRendererFunction!();
|
||||||
@@ -224,14 +236,4 @@ namespace GlitchyEngine.Renderer
|
|||||||
Log.EngineLogger.Assert(false, scope $"The effect doesn't contain a variable named \"{name}\"");
|
Log.EngineLogger.Assert(false, scope $"The effect doesn't contain a variable named \"{name}\"");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Float, Float2, Float3, Float4
|
|
||||||
// Color, ColorRGB, ColorRGBA
|
|
||||||
// Matrix3x3, Matrix4x3, Matrix
|
|
||||||
// Int, Int2, Int3, Int4
|
|
||||||
// UInt, UInt2, UInt3, UInt4
|
|
||||||
// Bool, Bool2, Bool3, Bool4
|
|
||||||
// Half, Half2, Half3, Half4
|
|
||||||
// Byte, Byte2, Byte3, Byte4
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
using System;
|
using GlitchyEngine.Content;
|
||||||
using GlitchyEngine.Core;
|
using GlitchyEngine.Core;
|
||||||
using GlitchyEngine.Math;
|
using GlitchyEngine.Math;
|
||||||
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
|
||||||
namespace GlitchyEngine.Renderer
|
namespace GlitchyEngine.Renderer
|
||||||
{
|
{
|
||||||
public abstract class Texture : RefCounter
|
public abstract class Texture : Asset
|
||||||
{
|
{
|
||||||
protected SamplerState _samplerState ~ _?.ReleaseRef();
|
protected SamplerState _samplerState ~ _?.ReleaseRef();
|
||||||
|
|
||||||
|
|||||||
@@ -442,6 +442,9 @@ 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)
|
||||||
|
continue;
|
||||||
|
|
||||||
Renderer.Submit(mesh.Mesh, meshRenderer.Material, entity, transform.WorldTransform);
|
Renderer.Submit(mesh.Mesh, meshRenderer.Material, entity, transform.WorldTransform);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user