cleanup
This commit is contained in:
@@ -1,5 +1,8 @@
|
||||
namespace SplashEdit.RuntimeCode
|
||||
{
|
||||
|
||||
// I tried to make this and now I'm scared to delete this.
|
||||
|
||||
/// <summary>
|
||||
/// Implemented by MonoBehaviours that participate in the PSX scene export pipeline.
|
||||
/// Each exportable object converts its Unity representation into PSX-ready data.
|
||||
|
||||
@@ -137,53 +137,55 @@ namespace SplashEdit.RuntimeCode
|
||||
private class Node
|
||||
{
|
||||
public Vector3 Point;
|
||||
public int Index;
|
||||
public Node Left, Right;
|
||||
}
|
||||
|
||||
private Node root;
|
||||
private List<Vector3> points;
|
||||
|
||||
public KDTree(List<Vector3> points)
|
||||
{
|
||||
this.points = points;
|
||||
root = Build(points, 0);
|
||||
var indexed = new List<(Vector3 point, int index)>();
|
||||
for (int i = 0; i < points.Count; i++)
|
||||
indexed.Add((points[i], i));
|
||||
root = Build(indexed, 0);
|
||||
}
|
||||
|
||||
private Node Build(List<Vector3> points, int depth)
|
||||
private Node Build(List<(Vector3 point, int index)> items, int depth)
|
||||
{
|
||||
if (points.Count == 0) return null;
|
||||
if (items.Count == 0) return null;
|
||||
|
||||
int axis = depth % 3;
|
||||
points.Sort((a, b) => a[axis].CompareTo(b[axis]));
|
||||
int median = points.Count / 2;
|
||||
items.Sort((a, b) => a.point[axis].CompareTo(b.point[axis]));
|
||||
int median = items.Count / 2;
|
||||
|
||||
return new Node
|
||||
{
|
||||
Point = points[median],
|
||||
Left = Build(points.Take(median).ToList(), depth + 1),
|
||||
Right = Build(points.Skip(median + 1).ToList(), depth + 1)
|
||||
Point = items[median].point,
|
||||
Index = items[median].index,
|
||||
Left = Build(items.Take(median).ToList(), depth + 1),
|
||||
Right = Build(items.Skip(median + 1).ToList(), depth + 1)
|
||||
};
|
||||
}
|
||||
|
||||
public int FindNearestIndex(Vector3 target)
|
||||
{
|
||||
Vector3 nearest = FindNearest(root, target, 0, root.Point);
|
||||
return points.IndexOf(nearest);
|
||||
return FindNearest(root, target, 0, root).Index;
|
||||
}
|
||||
|
||||
private Vector3 FindNearest(Node node, Vector3 target, int depth, Vector3 best)
|
||||
private Node FindNearest(Node node, Vector3 target, int depth, Node best)
|
||||
{
|
||||
if (node == null) return best;
|
||||
|
||||
if (Vector3.SqrMagnitude(target - node.Point) < Vector3.SqrMagnitude(target - best))
|
||||
best = node.Point;
|
||||
if (Vector3.SqrMagnitude(target - node.Point) < Vector3.SqrMagnitude(target - best.Point))
|
||||
best = node;
|
||||
|
||||
int axis = depth % 3;
|
||||
Node first = target[axis] < node.Point[axis] ? node.Left : node.Right;
|
||||
Node second = first == node.Left ? node.Right : node.Left;
|
||||
|
||||
best = FindNearest(first, target, depth + 1, best);
|
||||
if (Mathf.Pow(target[axis] - node.Point[axis], 2) < Vector3.SqrMagnitude(target - best))
|
||||
if (Mathf.Pow(target[axis] - node.Point[axis], 2) < Vector3.SqrMagnitude(target - best.Point))
|
||||
best = FindNearest(second, target, depth + 1, best);
|
||||
|
||||
return best;
|
||||
|
||||
@@ -2,6 +2,7 @@ using UnityEngine;
|
||||
|
||||
namespace SplashEdit.RuntimeCode
|
||||
{
|
||||
[Icon("Packages/net.psxsplash.splashedit/Icons/LuaFile.png")]
|
||||
public class LuaFile : ScriptableObject
|
||||
{
|
||||
[SerializeField] private string luaScript;
|
||||
|
||||
@@ -4,8 +4,6 @@ namespace SplashEdit.RuntimeCode
|
||||
{
|
||||
/// <summary>
|
||||
/// Pre-converted audio clip data ready for splashpack serialization.
|
||||
/// Populated by the Editor (PSXSceneExporter) so Runtime code never
|
||||
/// touches PSXAudioConverter.
|
||||
/// </summary>
|
||||
public struct AudioClipExport
|
||||
{
|
||||
@@ -18,9 +16,10 @@ namespace SplashEdit.RuntimeCode
|
||||
/// <summary>
|
||||
/// Attach to a GameObject to include an audio clip in the PS1 build.
|
||||
/// At export time, the AudioClip is converted to SPU ADPCM and packed
|
||||
/// into the splashpack binary. Use Audio.Play(clipIndex) from Lua.
|
||||
/// into the splashpack for runtime loading.
|
||||
/// </summary>
|
||||
[AddComponentMenu("PSX/Audio Clip")]
|
||||
[Icon("Packages/net.psxsplash.splashedit/Icons/PSXAudioClip.png")]
|
||||
public class PSXAudioClip : MonoBehaviour
|
||||
{
|
||||
[Tooltip("Name used to identify this clip in Lua (Audio.Play(\"name\"))." )]
|
||||
|
||||
@@ -17,6 +17,7 @@ namespace SplashEdit.RuntimeCode
|
||||
[DisallowMultipleComponent]
|
||||
[ExecuteAlways]
|
||||
[AddComponentMenu("PSX/UI/PSX Canvas")]
|
||||
[Icon("Packages/net.psxsplash.splashedit/Icons/PSXCanvas.png")]
|
||||
public class PSXCanvas : MonoBehaviour
|
||||
{
|
||||
[Tooltip("Name used to reference this canvas from Lua (max 24 chars). Must be unique per scene.")]
|
||||
|
||||
@@ -10,6 +10,7 @@ namespace SplashEdit.RuntimeCode
|
||||
/// all PSXCutsceneClip assets via Resources.FindObjectsOfTypeAll.
|
||||
/// </summary>
|
||||
[CreateAssetMenu(fileName = "NewCutscene", menuName = "PSX/Cutscene Clip", order = 100)]
|
||||
[Icon("Packages/net.psxsplash.splashedit/Icons/PSXCutsceneClip.png")]
|
||||
public class PSXCutsceneClip : ScriptableObject
|
||||
{
|
||||
[Tooltip("Name used to reference this cutscene from Lua (max 24 chars). Must be unique per scene.")]
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace SplashEdit.RuntimeCode
|
||||
{
|
||||
|
||||
[CreateAssetMenu(fileName = "PSXData", menuName = "PSXSplash/PS1 Project Data")]
|
||||
[Icon("Packages/net.psxsplash.splashedit/Icons/PSXData.png")]
|
||||
public class PSXData : ScriptableObject
|
||||
{
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ using UnityEditor;
|
||||
namespace SplashEdit.RuntimeCode
|
||||
{
|
||||
[CreateAssetMenu(fileName = "New PSXFont", menuName = "PSX/Font Asset")]
|
||||
[Icon("Packages/net.psxsplash.splashedit/Icons/PSXFontAsset.png")]
|
||||
public class PSXFontAsset : ScriptableObject
|
||||
{
|
||||
[Header("Source - Option A: TrueType/OTF Font")]
|
||||
@@ -154,7 +155,6 @@ namespace SplashEdit.RuntimeCode
|
||||
if (validCount > 0)
|
||||
{
|
||||
workingSize = 0;
|
||||
Debug.Log("PSXFontAsset: Using font's native size for character info.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -273,11 +273,6 @@ namespace SplashEdit.RuntimeCode
|
||||
// This makes the native advance widths match the bitmap exactly for
|
||||
// proportional rendering. Characters wider than cell get clipped (rare).
|
||||
|
||||
Debug.Log($"PSXFontAsset: Cell {glyphWidth}x{glyphHeight}, {glyphsPerRow}/row, " +
|
||||
$"{rowCount} rows, texture {texW}x{texH} " +
|
||||
$"(measured: {measuredMaxW}x{measuredMaxH}, " +
|
||||
$"ascender={maxAscender}, descender={maxDescender}, vScale={vScale:F2})");
|
||||
|
||||
// ── Step 5: Render glyphs into grid ──
|
||||
// Each glyph is LEFT-ALIGNED at native width for proportional rendering.
|
||||
// The advance widths from CharacterInfo match native glyph proportions.
|
||||
@@ -376,8 +371,6 @@ namespace SplashEdit.RuntimeCode
|
||||
return;
|
||||
}
|
||||
|
||||
Debug.Log($"PSXFontAsset: Rendered {renderedCount}/95 glyphs.");
|
||||
|
||||
// Store advance widths from the same CharacterInfo used for rendering.
|
||||
// This guarantees advances match the bitmap glyphs exactly.
|
||||
storedAdvanceWidths = new byte[96];
|
||||
@@ -424,7 +417,6 @@ namespace SplashEdit.RuntimeCode
|
||||
fontTexture = AssetDatabase.LoadAssetAtPath<Texture2D>(texPath);
|
||||
EditorUtility.SetDirty(this);
|
||||
AssetDatabase.SaveAssets();
|
||||
Debug.Log($"PSXFontAsset: Saved {texW}x{texH} bitmap at {texPath}");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ namespace SplashEdit.RuntimeCode
|
||||
/// the onInteract Lua event fires.
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(PSXObjectExporter))]
|
||||
[Icon("Packages/net.psxsplash.splashedit/Icons/PSXInteractable.png")]
|
||||
public class PSXInteractable : MonoBehaviour
|
||||
{
|
||||
[Header("Interaction Settings")]
|
||||
|
||||
@@ -76,6 +76,8 @@ namespace SplashEdit.RuntimeCode
|
||||
finalColor += lightContribution;
|
||||
}
|
||||
|
||||
// Clamp to 0.8 to leave headroom for PS1 2x color blending mode,
|
||||
// which doubles vertex colors. Without this cap, bright areas would clip.
|
||||
finalColor.r = Mathf.Clamp(finalColor.r, 0.0f, 0.8f);
|
||||
finalColor.g = Mathf.Clamp(finalColor.g, 0.0f, 0.8f);
|
||||
finalColor.b = Mathf.Clamp(finalColor.b, 0.0f, 0.8f);
|
||||
|
||||
@@ -83,9 +83,6 @@ namespace SplashEdit.RuntimeCode
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Creates a PSXMesh from a Unity Mesh by converting its vertices, normals, UVs, and applying shading.
|
||||
/// </summary>
|
||||
/// <summary>
|
||||
/// Creates a PSXMesh from a Unity Renderer by extracting its mesh and materials.
|
||||
/// </summary>
|
||||
@@ -203,12 +200,12 @@ namespace SplashEdit.RuntimeCode
|
||||
/// Converts a Unity vertex into a PSXVertex by applying fixed-point conversion, shading, and UV mapping.
|
||||
/// </summary>
|
||||
/// <param name="vertex">The position of the vertex.</param>
|
||||
/// <param name="GTEScaling">World-to-GTE scaling factor.</param>
|
||||
/// <param name="normal">The normal vector at the vertex.</param>
|
||||
/// <param name="uv">Texture coordinates for the vertex.</param>
|
||||
/// <param name="lightDir">The light direction used for shading calculations.</param>
|
||||
/// <param name="lightColor">The color of the light affecting the vertex.</param>
|
||||
/// <param name="textureWidth">Width of the texture for UV scaling.</param>
|
||||
/// <param name="textureHeight">Height of the texture for UV scaling.</param>
|
||||
/// <param name="color">Pre-computed vertex color from lighting.</param>
|
||||
/// <returns>A PSXVertex with converted coordinates, normals, UVs, and color.</returns>
|
||||
private static PSXVertex ConvertToPSXVertex(Vector3 vertex, float GTEScaling, Vector3 normal, Vector2 uv, int? textureWidth, int? textureHeight, Color color)
|
||||
{
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace SplashEdit.RuntimeCode
|
||||
|
||||
[RequireComponent(typeof(MeshFilter))]
|
||||
[RequireComponent(typeof(MeshRenderer))]
|
||||
[Icon("Packages/net.psxsplash.splashedit/Icons/PSXObjectExporter.png")]
|
||||
public class PSXObjectExporter : MonoBehaviour, IPSXExportable
|
||||
{
|
||||
public LuaFile LuaFile => luaFile;
|
||||
|
||||
@@ -4,6 +4,7 @@ using UnityEngine.Serialization;
|
||||
|
||||
namespace SplashEdit.RuntimeCode
|
||||
{
|
||||
[Icon("Packages/net.psxsplash.splashedit/Icons/PSXPlayer.png")]
|
||||
public class PSXPlayer : MonoBehaviour
|
||||
{
|
||||
[Header("Player Dimensions")]
|
||||
|
||||
@@ -11,6 +11,7 @@ namespace SplashEdit.RuntimeCode
|
||||
/// This is independent of the navigation portal system (PSXNavRegion).
|
||||
/// </summary>
|
||||
[ExecuteInEditMode]
|
||||
[Icon("Packages/net.psxsplash.splashedit/Icons/PSXPortalLink.png")]
|
||||
public class PSXPortalLink : MonoBehaviour
|
||||
{
|
||||
[Tooltip("First room connected by this portal.")]
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace SplashEdit.RuntimeCode
|
||||
/// This is independent of the navregion/portal system used for navigation.
|
||||
/// </summary>
|
||||
[ExecuteInEditMode]
|
||||
[Icon("Packages/net.psxsplash.splashedit/Icons/PSXRoom.png")]
|
||||
public class PSXRoom : MonoBehaviour
|
||||
{
|
||||
[Tooltip("Optional display name for this room (used in editor gizmos).")]
|
||||
|
||||
@@ -16,6 +16,7 @@ namespace SplashEdit.RuntimeCode
|
||||
}
|
||||
|
||||
[ExecuteInEditMode]
|
||||
[Icon("Packages/net.psxsplash.splashedit/Icons/PSXSceneExporter.png")]
|
||||
public class PSXSceneExporter : MonoBehaviour
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -7,7 +7,7 @@ using UnityEngine;
|
||||
namespace SplashEdit.RuntimeCode
|
||||
{
|
||||
/// <summary>
|
||||
/// Pure binary serializer for the splashpack v8 format.
|
||||
/// Pure binary serializer for the splashpack v16 format.
|
||||
/// All I/O extracted from PSXSceneExporter so the MonoBehaviour stays thin.
|
||||
/// </summary>
|
||||
public static class PSXSceneWriter
|
||||
@@ -72,7 +72,7 @@ namespace SplashEdit.RuntimeCode
|
||||
// ═══════════════════════════════════════════════════════════════
|
||||
|
||||
/// <summary>
|
||||
/// Serialize the scene to a splashpack v8 binary file.
|
||||
/// Serialize the scene to a splashpack v16 binary file.
|
||||
/// </summary>
|
||||
/// <param name="path">Absolute file path to write.</param>
|
||||
/// <param name="scene">Pre-built scene data.</param>
|
||||
@@ -148,13 +148,13 @@ namespace SplashEdit.RuntimeCode
|
||||
writer.Write((ushort)clutCount);
|
||||
writer.Write((ushort)colliderCount);
|
||||
writer.Write((ushort)scene.interactables.Length);
|
||||
writer.Write((ushort)PSXTrig.ConvertCoordinateToPSX(scene.playerPos.x, gte));
|
||||
writer.Write((ushort)PSXTrig.ConvertCoordinateToPSX(-scene.playerPos.y, gte));
|
||||
writer.Write((ushort)PSXTrig.ConvertCoordinateToPSX(scene.playerPos.z, gte));
|
||||
writer.Write(PSXTrig.ConvertCoordinateToPSX(scene.playerPos.x, gte));
|
||||
writer.Write(PSXTrig.ConvertCoordinateToPSX(-scene.playerPos.y, gte));
|
||||
writer.Write(PSXTrig.ConvertCoordinateToPSX(scene.playerPos.z, gte));
|
||||
|
||||
writer.Write((ushort)PSXTrig.ConvertToFixed12(scene.playerRot.eulerAngles.x * Mathf.Deg2Rad));
|
||||
writer.Write((ushort)PSXTrig.ConvertToFixed12(scene.playerRot.eulerAngles.y * Mathf.Deg2Rad));
|
||||
writer.Write((ushort)PSXTrig.ConvertToFixed12(scene.playerRot.eulerAngles.z * Mathf.Deg2Rad));
|
||||
writer.Write(PSXTrig.ConvertToFixed12(scene.playerRot.eulerAngles.x * Mathf.Deg2Rad));
|
||||
writer.Write(PSXTrig.ConvertToFixed12(scene.playerRot.eulerAngles.y * Mathf.Deg2Rad));
|
||||
writer.Write(PSXTrig.ConvertToFixed12(scene.playerRot.eulerAngles.z * Mathf.Deg2Rad));
|
||||
|
||||
writer.Write((ushort)PSXTrig.ConvertCoordinateToPSX(scene.playerHeight, gte));
|
||||
|
||||
@@ -475,6 +475,7 @@ namespace SplashEdit.RuntimeCode
|
||||
writer.Write((ushort)0); // padding
|
||||
|
||||
// Sentinel tpage = 0xFFFF marks untextured
|
||||
// haha funny word. Sentinel, sentinel, sentinel. I could keep saying it forever.
|
||||
writer.Write((ushort)0xFFFF);
|
||||
writer.Write((ushort)0);
|
||||
writer.Write((ushort)0);
|
||||
@@ -828,6 +829,9 @@ namespace SplashEdit.RuntimeCode
|
||||
// ══════════════════════════════════════════════════════
|
||||
// DEAD ZONE — pixel/audio bulk data (freed after VRAM/SPU upload)
|
||||
// Everything written after this point is not needed at runtime.
|
||||
// You may be asking why we don't just put pixel/audio data in separate files
|
||||
// or why don't we put this data at the end of the file to begin with. The answer is
|
||||
// Very simple and I'm going to tell it to you right now... OH GOD I FORGOT TO TURN OFF THE STOVE (runs away)
|
||||
// ══════════════════════════════════════════════════════
|
||||
AlignToFourBytes(writer);
|
||||
long pixelDataStart = writer.BaseStream.Position;
|
||||
|
||||
@@ -252,9 +252,9 @@ namespace SplashEdit.RuntimeCode
|
||||
if (BitDepth == PSXBPP.TEX_16BIT)
|
||||
{
|
||||
|
||||
for (int y = 0; y < Width; y++)
|
||||
for (int y = 0; y < Height; y++)
|
||||
{
|
||||
for (int x = 0; x < Height; x++)
|
||||
for (int x = 0; x < Width; x++)
|
||||
{
|
||||
tex.SetPixel(x, Height - 1 - y, ImageData[x, y].GetUnityColor());
|
||||
}
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
namespace SplashEdit.RuntimeCode
|
||||
{
|
||||
/// <summary>
|
||||
/// Cutscene track types. Must match the C++ TrackType enum in cutscene.hh.
|
||||
/// </summary>
|
||||
public enum PSXTrackType : byte
|
||||
{
|
||||
CameraPosition = 0,
|
||||
@@ -10,7 +7,6 @@ namespace SplashEdit.RuntimeCode
|
||||
ObjectPosition = 2,
|
||||
ObjectRotationY = 3,
|
||||
ObjectActive = 4,
|
||||
// UI track types (v13+)
|
||||
UICanvasVisible = 5,
|
||||
UIElementVisible = 6,
|
||||
UIProgress = 7,
|
||||
|
||||
@@ -2,6 +2,7 @@ using UnityEngine;
|
||||
|
||||
namespace SplashEdit.RuntimeCode
|
||||
{
|
||||
[Icon("Packages/net.psxsplash.splashedit/Icons/PSXTriggerBox.png")]
|
||||
public class PSXTriggerBox : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private Vector3 size = Vector3.one;
|
||||
|
||||
@@ -10,6 +10,7 @@ namespace SplashEdit.RuntimeCode
|
||||
[RequireComponent(typeof(RectTransform))]
|
||||
[DisallowMultipleComponent]
|
||||
[AddComponentMenu("PSX/UI/PSX UI Box")]
|
||||
[Icon("Packages/net.psxsplash.splashedit/Icons/PSXUIBox.png")]
|
||||
public class PSXUIBox : MonoBehaviour
|
||||
{
|
||||
[Tooltip("Name used to reference this element from Lua (max 24 chars).")]
|
||||
|
||||
@@ -10,6 +10,7 @@ namespace SplashEdit.RuntimeCode
|
||||
[RequireComponent(typeof(RectTransform))]
|
||||
[DisallowMultipleComponent]
|
||||
[AddComponentMenu("PSX/UI/PSX UI Image")]
|
||||
[Icon("Packages/net.psxsplash.splashedit/Icons/PSXUIImage.png")]
|
||||
public class PSXUIImage : MonoBehaviour
|
||||
{
|
||||
[Tooltip("Name used to reference this element from Lua (max 24 chars).")]
|
||||
|
||||
@@ -10,6 +10,7 @@ namespace SplashEdit.RuntimeCode
|
||||
[RequireComponent(typeof(RectTransform))]
|
||||
[DisallowMultipleComponent]
|
||||
[AddComponentMenu("PSX/UI/PSX UI Progress Bar")]
|
||||
[Icon("Packages/net.psxsplash.splashedit/Icons/PSXUIProgressBar.png")]
|
||||
public class PSXUIProgressBar : MonoBehaviour
|
||||
{
|
||||
[Tooltip("Name used to reference this element from Lua (max 24 chars).")]
|
||||
|
||||
@@ -10,6 +10,7 @@ namespace SplashEdit.RuntimeCode
|
||||
[RequireComponent(typeof(RectTransform))]
|
||||
[DisallowMultipleComponent]
|
||||
[AddComponentMenu("PSX/UI/PSX UI Text")]
|
||||
[Icon("Packages/net.psxsplash.splashedit/Icons/PSXUIText.png")]
|
||||
public class PSXUIText : MonoBehaviour
|
||||
{
|
||||
[Tooltip("Name used to reference this element from Lua (max 24 chars).")]
|
||||
|
||||
@@ -222,16 +222,16 @@ namespace SplashEdit.RuntimeCode
|
||||
{
|
||||
if (bvh == null) return 0;
|
||||
// BVH nodes: each node has AABB (24 bytes) + child/tri info (8 bytes) = 32 bytes
|
||||
// Triangle refs: 2 bytes each (uint16)
|
||||
return (long)bvh.NodeCount * 32 + (long)bvh.TriangleRefCount * 2;
|
||||
// Triangle refs: 4 bytes each (uint32)
|
||||
return (long)bvh.NodeCount * 32 + (long)bvh.TriangleRefCount * 4;
|
||||
}
|
||||
|
||||
private static long EstimateCollisionSize(PSXCollisionExporter collision)
|
||||
{
|
||||
if (collision == null || collision.MeshCount == 0) return 0;
|
||||
// Each collision mesh header: AABB + triangle count (28 bytes)
|
||||
// Each collision triangle: 3 vertices * 6 bytes = 18 bytes + normal 6 bytes = 24 bytes
|
||||
return (long)collision.MeshCount * 28 + (long)collision.TriangleCount * 24;
|
||||
// Each collision mesh header: AABB (24) + tri count (2) + flags (2) + offset (4) = 32 bytes
|
||||
// Each collision triangle: 3 verts * 12 bytes + normal 12 bytes + flags 4 bytes = 52 bytes
|
||||
return (long)collision.MeshCount * 32 + (long)collision.TriangleCount * 52;
|
||||
}
|
||||
|
||||
private static long EstimateNavRegionSize(PSXNavRegionBuilder nav)
|
||||
|
||||
@@ -321,7 +321,7 @@ namespace SplashEdit.RuntimeCode
|
||||
// Iterate over possible CLUT positions in VRAM.
|
||||
for (ushort x = 0; x < VramWidth; x += 16)
|
||||
{
|
||||
for (ushort y = 0; y <= VramHeight; y++)
|
||||
for (ushort y = 0; y < VramHeight; y++)
|
||||
{
|
||||
var candidate = new Rect(x, y, clutWidth, clutHeight);
|
||||
if (IsPlacementValid(candidate))
|
||||
|
||||
@@ -331,6 +331,30 @@ namespace SplashEdit.RuntimeCode
|
||||
{
|
||||
private static int MaxTextureSize => 256;
|
||||
|
||||
/// <summary>
|
||||
/// If a directory contains exactly one subdirectory (common after archive extraction),
|
||||
/// flatten its contents up one level and remove the nested directory.
|
||||
/// </summary>
|
||||
public static void FixNestedDirectory(string dir)
|
||||
{
|
||||
var subdirs = System.IO.Directory.GetDirectories(dir);
|
||||
if (subdirs.Length == 1)
|
||||
{
|
||||
string nested = subdirs[0];
|
||||
foreach (string file in System.IO.Directory.GetFiles(nested))
|
||||
{
|
||||
string dest = System.IO.Path.Combine(dir, System.IO.Path.GetFileName(file));
|
||||
if (!System.IO.File.Exists(dest)) System.IO.File.Move(file, dest);
|
||||
}
|
||||
foreach (string sub in System.IO.Directory.GetDirectories(nested))
|
||||
{
|
||||
string dest = System.IO.Path.Combine(dir, System.IO.Path.GetFileName(sub));
|
||||
if (!System.IO.Directory.Exists(dest)) System.IO.Directory.Move(sub, dest);
|
||||
}
|
||||
try { System.IO.Directory.Delete(nested, true); } catch { }
|
||||
}
|
||||
}
|
||||
|
||||
public static (Rect, Rect) BufferForResolution(Vector2 selectedResolution, bool verticalLayout, Vector2 offset = default)
|
||||
{
|
||||
if (offset == default)
|
||||
|
||||
Reference in New Issue
Block a user