Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions Editors/BmdEditor/ContextMenu/ExportBmdAsTerryProjectCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
using System;
using System.IO;
using System.Text;
using Editors.BmdEditor.Exporting;
using Shared.Core.Misc;
using Shared.Core.PackFiles;
using Shared.Core.Services;
using Shared.GameFormats.Bmd;
using Shared.Ui.BaseDialogs.PackFileTree;
using Shared.Ui.BaseDialogs.PackFileTree.ContextMenu.Commands;
using Shared.Ui.BaseDialogs.PackFileTree.Utility;

namespace Editors.BmdEditor.ContextMenu
{
public class ExportBmdAsTerryProjectCommand(IPackFileService packFileService, IStandardDialogs standardDialogs, IFileSystemAccess fileSystemAccess) : IContextMenuCommand
{
private readonly IPackFileService _packFileService = packFileService;
private readonly IStandardDialogs _standardDialogs = standardDialogs;
private readonly IFileSystemAccess _fileSystemAccess = fileSystemAccess;

public string GetDisplayName(TreeNode node) => "Export as Terry project";
public bool ShouldAdd(TreeNode node) => node.NodeType == NodeType.File && TreeNodeHelper.GetPackFile(node) != null;
public bool IsEnabled(TreeNode node)
{
var packFile = TreeNodeHelper.GetPackFile(node);
return packFile != null && packFile.Name.EndsWith(".bmd", StringComparison.OrdinalIgnoreCase);
}

private TreeNode _node = null!;

public void Configure(TreeNode node)
{
_node = node;
}

public void Execute()
{
var packFile = TreeNodeHelper.GetPackFile(_node);
if (packFile == null)
return;

var dialogResult = _standardDialogs.ShowSystemFolderBrowserDialog();
if (!dialogResult.Result || string.IsNullOrWhiteSpace(dialogResult.FolderPath))
return;

DirectoryHelper.EnsureCreated(dialogResult.FolderPath);

var bmdFile = BmdParser.Parse(packFile.DataSource.ReadData());
var project = BmdTerryProjectWriter.Build(bmdFile, BmdReferenceResolver.Create(_packFileService));

var baseName = Path.GetFileNameWithoutExtension(packFile.Name);
var terryPath = Path.Combine(dialogResult.FolderPath, baseName + ".terry");
var layerPath = Path.Combine(dialogResult.FolderPath, $"{baseName}.{project.LayerEntityId}.layer");

_fileSystemAccess.FileWriteAllBytes(terryPath, Encoding.UTF8.GetBytes(project.TerryXml));
_fileSystemAccess.FileWriteAllBytes(layerPath, Encoding.UTF8.GetBytes(project.LayerXml));
}
}
}
22 changes: 18 additions & 4 deletions Editors/BmdEditor/DependencyInjectionContainer.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Editors.BmdEditor.ViewModels;
using Editors.BmdEditor.ContextMenu;
using Editors.BmdEditor.ViewModels;
using Editors.BmdEditor.Views;
using Editors.BmdEditor.Services;
using Microsoft.Extensions.DependencyInjection;
Expand All @@ -14,6 +15,7 @@
using GameWorld.Core.Rendering.Geometry;
using GameWorld.Core.WpfWindow;
using GameWorld.Core.Components.Selection;
using Shared.Ui.BaseDialogs.PackFileTree.ContextMenu;

namespace Editors.BmdEditor
{
Expand All @@ -23,19 +25,23 @@ public override void Register(IServiceCollection serviceCollection)
{
// Views
serviceCollection.AddTransient<BmdEditorView>();
serviceCollection.AddTransient<BmdSceneView>();
serviceCollection.AddTransient<Bmd3DSceneViewer>();

// ViewModels
serviceCollection.AddScoped<BmdEditorViewModel>();
serviceCollection.AddScoped<BmdSceneViewModel>();
serviceCollection.AddScoped<IEditorInterface, BmdEditorViewModel>();

// Services
serviceCollection.AddScoped<BmdSceneCreator>();
serviceCollection.AddScoped<SelectionManager>();
serviceCollection.AddScoped<BmdElementLoader>();

// Game components (picked up by IComponentInserter)
RegisterGameComponent<BmdGizmoComponent>(serviceCollection);

// Context menu
serviceCollection.AddScoped<ExportBmdAsTerryProjectCommand>();
serviceCollection.AddSingleton<IPackFileContextMenuRegistration, BmdPackFileContextMenuRegistration>();

RegisterAllAsInterface<IDeveloperConfiguration>(serviceCollection, ServiceLifetime.Transient);
}

Expand All @@ -48,4 +54,12 @@ public override void RegisterTools(IEditorDatabase editorDatabase)
.Build(editorDatabase);
}
}

public class BmdPackFileContextMenuRegistration : IPackFileContextMenuRegistration
{
public void Register(PackFileContextMenuRegistry registry)
{
registry.RegisterPackFileContextMenuItem<ExportBmdAsTerryProjectCommand>(ContextMenuType.MainApplication, path: "Export", priority: 40, ContextMenuCluster.Export);
}
}
}
1 change: 1 addition & 0 deletions Editors/BmdEditor/Editors.BmdEditor.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
<ProjectReference Include="..\..\Shared\SharedCore\Shared.Core\Shared.Core.csproj" />
<ProjectReference Include="..\..\Shared\GameFiles\Shared.GameFormats.csproj" />
<ProjectReference Include="..\..\Shared\SharedUI\Shared.Ui\Shared.Ui.csproj" />
<ProjectReference Include="..\..\Shared\EmbeddedResources\Shared.EmbeddedResources.csproj" />
</ItemGroup>

</Project>
18 changes: 18 additions & 0 deletions Editors/BmdEditor/Exporting/BmdReferenceResolver.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using Shared.Core.PackFiles;
using Shared.GameFormats.Bmd;

namespace Editors.BmdEditor.Exporting
{
/// <summary>Resolves a BmdInfo reference's path to its parsed <see cref="BmdFile"/> via the pack
/// file system, for recursively flattening nested BMDs during Terry export.</summary>
public static class BmdReferenceResolver
{
public static Func<string, BmdFile?> Create(IPackFileService packFileService) => path =>
{
var packFile = packFileService.FindFile(path);
if (packFile == null)
return null;
return BmdParser.Parse(packFile.DataSource.ReadData());
};
}
}
Loading
Loading