mirror of
https://github.com/AssetRipper/AssetRipper.git
synced 2025-12-11 20:15:29 +01:00
parent
e7b6db3545
commit
03646ed0c7
@ -204,6 +204,7 @@
|
||||
"sprite_format_texture_description": "Export as an image of the sprite sheet. Can be viewed outside of Unity, but slower to export.",
|
||||
"sprite_format_yaml": "Yaml",
|
||||
"sprite_format_yaml_description": "Export as yaml assets which can be viewed in the editor. This is the only mode that ensures a precise recovery of all metadata of sprites.",
|
||||
"stack_trace": "Stack Trace",
|
||||
"submesh_count": "Submesh Count",
|
||||
"success": "Success!",
|
||||
"swagger_documentation": "Swagger Documentation",
|
||||
|
||||
@ -1035,6 +1035,11 @@ partial class Localization
|
||||
/// </summary>
|
||||
public static string SpriteFormatYamlDescription => Get("sprite_format_yaml_description");
|
||||
|
||||
/// <summary>
|
||||
/// Stack Trace
|
||||
/// </summary>
|
||||
public static string StackTrace => Get("stack_trace");
|
||||
|
||||
/// <summary>
|
||||
/// Submesh Count
|
||||
/// </summary>
|
||||
|
||||
@ -76,10 +76,12 @@ public sealed class ViewPage : DefaultPage
|
||||
new H2(writer).Close(Localization.FailedFiles);
|
||||
using (new Ul(writer).End())
|
||||
{
|
||||
foreach (FailedFile failedFile in Bundle.FailedFiles)
|
||||
for (int i = 0; i < Bundle.FailedFiles.Count; i++)
|
||||
{
|
||||
// Todo: page for failed files
|
||||
new Li(writer).Close(failedFile.Name);
|
||||
using (new Li(writer).End())
|
||||
{
|
||||
PathLinking.WriteLink(writer, Path.GetFailedFile(i), Bundle.FailedFiles[i].NameFixed);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,88 @@
|
||||
using AssetRipper.GUI.Web.Paths;
|
||||
using AssetRipper.IO.Files;
|
||||
using AssetRipper.Web.Extensions;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace AssetRipper.GUI.Web.Pages.FailedFiles;
|
||||
|
||||
internal static class FailedFileAPI
|
||||
{
|
||||
public static class Urls
|
||||
{
|
||||
public const string Base = "/FailedFiles";
|
||||
public const string View = Base + "/View";
|
||||
public const string StackTrace = Base + "/StackTrace";
|
||||
}
|
||||
|
||||
private const string Path = "Path";
|
||||
|
||||
public static string GetViewUrl(FailedFilePath path) => $"{Urls.View}?{GetPathQuery(path)}";
|
||||
public static Task GetView(HttpContext context)
|
||||
{
|
||||
context.Response.DisableCaching();
|
||||
if (TryGetFileFromQuery(context, out FailedFile? file, out FailedFilePath path, out Task? failureTask))
|
||||
{
|
||||
return new ViewPage() { File = file, Path = path }.WriteToResponse(context.Response);
|
||||
}
|
||||
else
|
||||
{
|
||||
return failureTask;
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetStackTraceUrl(FailedFilePath path) => $"{Urls.StackTrace}?{GetPathQuery(path)}";
|
||||
public static Task GetStackTrace(HttpContext context)
|
||||
{
|
||||
context.Response.DisableCaching();
|
||||
if (TryGetFileFromQuery(context, out FailedFile? file, out _, out Task? failureTask))
|
||||
{
|
||||
return Results.Text(file.StackTrace).ExecuteAsync(context);
|
||||
}
|
||||
else
|
||||
{
|
||||
return failureTask;
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetPathQuery(FailedFilePath path) => $"{Path}={path.ToJson().ToUrl()}";
|
||||
|
||||
private static bool TryGetFileFromQuery(HttpContext context, [NotNullWhen(true)] out FailedFile? file, out FailedFilePath path, [NotNullWhen(false)] out Task? failureTask)
|
||||
{
|
||||
if (!context.Request.Query.TryGetValue(Path, out string? json) || string.IsNullOrEmpty(json))
|
||||
{
|
||||
file = null;
|
||||
path = default;
|
||||
failureTask = context.Response.NotFound("The path must be included in the request.");
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
path = FailedFilePath.FromJson(json);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
file = null;
|
||||
path = default;
|
||||
failureTask = context.Response.NotFound(ex.ToString());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!GameFileLoader.IsLoaded)
|
||||
{
|
||||
file = null;
|
||||
failureTask = context.Response.NotFound("No files loaded.");
|
||||
return false;
|
||||
}
|
||||
else if (!GameFileLoader.GameBundle.TryGetFailedFile(path, out file))
|
||||
{
|
||||
failureTask = context.Response.NotFound($"Resource file could not be resolved: {path}");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
failureTask = null;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
37
Source/AssetRipper.GUI.Web/Pages/FailedFiles/ViewPage.cs
Normal file
37
Source/AssetRipper.GUI.Web/Pages/FailedFiles/ViewPage.cs
Normal file
@ -0,0 +1,37 @@
|
||||
using AssetRipper.Assets.Bundles;
|
||||
using AssetRipper.GUI.Web.Paths;
|
||||
using AssetRipper.IO.Files;
|
||||
|
||||
namespace AssetRipper.GUI.Web.Pages.FailedFiles;
|
||||
|
||||
public sealed class ViewPage : DefaultPage
|
||||
{
|
||||
public required FailedFile File { get; init; }
|
||||
public required FailedFilePath Path { get; init; }
|
||||
|
||||
public Bundle? Bundle => GameFileLoader.GameBundle.TryGetBundle(Path.BundlePath);
|
||||
|
||||
public override string GetTitle() => File.NameFixed;
|
||||
|
||||
public override void WriteInnerContent(TextWriter writer)
|
||||
{
|
||||
new H1(writer).Close(GetTitle());
|
||||
|
||||
if (Bundle is { } bundle)
|
||||
{
|
||||
new H2(writer).Close(Localization.Bundle);
|
||||
PathLinking.WriteLink(writer, Path.BundlePath, bundle.Name);
|
||||
}
|
||||
|
||||
new H2(writer).Close(Localization.StackTrace);
|
||||
|
||||
string url = FailedFileAPI.GetStackTraceUrl(Path);
|
||||
|
||||
new Pre(writer).WithClass("bg-dark-subtle rounded-3 p-2").WithDynamicTextContent(url).Close();
|
||||
|
||||
using (new Div(writer).WithClass("text-center").End())
|
||||
{
|
||||
SaveButton.Write(writer, url, "error.txt");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -62,6 +62,11 @@ public readonly record struct BundlePath : IPath<BundlePath>
|
||||
return new CollectionPath(this, index);
|
||||
}
|
||||
|
||||
public FailedFilePath GetFailedFile(int index)
|
||||
{
|
||||
return new FailedFilePath(this, index);
|
||||
}
|
||||
|
||||
public ResourcePath GetResource(int index)
|
||||
{
|
||||
return new ResourcePath(this, index);
|
||||
|
||||
17
Source/AssetRipper.GUI.Web/Paths/FailedFilePath.cs
Normal file
17
Source/AssetRipper.GUI.Web/Paths/FailedFilePath.cs
Normal file
@ -0,0 +1,17 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace AssetRipper.GUI.Web.Paths;
|
||||
|
||||
public readonly record struct FailedFilePath([property: JsonPropertyName("B")] BundlePath BundlePath, [property: JsonPropertyName("I")] int Index) : IPath<FailedFilePath>
|
||||
{
|
||||
public string ToJson()
|
||||
{
|
||||
return JsonSerializer.Serialize(this, PathSerializerContext.Default.FailedFilePath);
|
||||
}
|
||||
|
||||
public static FailedFilePath FromJson(string json)
|
||||
{
|
||||
return JsonSerializer.Deserialize(json, PathSerializerContext.Default.FailedFilePath);
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,7 @@
|
||||
using AssetRipper.Assets;
|
||||
using AssetRipper.Assets.Bundles;
|
||||
using AssetRipper.Assets.Collections;
|
||||
using AssetRipper.IO.Files;
|
||||
using AssetRipper.IO.Files.ResourceFiles;
|
||||
|
||||
namespace AssetRipper.GUI.Web.Paths;
|
||||
@ -117,6 +118,22 @@ public static class PathExtensions
|
||||
return resource is not null;
|
||||
}
|
||||
|
||||
public static FailedFile? TryGetFailedFile(this GameBundle gameBundle, FailedFilePath path)
|
||||
{
|
||||
Bundle? bundle = gameBundle.TryGetBundle(path.BundlePath);
|
||||
if (bundle is null || path.Index < 0 || path.Index >= bundle.FailedFiles.Count)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return bundle.FailedFiles[path.Index];
|
||||
}
|
||||
|
||||
public static bool TryGetFailedFile(this GameBundle gameBundle, FailedFilePath path, [NotNullWhen(true)] out FailedFile? failedFile)
|
||||
{
|
||||
failedFile = gameBundle.TryGetFailedFile(path);
|
||||
return failedFile is not null;
|
||||
}
|
||||
|
||||
public static IUnityObjectBase? TryGetAsset(this GameBundle gameBundle, AssetPath path)
|
||||
{
|
||||
AssetCollection? collection = gameBundle.TryGetCollection(path.CollectionPath);
|
||||
|
||||
@ -4,6 +4,7 @@ using AssetRipper.Assets.Collections;
|
||||
using AssetRipper.GUI.Web.Pages.Assets;
|
||||
using AssetRipper.GUI.Web.Pages.Bundles;
|
||||
using AssetRipper.GUI.Web.Pages.Collections;
|
||||
using AssetRipper.GUI.Web.Pages.FailedFiles;
|
||||
using AssetRipper.GUI.Web.Pages.Resources;
|
||||
using AssetRipper.GUI.Web.Pages.Scenes;
|
||||
using System.Runtime.CompilerServices;
|
||||
@ -56,6 +57,10 @@ internal static class PathLinking
|
||||
{
|
||||
return ResourceAPI.GetViewUrl(Unsafe.As<T, ResourcePath>(ref path));
|
||||
}
|
||||
else if (typeof(T) == typeof(FailedFilePath))
|
||||
{
|
||||
return FailedFileAPI.GetViewUrl(Unsafe.As<T, FailedFilePath>(ref path));
|
||||
}
|
||||
else
|
||||
{
|
||||
return "";//Exceptions prevent inlining
|
||||
|
||||
@ -7,6 +7,7 @@ namespace AssetRipper.GUI.Web.Paths;
|
||||
[JsonSerializable(typeof(CollectionPath))]
|
||||
[JsonSerializable(typeof(ScenePath))]
|
||||
[JsonSerializable(typeof(ResourcePath))]
|
||||
[JsonSerializable(typeof(FailedFilePath))]
|
||||
internal sealed partial class PathSerializerContext : JsonSerializerContext
|
||||
{
|
||||
}
|
||||
|
||||
@ -3,6 +3,7 @@ using AssetRipper.GUI.Web.Pages;
|
||||
using AssetRipper.GUI.Web.Pages.Assets;
|
||||
using AssetRipper.GUI.Web.Pages.Bundles;
|
||||
using AssetRipper.GUI.Web.Pages.Collections;
|
||||
using AssetRipper.GUI.Web.Pages.FailedFiles;
|
||||
using AssetRipper.GUI.Web.Pages.Resources;
|
||||
using AssetRipper.GUI.Web.Pages.Scenes;
|
||||
using AssetRipper.GUI.Web.Pages.Settings;
|
||||
@ -255,6 +256,11 @@ public static class WebApplicationLauncher
|
||||
.WithSummary("Get the number of elements in the collection.")
|
||||
.Produces<int>();
|
||||
|
||||
//Failed Files
|
||||
app.MapGet(FailedFileAPI.Urls.View, FailedFileAPI.GetView).ProducesHtmlPage();
|
||||
app.MapGet(FailedFileAPI.Urls.StackTrace, FailedFileAPI.GetStackTrace)
|
||||
.Produces<string>();
|
||||
|
||||
//Resources
|
||||
app.MapGet(ResourceAPI.Urls.View, ResourceAPI.GetView).ProducesHtmlPage();
|
||||
app.MapGet(ResourceAPI.Urls.Data, ResourceAPI.GetData)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user