Skip to content

Commit

Permalink
feat: Make Stride.StorageTool as Gui Tool (#2479)
Browse files Browse the repository at this point in the history
* feat: Make Stride.StorageTool as Gui Tool

* fixup! feat: Make Stride.StorageTool as Gui Tool

* fixup! feat: Make Stride.StorageTool as Gui Tool

* Update README.md

---------

Co-authored-by: Nicolas Musset <[email protected]>
  • Loading branch information
Jklawreszuk and Kryptos-FR authored Oct 8, 2024
1 parent e890e27 commit 2af6925
Show file tree
Hide file tree
Showing 16 changed files with 400 additions and 411 deletions.
277 changes: 141 additions & 136 deletions sources/Directory.Packages.props

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions sources/tools/Stride.StorageTool/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
nupkg/*
11 changes: 11 additions & 0 deletions sources/tools/Stride.StorageTool/App.axaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<Application xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Stride.StorageTool.App"
RequestedThemeVariant="Default">
<!-- "Default" ThemeVariant follows system theme variant. "Dark" or "Light" are other available options. -->

<Application.Styles>
<FluentTheme />
<StyleInclude Source="avares://Avalonia.Controls.DataGrid/Themes/Fluent.xaml"/>
</Application.Styles>
</Application>
24 changes: 24 additions & 0 deletions sources/tools/Stride.StorageTool/App.axaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;

namespace Stride.StorageTool;

public partial class App : Application
{
public override void Initialize()
{
AvaloniaXamlLoader.Load(this);
}

public override void OnFrameworkInitializationCompleted()
{
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
var bundlePath = desktop.Args?.Length > 0 ? desktop.Args[0] : null;
desktop.MainWindow = new MainWindow(bundlePath);
}

base.OnFrameworkInitializationCompleted();
}
}
33 changes: 33 additions & 0 deletions sources/tools/Stride.StorageTool/MainWindow.axaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Stride.StorageTool.MainWindow"
Title="Stride.StorageTool">
<Grid RowDefinitions="Auto,*">
<Menu>
<MenuItem Header="_File">
<MenuItem Header="_Open bundle (Ctrl+O)" HotKey="Ctrl+O" Click="OpenBundle" />
<Separator/>
<MenuItem Header="_Exit (Ctrl+Q)" HotKey="Ctrl+Q" Click="Exit" />
</MenuItem>
</Menu>
<StackPanel VerticalAlignment="Center" Grid.Row="1" Name="WelcomePanel">
<TextBlock
FontSize="32"
FontWeight="SemiBold"
HorizontalAlignment="Center"
Text="Stride StorageTool" />
<TextBlock
FontSize="28"
TextAlignment="Center"
HorizontalAlignment="Center"
Text="Choose File > Open Bundle to open the .bundle file"/>
</StackPanel>
<DataGrid Grid.Row="1" Margin="20" Name="ObjectDataGrid" IsReadOnly="True"
GridLinesVisibility="All"
AutoGenerateColumns="True"
BorderThickness="1" BorderBrush="Gray"/>
</Grid>
</Window>
78 changes: 78 additions & 0 deletions sources/tools/Stride.StorageTool/MainWindow.axaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
using System;
using Avalonia.Controls;
using Avalonia.Interactivity;
using Avalonia.Platform.Storage;
using Stride.Core.Storage;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace Stride.StorageTool;

public partial class MainWindow : Window
{
public MainWindow(string? bundlePath)
{
InitializeComponent();
ObjectDataGrid.IsVisible = false;
WelcomePanel.IsVisible = true;

if (File.Exists(bundlePath))
{
using FileStream fs = File.OpenRead(bundlePath);
LoadObjectEntries(fs);
}
}

private void Exit(object sender, RoutedEventArgs e)
{
Environment.Exit(0);
}

private async void OpenBundle(object sender, RoutedEventArgs e)
{
var bundleFiles = await this.StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions()
{
FileTypeFilter =
[
new("Bundle package") { Patterns = ["*.bundle"], }
],
Title = "Choose .bundle package",
AllowMultiple = false,
});


if(bundleFiles.Count == 0)
return;

var bundleFile = bundleFiles[0];

var bundleStream = await bundleFile.OpenReadAsync();

LoadObjectEntries(bundleStream);
}

private void LoadObjectEntries(Stream bundleStream)
{
BundleDescription bundle = BundleOdbBackend.ReadBundleDescription(bundleStream);

var objectInfos = bundle.Objects.ToDictionary(x => x.Key, x => x.Value);

var entries = new List<ObjectEntry>();
foreach (var locationIds in bundle.Assets)
{
var entry = new ObjectEntry { Location = locationIds.Key, Id = locationIds.Value.ToString() };

if (objectInfos.TryGetValue(locationIds.Value, out var objectInfo))
{
entry.Size = objectInfo.EndOffset - objectInfo.StartOffset;
entry.SizeNotCompressed = objectInfo.SizeNotCompressed;
}
entries.Add(entry);
}

ObjectDataGrid.IsVisible = true;
WelcomePanel.IsVisible = false;
ObjectDataGrid.ItemsSource = entries;
}
}
26 changes: 26 additions & 0 deletions sources/tools/Stride.StorageTool/ObjectEntry.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright (c) .NET Foundation and Contributors (https://dotnetfoundation.org/ & https://stride3d.net) and Silicon Studio Corp. (https://www.siliconstudio.co.jp)
// Distributed under the MIT license. See the LICENSE.md file in the project root for more information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Stride.Core;
using Stride.Core.IO;
using Stride.Core.Storage;

namespace Stride.StorageTool;

/// <summary>
/// Description of an object entry in the bundle.
/// </summary>
public class ObjectEntry
{
public string Location { get; set; }

public string Id { get; set; }

public long Size { get; set; }

public long SizeNotCompressed { get; set; }
}
120 changes: 17 additions & 103 deletions sources/tools/Stride.StorageTool/Program.cs
Original file line number Diff line number Diff line change
@@ -1,107 +1,21 @@
// Copyright (c) .NET Foundation and Contributors (https://dotnetfoundation.org/ & https://stride3d.net) and Silicon Studio Corp. (https://www.siliconstudio.co.jp)
// Distributed under the MIT license. See the LICENSE.md file in the project root for more information.
using Avalonia;
using System;
using System.IO;
using System.Reflection;
using System.Security.Principal;
using Microsoft.Win32;
using Mono.Options;

namespace Stride.StorageTool
{
/// <summary>
/// Tool to manage storage/bundles.
/// </summary>
class Program
{
static void Main(string[] args)
{ var exeName = Path.GetFileName(Assembly.GetExecutingAssembly().Location);
var showHelp = false;
int exitCode = 0;

var p = new OptionSet
{
"Copyright (c) .NET Foundation and Contributors (https://dotnetfoundation.org/ & https://stride3d.net) and Silicon Studio Corp. (https://www.siliconstudio.co.jp) All Rights Reserved",
"Storage Tool - Version: "
+
String.Format(
"{0}.{1}.{2}",
typeof(Program).Assembly.GetName().Version.Major,
typeof(Program).Assembly.GetName().Version.Minor,
typeof(Program).Assembly.GetName().Version.Build) + string.Empty,
string.Format("Usage: {0} command [options]*", exeName),
string.Empty,
"=== command ===",
string.Empty,
"view [bundleFile]",
"register",
"=== Options ===",
string.Empty,
{ "h|help", "Show this message and exit", v => showHelp = v != null },
};

try
{
var commandArgs = p.Parse(args);
if (showHelp)
{
p.WriteOptionDescriptions(Console.Out);
Environment.Exit(0);
}

if (commandArgs.Count == 0)
throw new OptionException("Expecting a command", "");

var command = commandArgs[0];
switch (command)
{
case "view":
if (commandArgs.Count != 2)
{
throw new OptionException("View command expecting a path to bundle file","");
}
StorageToolApp.View(commandArgs[1]);
break;
case "register":
//[HKEY_CURRENT_USER\Software\Classes\.bundle]
//@="bundlefile"
//[HKEY_CURRENT_USER\Software\Classes\bundlefile]
//@="Stride Bundle file Extension"
//[HKEY_CURRENT_USER\Software\Classes\bundlefile\shell\View\command]
//@="StorageTool.exe %1"

var classesKey = Registry.CurrentUser.OpenSubKey("Software\\Classes", RegistryKeyPermissionCheck.ReadWriteSubTree);
var bundleKey = classesKey.CreateSubKey(".bundle");
bundleKey.SetValue(null, "bundlefile");
namespace Stride.StorageTool;

var bundlefileKey = classesKey.CreateSubKey("bundlefile");
bundlefileKey.SetValue(null, "Stride Bundle file Extension");

var commandKey = bundlefileKey.CreateSubKey("shell").CreateSubKey("View").CreateSubKey("command");
commandKey.SetValue(null, Assembly.GetExecutingAssembly().Location + " view %1");

break;
default:
throw new OptionException(string.Format("Invalid command [{0}]", command), "");
}
}
catch (Exception e)
{
LogError("{0}: {1}", exeName, e is OptionException || e is StorageAppException ? e.Message : e.ToString());
if (e is OptionException)
p.WriteOptionDescriptions(Console.Out);

}

Environment.Exit(exitCode);
}

public static void LogError(string message, params object[] args)
{
var color = Console.ForegroundColor;
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(message, args);
Console.ForegroundColor = color;
}
}
class Program
{
// Initialization code. Don't use any Avalonia, third-party APIs or any
// SynchronizationContext-reliant code before AppMain is called: things aren't initialized
// yet and stuff might break.
[STAThread]
public static void Main(string[] args) => BuildAvaloniaApp()
.StartWithClassicDesktopLifetime(args);

// Avalonia configuration, don't remove; also used by visual designer.
public static AppBuilder BuildAvaloniaApp()
=> AppBuilder.Configure<App>()
.UsePlatformDetect()
.WithInterFont()
.LogToTrace();
}
28 changes: 0 additions & 28 deletions sources/tools/Stride.StorageTool/Properties/AssemblyInfo.cs

This file was deleted.

22 changes: 22 additions & 0 deletions sources/tools/Stride.StorageTool/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Stride.StorageTool

This is simple Stride Asset Bundle previewer.
Please, read the article in the documentation to learn more : https://doc.stride3d.net/latest/en/manual/engine/assets/asset-bundles.html

## Installation

To install globally on your system use the `install-tool.ps1` powershell script. Script should install and associate
`stride-bundle` command with .bundle extension.

1. Step: Type `powershell.exe` and run it with administrator privilages.
> [!NOTE]
> Are you running `powershell` first time ?
> Make sure to enable execution of your scripts first.
> Type following command:
> ```ps1
> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
> ```
2. Step: Drag and drop `install-tool.ps1`
Done!
29 changes: 0 additions & 29 deletions sources/tools/Stride.StorageTool/StorageAppException.cs

This file was deleted.

Loading

0 comments on commit 2af6925

Please sign in to comment.