Skip to content

Commit

Permalink
Support additional texture compression formats in portrait preview
Browse files Browse the repository at this point in the history
  • Loading branch information
tech-ticks committed Nov 5, 2021
1 parent d96f662 commit 6589ae6
Show file tree
Hide file tree
Showing 3 changed files with 897 additions and 4 deletions.
59 changes: 55 additions & 4 deletions SkyEditor.UI/Controllers/Pokemon/PokemonController.cs
Expand Up @@ -13,6 +13,7 @@
using SkyEditorUI.Infrastructure.AssetFormats;
using Cairo;
using System.Threading;
using System.IO;

namespace SkyEditorUI.Controllers
{
Expand Down Expand Up @@ -41,6 +42,8 @@ partial class PokemonController : Widget
private Modpack modpack;
private Builder builder;
private ImageSurface? portraitSurface;
private double portraitZoomFactor = 1;
private bool nearestNeighborFiltering = false;

public PokemonController(IRtdxRom rom, Modpack modpack, ControllerContext context)
: this(new Builder("Pokemon.glade"), rom, modpack, context)
Expand Down Expand Up @@ -149,8 +152,25 @@ private void LoadPortrait()

new Thread(() =>
{
assetBundles.LoadFiles(PhysicalFileSystem.Instance, IOPath.Combine(rom.RomDirectory,
"romfs/Data/StreamingAssets/ab", $"{portraitSheetName}.ab"));
var relativePortraitPath = IOPath.Combine("ab", $"{portraitSheetName}.ab");
string? assetBundlePath = null;
foreach (var mod in modpack!.Mods ?? Enumerable.Empty<Mod>())
{
var bundlePathInMod = IOPath.Combine(mod.GetAssetsDirectory(), relativePortraitPath);
if (File.Exists(bundlePathInMod))
{
assetBundlePath = bundlePathInMod;
break;
}
}
if (assetBundlePath == null)
{
// Load from the ROM if it's not overwritten in any mods
assetBundlePath = IOPath.Combine(rom.RomDirectory, "romfs/Data/StreamingAssets/", relativePortraitPath);
}
assetBundles.LoadFiles(PhysicalFileSystem.Instance, assetBundlePath);
System.Console.WriteLine($"Loading {assetBundlePath}");
var file = assetBundles.assetsFileList[0];
var texture = file.Objects.OfType<Texture2D>().FirstOrDefault();
if (texture == null)
Expand All @@ -163,12 +183,31 @@ private void LoadPortrait()
var encodedData = texture.image_data.GetData();
assetBundles.Clear();
if (texture.m_TextureFormat != TextureFormat.ASTC_RGBA_4x4)
byte[] decoded;
if (texture.m_TextureFormat == TextureFormat.ASTC_RGBA_4x4)
{
decoded = AstcDecoder.DecodeASTC(encodedData, texture.m_Width, texture.m_Height, 4, 4);
}
else if (texture.m_TextureFormat == TextureFormat.DXT1)
{
decoded = new byte[texture.m_Width * texture.m_Height * 4]; // RGBA
DxtDecoder.DecompressDXT1(encodedData, texture.m_Width, texture.m_Height, decoded);
}
else if (texture.m_TextureFormat == TextureFormat.RGB24)
{
decoded = new byte[texture.m_Width * texture.m_Height * 4]; // RGBA
RgbConverter.RGB24ToBGRA32(encodedData, texture.m_Width, texture.m_Height, decoded);
}
else if (texture.m_TextureFormat == TextureFormat.RGBA32)
{
decoded = new byte[texture.m_Width * texture.m_Height * 4]; // RGBA
RgbConverter.RGBA32ToBGRA32(encodedData, texture.m_Width, texture.m_Height, decoded);
}
else
{
Console.WriteLine($"Unexpected texture format: {texture.m_TextureFormat}");
return;
}
var decoded = AstcDecoder.DecodeASTC(encodedData, texture.m_Width, texture.m_Height, 4, 4);
if (portraitSurface != null)
{
Expand All @@ -177,6 +216,12 @@ private void LoadPortrait()
portraitSurface = new ImageSurface(decoded, Format.ARGB32, texture.m_Width, texture.m_Height,
4 * texture.m_Width);
// The expected size is 1024x1024, but portraits can be bigger or smaller
portraitZoomFactor = 1024 / texture.m_Width;
System.Console.WriteLine(portraitZoomFactor);
System.Console.WriteLine(texture.m_Width);
nearestNeighborFiltering = texture.m_TextureSettings.m_FilterMode == 0;
GLib.Idle.Add(() =>
{
drawAreaPortrait!.QueueDraw();
Expand All @@ -199,12 +244,18 @@ private void OnDrawPortrait(object sender, DrawnArgs args)

args.Cr.Save();
args.Cr.Scale(0.5, 0.5);
args.Cr.Scale(portraitZoomFactor, portraitZoomFactor);

// The image is flipped vertically
args.Cr.Translate(0, portraitSurface.Height);
args.Cr.Scale(1, -1);

args.Cr.SetSourceSurface(portraitSurface, 0, 0);
using var pattern = args.Cr.GetSource() as SurfacePattern;
if (pattern != null)
{
pattern.Filter = nearestNeighborFiltering ? Filter.Nearest : Filter.Good;
}
args.Cr.Paint();
args.Cr.Restore();

Expand Down

0 comments on commit 6589ae6

Please sign in to comment.