Broken UI and Loading screens

This commit is contained in:
Jan Racek
2026-03-26 19:14:15 +01:00
parent a8aa674a9c
commit d5be174247
6 changed files with 542 additions and 1 deletions

View File

@@ -109,6 +109,15 @@ namespace SplashEdit.EditorCode
return Path.Combine(BuildOutputDir, $"scene_{sceneIndex}.splashpack");
}
/// <summary>
/// Gets the loader pack (loading screen) output path for a scene by index.
/// Uses a deterministic naming scheme: scene_0.loading, scene_1.loading, etc.
/// </summary>
public static string GetSceneLoaderPackPath(int sceneIndex, string sceneName)
{
return Path.Combine(BuildOutputDir, $"scene_{sceneIndex}.loading");
}
/// <summary>
/// ISO output path for release builds.
/// </summary>

View File

@@ -877,6 +877,7 @@ namespace SplashEdit.EditorCode
public bool ExportAllScenes()
{
SplashBuildPaths.EnsureDirectories();
_loaderPackCache = new Dictionary<string, string>();
// Save current scene
string currentScenePath = SceneManager.GetActiveScene().path;
@@ -912,6 +913,13 @@ namespace SplashEdit.EditorCode
string outputPath = SplashBuildPaths.GetSceneSplashpackPath(i, scene.name);
exporter.ExportToPath(outputPath);
Log($"Exported '{scene.name}' → {Path.GetFileName(outputPath)}", LogType.Log);
// Export loading screen if assigned
if (exporter.LoadingScreenPrefab != null)
{
string loaderPath = SplashBuildPaths.GetSceneLoaderPackPath(i, scene.name);
ExportLoaderPack(exporter.LoadingScreenPrefab, loaderPath, i, scene.name);
}
}
catch (Exception ex)
{
@@ -934,6 +942,87 @@ namespace SplashEdit.EditorCode
return success;
}
/// <summary>
/// Cache of already-exported loader packs for deduplication.
/// Key = prefab asset GUID, Value = path of the written file.
/// If two scenes reference the same loading screen prefab, we copy the file
/// instead of regenerating it.
/// </summary>
private Dictionary<string, string> _loaderPackCache = new Dictionary<string, string>();
private void ExportLoaderPack(GameObject prefab, string outputPath, int sceneIndex, string sceneName)
{
string prefabPath = AssetDatabase.GetAssetPath(prefab);
string guid = AssetDatabase.AssetPathToGUID(prefabPath);
// Dedup: if we already exported this exact prefab, just copy the file
if (!string.IsNullOrEmpty(guid) && _loaderPackCache.TryGetValue(guid, out string cachedPath))
{
if (File.Exists(cachedPath))
{
File.Copy(cachedPath, outputPath, true);
Log($"Loading screen for '{sceneName}' → {Path.GetFileName(outputPath)} (deduped from {Path.GetFileName(cachedPath)})", LogType.Log);
return;
}
}
// Need the PSXData resolution to pass to the writer
Vector2 resolution;
bool db, vl;
List<ProhibitedArea> pa;
DataStorage.LoadData(out resolution, out db, out vl, out pa);
// Instantiate the prefab temporarily so the components are live
// (GetComponentsInChildren needs active hierarchy)
GameObject instance = (GameObject)PrefabUtility.InstantiatePrefab(prefab);
try
{
// Pack UI image textures into VRAM (same flow as PSXSceneExporter)
TextureAtlas[] atlases = null;
PSXUIImage[] uiImages = instance.GetComponentsInChildren<PSXUIImage>(true);
if (uiImages != null && uiImages.Length > 0)
{
List<PSXTexture2D> uiTextures = new List<PSXTexture2D>();
foreach (PSXUIImage img in uiImages)
{
if (img.SourceTexture != null)
{
Utils.SetTextureImporterFormat(img.SourceTexture, true);
PSXTexture2D tex = PSXTexture2D.CreateFromTexture2D(img.SourceTexture, img.BitDepth);
tex.OriginalTexture = img.SourceTexture;
img.PackedTexture = tex;
uiTextures.Add(tex);
}
}
if (uiTextures.Count > 0)
{
(Rect buffer1, Rect buffer2) = Utils.BufferForResolution(resolution, vl);
List<Rect> framebuffers = new List<Rect> { buffer1 };
if (db) framebuffers.Add(buffer2);
VRAMPacker packer = new VRAMPacker(framebuffers, pa);
var packed = packer.PackTexturesIntoVRAM(new PSXObjectExporter[0], uiTextures);
atlases = packed.atlases;
}
}
// CollectCanvasFromPrefab reads PackedTexture VRAM coords (set by packer above)
bool ok = PSXLoaderPackWriter.Write(outputPath, instance, resolution, atlases,
(msg, type) => Log(msg, type));
if (ok)
{
Log($"Loading screen for '{sceneName}' → {Path.GetFileName(outputPath)}", LogType.Log);
if (!string.IsNullOrEmpty(guid))
_loaderPackCache[guid] = outputPath;
}
}
finally
{
UnityEngine.Object.DestroyImmediate(instance);
}
}
private void WriteManifest()
{
string manifestPath = SplashBuildPaths.ManifestPath;