mirror of
https://github.com/aharabada/glitchy-engine-beef.git
synced 2026-09-05 13:01:52 +00:00
Basic Model drag'n'drop
This commit is contained in:
@@ -5,6 +5,7 @@ using GlitchyEngine.Math;
|
||||
using System.Collections;
|
||||
using GlitchyEngine.Renderer;
|
||||
using GlitchyEngine;
|
||||
using GlitchyEngine.Content;
|
||||
|
||||
namespace GlitchyEditor.EditWindows
|
||||
{
|
||||
@@ -62,6 +63,7 @@ namespace GlitchyEditor.EditWindows
|
||||
ShowComponentEditor<SpriterRendererComponent>("Sprite Renderer", entity, => ShowSpriteRendererComponentEditor, => ShowComponentContextMenu<SpriterRendererComponent>);
|
||||
ShowComponentEditor<MeshRendererComponent>("Mesh Renderer", entity, => ShowMeshRendererComponentEditor, => ShowComponentContextMenu<MeshRendererComponent>);
|
||||
ShowComponentEditor<LightComponent>("Light", entity, => ShowLightComponentEditor, => ShowComponentContextMenu<LightComponent>);
|
||||
ShowComponentEditor<MeshComponent>("Mesh", entity, => ShowMeshComponentEditor, => ShowComponentContextMenu<MeshComponent>);
|
||||
|
||||
ShowAddComponentButton(entity);
|
||||
}
|
||||
@@ -461,6 +463,47 @@ namespace GlitchyEditor.EditWindows
|
||||
light.Illuminance = illuminance;
|
||||
}
|
||||
|
||||
private static void ShowMeshComponentEditor(Entity entity, MeshComponent* meshComponent)
|
||||
{
|
||||
ImGui.Button("Drag Mesh here!");
|
||||
if (ImGui.BeginDragDropTarget())
|
||||
{
|
||||
ImGui.Payload* payload = ImGui.AcceptDragDropPayload("CONTENT_BROWSER_ITEM");
|
||||
|
||||
if (payload != null)
|
||||
{
|
||||
StringView fullpath = .((char8*)payload.Data, (int)payload.DataSize);
|
||||
|
||||
int idx = fullpath.IndexOf('#');
|
||||
|
||||
if (idx == -1)
|
||||
{
|
||||
// Doesn't make sense here, we NEED a sub asset
|
||||
Runtime.NotImplemented();
|
||||
}
|
||||
|
||||
StringView filePath = fullpath.Substring(0, idx);
|
||||
StringView meshName = fullpath.Substring(idx + 1);
|
||||
|
||||
// TODO: support multiple primitives (treat every primitive as a single mesh?)
|
||||
using (GeometryBinding binding = ModelLoader.LoadMesh(filePath, meshName, 0))
|
||||
{
|
||||
meshComponent.Mesh = binding;
|
||||
}
|
||||
|
||||
//ModelLoader.LoadModel(scope .(path), )
|
||||
|
||||
/*using (Texture2D newTexture = new Texture2D(path, true))
|
||||
{
|
||||
newTexture.SamplerState = SamplerStateManager.AnisotropicWrap;
|
||||
material.SetTexture(texture.key, newTexture);
|
||||
}*/
|
||||
}
|
||||
|
||||
ImGui.EndDragDropTarget();
|
||||
}
|
||||
}
|
||||
|
||||
private static void ShowAddComponentButton(Entity entity)
|
||||
{
|
||||
static char8[128] searchBuffer = .();
|
||||
|
||||
@@ -8,70 +8,38 @@ using GlitchyEngine.Math;
|
||||
|
||||
namespace GlitchyEditor.EditWindows
|
||||
{
|
||||
using internal GlitchyEditor.EditorContentManager;
|
||||
|
||||
class ContentBrowserWindow : EditorWindow
|
||||
{
|
||||
// TODO: Get from project
|
||||
const String ContentDirectory = "./content";
|
||||
|
||||
FileSystemWatcher fsw ~ {
|
||||
_.StopRaisingEvents();
|
||||
delete _;
|
||||
};
|
||||
|
||||
private String _currentDirectory ~ delete _;
|
||||
//private String _currentDirectory ~ delete _;
|
||||
private TreeNode<EditorContentManager.AssetNode> _currentDirectoryNode;
|
||||
|
||||
public static SubTexture2D s_FolderTexture;
|
||||
public static SubTexture2D s_FileTexture;
|
||||
|
||||
public EditorContentManager _manager ~ delete _;
|
||||
|
||||
public this()
|
||||
{
|
||||
fsw = new FileSystemWatcher(ContentDirectory);
|
||||
fsw.IncludeSubdirectories = true;
|
||||
|
||||
fsw.OnChanged.Add(new (filename) => {
|
||||
_fileSystemDirty = true;
|
||||
_currentDirectoryDirty = true;
|
||||
});
|
||||
|
||||
fsw.OnCreated.Add(new (filename) => {
|
||||
_fileSystemDirty = true;
|
||||
_currentDirectoryDirty = true;
|
||||
});
|
||||
|
||||
fsw.OnDeleted.Add(new (filename) => {
|
||||
_fileSystemDirty = true;
|
||||
_currentDirectoryDirty = true;
|
||||
});
|
||||
|
||||
fsw.OnRenamed.Add(new (newName, oldName) => {
|
||||
_fileSystemDirty = true;
|
||||
_currentDirectoryDirty = true;
|
||||
});
|
||||
|
||||
fsw.StartRaisingEvents();
|
||||
|
||||
_manager = new EditorContentManager();
|
||||
}
|
||||
|
||||
protected override void InternalShow()
|
||||
{
|
||||
_manager.Update();
|
||||
|
||||
_currentDirectoryNode ??= _manager._assetHierarchy;
|
||||
|
||||
if(!ImGui.Begin("Content Browser", &_open, .None))
|
||||
{
|
||||
ImGui.End();
|
||||
return;
|
||||
}
|
||||
|
||||
if (_fileSystemDirty)
|
||||
{
|
||||
BuildDirectoryTree();
|
||||
|
||||
_fileSystemDirty = false;
|
||||
}
|
||||
|
||||
if (_currentDirectoryDirty)
|
||||
{
|
||||
BuildCurrentDirectory();
|
||||
}
|
||||
|
||||
ImGui.Columns(2);
|
||||
|
||||
DrawDirectorySideBar();
|
||||
@@ -85,101 +53,27 @@ namespace GlitchyEditor.EditWindows
|
||||
ImGui.End();
|
||||
}
|
||||
|
||||
private bool _fileSystemDirty = true;
|
||||
private bool _currentDirectoryDirty = true;
|
||||
|
||||
class DirectoryNode
|
||||
{
|
||||
public String Name ~ delete _;
|
||||
public String Path ~ delete _;
|
||||
}
|
||||
|
||||
TreeNode<DirectoryNode> directoryNames = new TreeNode<DirectoryNode>() ~ DeleteTreeAndChildren!(_);
|
||||
|
||||
class Entry
|
||||
{
|
||||
public String Name ~ delete _;
|
||||
public bool IsDirectory;
|
||||
}
|
||||
|
||||
List<Entry> _currentDirContent = new .() ~ DeleteContainerAndItems!(_);
|
||||
|
||||
private void BuildDirectoryTree()
|
||||
{
|
||||
DeleteTreeAndChildren!(directoryNames);
|
||||
directoryNames = new TreeNode<DirectoryNode>();
|
||||
|
||||
String str = scope .(ContentDirectory);
|
||||
|
||||
void AddDirectoryToTree(String path, TreeNode<DirectoryNode> parentNode)
|
||||
{
|
||||
DirectoryNode node = new DirectoryNode();
|
||||
node.Path = new String(path);
|
||||
node.Name = new String();
|
||||
|
||||
Path.GetFileName(node.Path, node.Name);
|
||||
|
||||
var newNode = parentNode.AddChild(node);
|
||||
|
||||
String filter = scope $"{path}/*";
|
||||
|
||||
for (var directory in Directory.Enumerate(filter, .Directories))
|
||||
{
|
||||
directory.GetFilePath(str..Clear());
|
||||
|
||||
AddDirectoryToTree(str, newNode);
|
||||
}
|
||||
}
|
||||
|
||||
String filter = scope $"{ContentDirectory}/*";
|
||||
|
||||
for (var directory in Directory.Enumerate(filter, .Directories))
|
||||
{
|
||||
directory.GetFilePath(str..Clear());
|
||||
|
||||
AddDirectoryToTree(str, directoryNames);
|
||||
}
|
||||
}
|
||||
|
||||
private void BuildCurrentDirectory()
|
||||
{
|
||||
ClearAndDeleteItems!(_currentDirContent);
|
||||
|
||||
String filter = scope $"{_currentDirectory}/*";
|
||||
|
||||
String buffer = scope String();
|
||||
|
||||
for (var entry in Directory.Enumerate(filter, .Directories | .Files))
|
||||
{
|
||||
entry.GetFilePath(buffer..Clear());
|
||||
|
||||
Entry e = new Entry();
|
||||
e.Name = new String();
|
||||
Path.GetFileName(buffer, e.Name);
|
||||
e.IsDirectory = entry.IsDirectory;
|
||||
|
||||
_currentDirContent.Add(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawDirectorySideBar()
|
||||
{
|
||||
for(var child in directoryNames.Children)
|
||||
for(var child in _manager._assetHierarchy.Children)
|
||||
{
|
||||
ImGuiPrintEntityTree(child);
|
||||
}
|
||||
}
|
||||
|
||||
private void ImGuiPrintEntityTree(TreeNode<DirectoryNode> tree)
|
||||
private void ImGuiPrintEntityTree(TreeNode<EditorContentManager.AssetNode> tree)
|
||||
{
|
||||
String name = tree.Value.Name;
|
||||
if (!tree->IsDirectory)
|
||||
return;
|
||||
|
||||
String name = tree->Name;
|
||||
|
||||
ImGui.TreeNodeFlags flags = .OpenOnArrow | .SpanAvailWidth;
|
||||
|
||||
if(tree.Children.Count == 0)
|
||||
flags |= .Leaf;
|
||||
|
||||
if (tree.Value.Path == _currentDirectory)
|
||||
if (tree == _currentDirectoryNode)
|
||||
{
|
||||
flags |= .Selected;
|
||||
}
|
||||
@@ -188,10 +82,11 @@ namespace GlitchyEditor.EditWindows
|
||||
|
||||
if (ImGui.IsItemClicked(.Left))
|
||||
{
|
||||
if (_currentDirectory != null)
|
||||
/*if (_currentDirectory != null)
|
||||
delete _currentDirectory;
|
||||
|
||||
_currentDirectory = new String(tree.Value.Path);
|
||||
_currentDirectory = new String(tree.Value.Path);*/
|
||||
_currentDirectoryNode = tree;
|
||||
}
|
||||
|
||||
if(isOpen)
|
||||
@@ -205,35 +100,38 @@ namespace GlitchyEditor.EditWindows
|
||||
}
|
||||
}
|
||||
|
||||
private static Vector2 DirectoryItemSize = .(100, 100);
|
||||
private static Vector2 DirectoryItemSize = .(110, 110);
|
||||
|
||||
const Vector2 padding = .(24, 24);
|
||||
|
||||
private void DrawCurrentDirectory()
|
||||
{
|
||||
if (_currentDirectoryNode == null)
|
||||
return;
|
||||
|
||||
ImGui.Style* style = ImGui.GetStyle();
|
||||
|
||||
float window_visible_x2 = ImGui.GetWindowPos().x + ImGui.GetWindowContentRegionMax().x;
|
||||
for (var entry in _currentDirContent)
|
||||
for (var entry in _currentDirectoryNode.Children)
|
||||
{
|
||||
ImGui.PushID(entry.Name);
|
||||
ImGui.PushID(entry->Name);
|
||||
|
||||
DrawDirectoryItem(entry);
|
||||
|
||||
float last_button_x2 = ImGui.GetItemRectMax().x;
|
||||
float next_button_x2 = last_button_x2 + style.ItemSpacing.x + DirectoryItemSize.X; // Expected position if next button was on same line
|
||||
if (entry != _currentDirContent.Back && next_button_x2 < window_visible_x2)
|
||||
if (entry != _currentDirectoryNode.Children.Back && next_button_x2 < window_visible_x2)
|
||||
ImGui.SameLine();
|
||||
|
||||
ImGui.PopID();
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawDirectoryItem(Entry entry)
|
||||
private void DrawDirectoryItem(TreeNode<EditorContentManager.AssetNode> entry)
|
||||
{
|
||||
ImGui.BeginChild("item", (.)DirectoryItemSize);
|
||||
|
||||
SubTexture2D image = entry.IsDirectory ? s_FolderTexture : s_FileTexture;
|
||||
SubTexture2D image = entry->IsDirectory ? s_FolderTexture : s_FileTexture;
|
||||
|
||||
ImGui.PushStyleColor(.Button, ImGui.Vec4(0, 0, 0, 0));
|
||||
|
||||
@@ -241,7 +139,7 @@ namespace GlitchyEditor.EditWindows
|
||||
|
||||
if (ImGui.BeginDragDropSource())
|
||||
{
|
||||
String fullpath = scope $"{_currentDirectory}{Path.DirectorySeparatorChar}{entry.Name}";
|
||||
String fullpath = scope $"{_currentDirectoryNode->Path}{Path.DirectorySeparatorChar}{entry->Name}";
|
||||
|
||||
// TODO: this is dirty
|
||||
if (fullpath.StartsWith(ContentDirectory, .OrdinalIgnoreCase))
|
||||
@@ -259,17 +157,51 @@ namespace GlitchyEditor.EditWindows
|
||||
|
||||
ImGui.PopStyleColor();
|
||||
|
||||
ImGui.TextUnformatted(entry.Name);
|
||||
ImGui.TextUnformatted(entry->Name);
|
||||
|
||||
if (entry->SubAssets?.Count > 0)
|
||||
{
|
||||
// Button for revealing sub assets (e.g. Meshes in 3D-Model)
|
||||
|
||||
ImGui.SameLine();
|
||||
if (ImGui.Button(">"))
|
||||
ImGui.OpenPopup("SubAssets");
|
||||
}
|
||||
|
||||
if (ImGui.BeginPopup("SubAssets", .Popup))
|
||||
{
|
||||
for (var subAsset in entry->SubAssets)
|
||||
{
|
||||
ImGui.Button(subAsset.Name);
|
||||
|
||||
if (ImGui.BeginDragDropSource())
|
||||
{
|
||||
String fullpath = Path.InternalCombine(.. scope String(), _currentDirectoryNode->Path, entry->Name);
|
||||
fullpath.AppendF($"#{subAsset.Name}");
|
||||
//scope $"{_currentDirectoryNode->Path}{Path.DirectorySeparatorChar}{entry->Name}";
|
||||
//String fullpath = scope $"{subAsset.Asset.Path}#{subAsset.Name}";
|
||||
|
||||
// TODO: this is dirty
|
||||
//if (fullpath.StartsWith(ContentDirectory, .OrdinalIgnoreCase))
|
||||
// fullpath.Remove(0, ContentDirectory.Length);
|
||||
|
||||
ImGui.SetDragDropPayload("CONTENT_BROWSER_ITEM", fullpath.CStr(), (.)fullpath.Length, .Once);
|
||||
|
||||
ImGui.EndDragDropSource();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui.EndPopup();
|
||||
}
|
||||
|
||||
ImGui.EndChild();
|
||||
}
|
||||
|
||||
private void EntryDoubleClicked(Entry entry)
|
||||
private void EntryDoubleClicked(TreeNode<EditorContentManager.AssetNode> entry)
|
||||
{
|
||||
if (entry.IsDirectory)
|
||||
if (entry->IsDirectory)
|
||||
{
|
||||
_currentDirectory.Append(Path.DirectorySeparatorChar);
|
||||
_currentDirectory.Append(entry.Name);
|
||||
_currentDirectoryNode = entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,247 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using GlitchyEngine.Collections;
|
||||
using System.Collections;
|
||||
using GlitchyEngine.Renderer;
|
||||
using System.Threading;
|
||||
using GlitchyEngine.Content;
|
||||
|
||||
namespace GlitchyEditor;
|
||||
|
||||
/*class PreviewImageManager
|
||||
{
|
||||
/// Thread that loads/generates preview images in the background
|
||||
//private Thread _loaderThread;
|
||||
|
||||
/// Set to true to notify the loader to stop
|
||||
//private bool _stopLoader;
|
||||
|
||||
private append Dictionary<String, Texture2D> _previewImages = .() ~ {
|
||||
for (var v in _)
|
||||
{
|
||||
delete v.key;
|
||||
v.value.ReleaseRef();
|
||||
}
|
||||
|
||||
delete _;
|
||||
};
|
||||
|
||||
public Texture2D GetPreviewImage(String assetName)
|
||||
{
|
||||
if (_previewImages.TryGetValue(assetName, let image))
|
||||
{
|
||||
return image..AddRef();
|
||||
}
|
||||
|
||||
if (assetName.EndsWith(".png", .OrdinalIgnoreCase))
|
||||
{
|
||||
/*using (Texture2D texture = new Texture2D(assetName, true))
|
||||
{
|
||||
Texture2DDesc desc = .(128, 128, .R8G8B8A8_UNorm_SRGB)
|
||||
{
|
||||
Usage = .Immutable
|
||||
};
|
||||
|
||||
Texture2D myActualTexture = new Texture2D(desc);
|
||||
|
||||
// TODO: Scale down texture (on GPU?)
|
||||
}*/
|
||||
|
||||
Texture2D texture = new Texture2D(assetName, true);
|
||||
|
||||
if (texture.Width <= 128 && texture.Height <= 128)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
if ( texture.MipLevels > 1)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
_previewImages.Add(new String(assetName), texture);
|
||||
|
||||
return texture..AddRef();
|
||||
}
|
||||
else
|
||||
{
|
||||
Runtime.NotImplemented();
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
class EditorContentManager
|
||||
{
|
||||
// TODO: Get from project
|
||||
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();
|
||||
}
|
||||
|
||||
internal TreeNode<AssetNode> _assetHierarchy = new TreeNode<AssetNode>() ~ DeleteTreeAndChildren!(_);
|
||||
|
||||
public this()
|
||||
{
|
||||
SetupFileSystemWatcher();
|
||||
}
|
||||
|
||||
/// Initializes the FSW for the current ContentDirectory and registers the events.
|
||||
private void SetupFileSystemWatcher()
|
||||
{
|
||||
fsw = new FileSystemWatcher(ContentDirectory);
|
||||
fsw.IncludeSubdirectories = true;
|
||||
|
||||
fsw.OnChanged.Add(new (filename) => {
|
||||
_fileSystemDirty = true;
|
||||
});
|
||||
|
||||
fsw.OnCreated.Add(new (filename) => {
|
||||
_fileSystemDirty = true;
|
||||
});
|
||||
|
||||
fsw.OnDeleted.Add(new (filename) => {
|
||||
_fileSystemDirty = true;
|
||||
});
|
||||
|
||||
fsw.OnRenamed.Add(new (newName, oldName) => {
|
||||
_fileSystemDirty = true;
|
||||
});
|
||||
|
||||
fsw.StartRaisingEvents();
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
if (_fileSystemDirty)
|
||||
{
|
||||
UpdateFiles();
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateFiles()
|
||||
{
|
||||
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)
|
||||
{
|
||||
// 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()
|
||||
{
|
||||
Asset = assetNode.Value,
|
||||
Name = new String(assetNode->Name)
|
||||
});
|
||||
}
|
||||
else if (assetNode->Name.EndsWith(".gltf", .OrdinalIgnoreCase) || assetNode->Name.EndsWith(".glb", .OrdinalIgnoreCase))
|
||||
{
|
||||
List<String> meshNames = scope List<String>();
|
||||
ModelLoader.GetMeshNames(assetNode->Path, meshNames);
|
||||
|
||||
assetNode->SubAssets = new List<Asset>();
|
||||
|
||||
for (var meshName in meshNames)
|
||||
{
|
||||
assetNode->SubAssets.Add(new Asset()
|
||||
{
|
||||
Asset = assetNode.Value,
|
||||
// Pass ownership of meshName to SubAsset -> save a copy and delete
|
||||
Name = meshName
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AddFilesOfDirectory(TreeNode<AssetNode> directory)
|
||||
{
|
||||
String filter = scope $"{directory->Path}/*";
|
||||
|
||||
String buffer = scope String();
|
||||
|
||||
for (var entry in Directory.Enumerate(filter, .Files))
|
||||
{
|
||||
entry.GetFilePath(buffer..Clear());
|
||||
|
||||
AssetNode e = new AssetNode();
|
||||
e.Name = new String();
|
||||
Path.GetFileName(buffer, e.Name);
|
||||
|
||||
e.Path = new String(buffer);
|
||||
|
||||
e.IsDirectory = entry.IsDirectory;
|
||||
|
||||
var node = directory.AddChild(e);
|
||||
GrabSubAssets(node);
|
||||
}
|
||||
}
|
||||
|
||||
void AddDirectoryToTree(String path, TreeNode<AssetNode> parentNode)
|
||||
{
|
||||
AssetNode node = new AssetNode();
|
||||
node.Path = new String(path);
|
||||
node.Name = new String();
|
||||
node.IsDirectory = true;
|
||||
|
||||
Path.GetFileName(node.Path, node.Name);
|
||||
|
||||
var newNode = parentNode.AddChild(node);
|
||||
|
||||
String filter = scope $"{path}/*";
|
||||
|
||||
for (var directory in Directory.Enumerate(filter, .Directories))
|
||||
{
|
||||
directory.GetFilePath(str..Clear());
|
||||
|
||||
AddDirectoryToTree(str, newNode);
|
||||
}
|
||||
|
||||
AddFilesOfDirectory(newNode);
|
||||
}
|
||||
|
||||
String filter = scope $"{ContentDirectory}/*";
|
||||
|
||||
for (var directory in Directory.Enumerate(filter, .Directories))
|
||||
{
|
||||
directory.GetFilePath(str..Clear());
|
||||
|
||||
AddDirectoryToTree(str, _assetHierarchy);
|
||||
}
|
||||
|
||||
_fileSystemDirty = false;
|
||||
}
|
||||
}
|
||||
@@ -12,13 +12,67 @@ namespace GlitchyEngine.Content
|
||||
{
|
||||
static readonly Matrix RightToLeftHand = .Scaling(1, 1, -1);
|
||||
|
||||
public static Result<void> GetMeshNames(String filename, List<String> meshNames)
|
||||
{
|
||||
CGLTF.Options options = .();
|
||||
CGLTF.Data* data;
|
||||
CGLTF.Result result = CGLTF.ParseFile(options, filename, out data);
|
||||
|
||||
if (!(result case .Success))
|
||||
return .Err;
|
||||
|
||||
for (var mesh in data.Meshes)
|
||||
{
|
||||
meshNames.Add(new String(mesh.Name));
|
||||
}
|
||||
|
||||
CGLTF.Free(data);
|
||||
|
||||
return .Ok;
|
||||
}
|
||||
|
||||
public static GeometryBinding LoadMesh(StringView fileName, 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.
|
||||
|
||||
char8* scopedFileName = fileName.ToScopeCStr!();
|
||||
|
||||
CGLTF.Options options = .();
|
||||
CGLTF.Data* data;
|
||||
CGLTF.Result result = CGLTF.ParseFile(options, scopedFileName, out data);
|
||||
|
||||
if (!(result case .Success))
|
||||
return null;
|
||||
|
||||
result = CGLTF.LoadBuffers(options, data, scopedFileName);
|
||||
|
||||
GeometryBinding geoBinding = null;
|
||||
|
||||
for (var mesh in data.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(data);
|
||||
|
||||
return geoBinding;
|
||||
}
|
||||
|
||||
public static EcsEntity LoadModel(String filename, Material material, EcsWorld world,
|
||||
List<AnimationClip> outClips, StringView entityName = StringView())
|
||||
{
|
||||
CGLTF.Options options = .();
|
||||
CGLTF.Data* data;
|
||||
CGLTF.Result result = CGLTF.ParseFile(options, filename, out data);
|
||||
|
||||
|
||||
Log.EngineLogger.Assert(result == .Success, "Failed to load model.");
|
||||
|
||||
result = CGLTF.LoadBuffers(options, data, filename);
|
||||
|
||||
Reference in New Issue
Block a user