Somewhat fixed ui
This commit is contained in:
@@ -4,7 +4,7 @@ using SplashEdit.RuntimeCode;
|
||||
|
||||
namespace SplashEdit.EditorCode
|
||||
{
|
||||
// ─── Scene Preview Gizmos ───
|
||||
// --- Scene Preview Gizmos ---
|
||||
// These draw filled rectangles in the Scene view for WYSIWYG UI preview.
|
||||
|
||||
public static class PSXUIGizmos
|
||||
@@ -76,9 +76,8 @@ namespace SplashEdit.EditorCode
|
||||
Color fill = new Color(0, 0, 0, selected ? 0.3f : 0.1f);
|
||||
Handles.DrawSolidRectangleWithOutline(corners, fill, border);
|
||||
|
||||
// Draw text preview at actual PSX glyph size.
|
||||
// On the PS1, chainprintf renders each glyph top-left aligned at the
|
||||
// element's position — no centering. Mimic that here.
|
||||
// Pixel-perfect preview: render each glyph from the actual font bitmap
|
||||
// at PS1 scale, using advance widths for proportional positioning.
|
||||
string label = string.IsNullOrEmpty(text.DefaultText) ? "[empty]" : text.DefaultText;
|
||||
|
||||
PSXFontAsset font = text.GetEffectiveFont();
|
||||
@@ -86,39 +85,85 @@ namespace SplashEdit.EditorCode
|
||||
int glyphH = font != null ? font.GlyphHeight : 16;
|
||||
|
||||
Handles.BeginGUI();
|
||||
// Convert top-left corner (corners[1] in Unity is top-left after GetWorldCorners)
|
||||
Vector2 topLeft = HandleUtility.WorldToGUIPoint(corners[1]);
|
||||
Vector2 botRight = HandleUtility.WorldToGUIPoint(corners[3]);
|
||||
|
||||
// Calculate pixel scale: how many screen pixels represent one PSX pixel
|
||||
float rectWorldW = Vector3.Distance(corners[0], corners[3]);
|
||||
float rectScreenW = Mathf.Abs(botRight.x - topLeft.x);
|
||||
float rectW = rt.rect.width;
|
||||
float psxPixelScale = (rectW > 0.01f) ? rectScreenW / rectW : 1f;
|
||||
|
||||
float charScreenW = glyphW * psxPixelScale;
|
||||
float charScreenH = glyphH * psxPixelScale;
|
||||
int fontSize = Mathf.Clamp(Mathf.RoundToInt(charScreenH * 0.75f), 6, 72);
|
||||
|
||||
GUIStyle style = new GUIStyle(EditorStyles.label);
|
||||
style.normal.textColor = text.TextColor;
|
||||
style.alignment = TextAnchor.UpperLeft;
|
||||
style.fontSize = fontSize;
|
||||
style.wordWrap = false;
|
||||
style.clipping = TextClipping.Clip;
|
||||
style.padding = new RectOffset(0, 0, 0, 0);
|
||||
|
||||
// Render position = top-left of the rect (matching PSX chainprintf behavior)
|
||||
float guiX = Mathf.Min(topLeft.x, botRight.x);
|
||||
float guiY = Mathf.Min(topLeft.y, botRight.y);
|
||||
float guiW = Mathf.Abs(botRight.x - topLeft.x);
|
||||
float guiH = Mathf.Abs(botRight.y - topLeft.y);
|
||||
Rect guiRect = new Rect(
|
||||
Mathf.Min(topLeft.x, botRight.x),
|
||||
Mathf.Min(topLeft.y, botRight.y),
|
||||
guiW, guiH);
|
||||
|
||||
GUI.color = new Color(text.TextColor.r, text.TextColor.g, text.TextColor.b, selected ? 1f : 0.7f);
|
||||
GUI.Label(guiRect, label, style);
|
||||
GUI.color = Color.white;
|
||||
Color tintColor = text.TextColor;
|
||||
tintColor.a = selected ? 1f : 0.7f;
|
||||
|
||||
// If we have a font bitmap, render pixel-perfect from the texture
|
||||
if (font != null && font.FontTexture != null && font.SourceFont != null)
|
||||
{
|
||||
Texture2D fontTex = font.FontTexture;
|
||||
int glyphsPerRow = font.GlyphsPerRow;
|
||||
int texH = font.TextureHeight;
|
||||
float cellScreenW = glyphW * psxPixelScale;
|
||||
float cellScreenH = glyphH * psxPixelScale;
|
||||
|
||||
// Get advance widths for proportional positioning
|
||||
float cursorX = guiX;
|
||||
GUI.color = tintColor;
|
||||
foreach (char ch in label)
|
||||
{
|
||||
if (ch < 32 || ch > 126) continue;
|
||||
int charIdx = ch - 32;
|
||||
int col = charIdx % glyphsPerRow;
|
||||
int row = charIdx / glyphsPerRow;
|
||||
|
||||
float advance = glyphW; // fallback
|
||||
if (font.AdvanceWidths != null && charIdx < font.AdvanceWidths.Length)
|
||||
{
|
||||
advance = font.AdvanceWidths[charIdx];
|
||||
}
|
||||
|
||||
if (ch != ' ')
|
||||
{
|
||||
// UV rect for this glyph in the font bitmap
|
||||
float uvX = (float)(col * glyphW) / fontTex.width;
|
||||
float uvY = 1f - (float)((row + 1) * glyphH) / fontTex.height;
|
||||
float uvW = (float)glyphW / fontTex.width;
|
||||
float uvH = (float)glyphH / fontTex.height;
|
||||
|
||||
// Draw at advance width, not cell width - matches PS1 proportional rendering
|
||||
float spriteScreenW = advance * psxPixelScale;
|
||||
Rect screenRect = new Rect(cursorX, guiY, spriteScreenW, cellScreenH);
|
||||
// UV: only show the portion of the cell that the advance covers
|
||||
float uvWScaled = uvW * (advance / glyphW);
|
||||
Rect uvRect = new Rect(uvX, uvY, uvWScaled, uvH);
|
||||
|
||||
if (screenRect.xMax > guiX && screenRect.x < guiX + guiW)
|
||||
GUI.DrawTextureWithTexCoords(screenRect, fontTex, uvRect);
|
||||
}
|
||||
|
||||
cursorX += advance * psxPixelScale;
|
||||
}
|
||||
GUI.color = Color.white;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fallback: use Unity's text rendering for system font
|
||||
int fSize = Mathf.Clamp(Mathf.RoundToInt(glyphH * psxPixelScale * 0.75f), 6, 72);
|
||||
GUIStyle style = new GUIStyle(EditorStyles.label);
|
||||
style.normal.textColor = tintColor;
|
||||
style.alignment = TextAnchor.UpperLeft;
|
||||
style.fontSize = fSize;
|
||||
style.wordWrap = false;
|
||||
style.clipping = TextClipping.Clip;
|
||||
|
||||
Rect guiRect = new Rect(guiX, guiY, guiW, guiH);
|
||||
GUI.color = tintColor;
|
||||
GUI.Label(guiRect, label, style);
|
||||
GUI.color = Color.white;
|
||||
}
|
||||
Handles.EndGUI();
|
||||
}
|
||||
|
||||
@@ -259,7 +304,7 @@ namespace SplashEdit.EditorCode
|
||||
if (img.SourceTexture != null)
|
||||
{
|
||||
if (img.SourceTexture.width > 256 || img.SourceTexture.height > 256)
|
||||
EditorGUILayout.HelpBox("Texture exceeds 256×256. It will be resized during export.", MessageType.Warning);
|
||||
EditorGUILayout.HelpBox("Texture exceeds 256x256. It will be resized during export.", MessageType.Warning);
|
||||
}
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
@@ -377,31 +422,40 @@ namespace SplashEdit.EditorCode
|
||||
{
|
||||
serializedObject.Update();
|
||||
|
||||
PSXFontAsset font = (PSXFontAsset)target;
|
||||
|
||||
EditorGUILayout.LabelField("PSX Font Asset", EditorStyles.boldLabel);
|
||||
EditorGUILayout.Space(4);
|
||||
|
||||
// Source font (TTF/OTF)
|
||||
// ── Source font (TTF/OTF) ──
|
||||
EditorGUILayout.LabelField("Auto-Convert from Font", EditorStyles.miniBoldLabel);
|
||||
EditorGUILayout.PropertyField(serializedObject.FindProperty("sourceFont"), new GUIContent("Source Font (TTF/OTF)",
|
||||
"Assign a Unity Font (TrueType/OpenType). Click 'Generate Bitmap' to rasterize it."));
|
||||
"Assign a Unity Font (TrueType/OpenType). Click 'Generate Bitmap' to rasterize it.\n" +
|
||||
"Glyph cell dimensions are auto-derived from the font metrics."));
|
||||
EditorGUILayout.PropertyField(serializedObject.FindProperty("fontSize"), new GUIContent("Font Size",
|
||||
"Pixel height for rasterization. Determines glyph cell height."));
|
||||
"Pixel height for rasterization. Determines glyph cell height.\n" +
|
||||
"Glyph cell width is auto-derived from the widest character.\n" +
|
||||
"Changing this and re-generating will update both the bitmap AND the glyph dimensions."));
|
||||
|
||||
PSXFontAsset font = (PSXFontAsset)target;
|
||||
if (font.SourceFont != null)
|
||||
{
|
||||
if (GUILayout.Button("Generate Bitmap from Font"))
|
||||
EditorGUILayout.Space(2);
|
||||
if (GUILayout.Button("Generate Bitmap from Font", GUILayout.Height(28)))
|
||||
{
|
||||
Undo.RecordObject(font, "Generate PSX Font Bitmap");
|
||||
font.GenerateBitmapFromFont();
|
||||
}
|
||||
|
||||
if (font.FontTexture == null)
|
||||
EditorGUILayout.HelpBox("Click 'Generate Bitmap' to create the font texture.", MessageType.Info);
|
||||
EditorGUILayout.HelpBox(
|
||||
"Click 'Generate Bitmap' to create the font texture.\n" +
|
||||
"If generation fails, check that the font's import settings have " +
|
||||
"'Character' set to 'ASCII Default Set'.", MessageType.Info);
|
||||
}
|
||||
|
||||
EditorGUILayout.Space(8);
|
||||
|
||||
// Manual bitmap
|
||||
// ── Manual bitmap ──
|
||||
EditorGUILayout.LabelField("Manual Bitmap Source", EditorStyles.miniBoldLabel);
|
||||
EditorGUILayout.PropertyField(serializedObject.FindProperty("fontTexture"), new GUIContent("Font Texture",
|
||||
"256px wide bitmap. Glyphs in ASCII order from 0x20 (space). " +
|
||||
@@ -409,15 +463,32 @@ namespace SplashEdit.EditorCode
|
||||
|
||||
EditorGUILayout.Space(4);
|
||||
|
||||
// Glyph metrics
|
||||
// ── Glyph metrics ──
|
||||
// If using auto-convert, these are set by GenerateBitmapFromFont.
|
||||
// For manual bitmaps, the user sets them directly.
|
||||
EditorGUILayout.LabelField("Glyph Metrics", EditorStyles.miniBoldLabel);
|
||||
EditorGUILayout.PropertyField(serializedObject.FindProperty("glyphWidth"), new GUIContent("Glyph Width",
|
||||
"Width of each glyph cell in pixels."));
|
||||
EditorGUILayout.PropertyField(serializedObject.FindProperty("glyphHeight"), new GUIContent("Glyph Height",
|
||||
"Height of each glyph cell in pixels."));
|
||||
if (font.SourceFont != null && font.FontTexture != null)
|
||||
{
|
||||
// Show as read-only when auto-generated
|
||||
EditorGUI.BeginDisabledGroup(true);
|
||||
EditorGUILayout.IntField(new GUIContent("Glyph Width", "Auto-derived from font. Re-generate to change."), font.GlyphWidth);
|
||||
EditorGUILayout.IntField(new GUIContent("Glyph Height", "Auto-derived from font. Re-generate to change."), font.GlyphHeight);
|
||||
EditorGUI.EndDisabledGroup();
|
||||
EditorGUILayout.HelpBox("Glyph dimensions are auto-derived when generating from a font.\n" +
|
||||
"Change the Font Size slider and re-generate to adjust.", MessageType.Info);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Editable for manual bitmap workflow
|
||||
EditorGUILayout.PropertyField(serializedObject.FindProperty("glyphWidth"), new GUIContent("Glyph Width",
|
||||
"Width of each glyph cell in pixels. Must divide 256 evenly (4, 8, 16, or 32)."));
|
||||
EditorGUILayout.PropertyField(serializedObject.FindProperty("glyphHeight"), new GUIContent("Glyph Height",
|
||||
"Height of each glyph cell in pixels."));
|
||||
}
|
||||
|
||||
EditorGUILayout.Space(4);
|
||||
|
||||
// ── Layout info ──
|
||||
int glyphsPerRow = font.GlyphsPerRow;
|
||||
int rowCount = font.RowCount;
|
||||
int totalH = font.TextureHeight;
|
||||
@@ -427,15 +498,42 @@ namespace SplashEdit.EditorCode
|
||||
$"Layout: {glyphsPerRow} glyphs/row, {rowCount} rows\n" +
|
||||
$"Texture: 256 x {totalH} pixels (4bpp)\n" +
|
||||
$"VRAM: {vramBytes} bytes ({vramBytes / 1024f:F1} KB)\n" +
|
||||
$"Glyph size: {font.GlyphWidth} x {font.GlyphHeight}",
|
||||
$"Glyph cell: {font.GlyphWidth} x {font.GlyphHeight}",
|
||||
MessageType.Info);
|
||||
|
||||
// Show advance width status
|
||||
if (font.AdvanceWidths != null && font.AdvanceWidths.Length >= 95)
|
||||
{
|
||||
int minAdv = 255, maxAdv = 0;
|
||||
for (int i = 1; i < 95; i++) // skip space
|
||||
{
|
||||
if (font.AdvanceWidths[i] < minAdv) minAdv = font.AdvanceWidths[i];
|
||||
if (font.AdvanceWidths[i] > maxAdv) maxAdv = font.AdvanceWidths[i];
|
||||
}
|
||||
EditorGUILayout.HelpBox(
|
||||
$"Advance widths: {minAdv}-{maxAdv}px (proportional spacing stored)",
|
||||
MessageType.Info);
|
||||
}
|
||||
else if (font.FontTexture != null)
|
||||
{
|
||||
EditorGUILayout.HelpBox(
|
||||
"No advance widths stored. Click 'Generate Bitmap' to compute them.",
|
||||
MessageType.Warning);
|
||||
}
|
||||
|
||||
// ── Validation ──
|
||||
if (font.FontTexture != null)
|
||||
{
|
||||
if (font.FontTexture.width != 256)
|
||||
EditorGUILayout.HelpBox($"Font texture must be 256 pixels wide (currently {font.FontTexture.width}).", MessageType.Error);
|
||||
|
||||
if (256 % font.GlyphWidth != 0)
|
||||
EditorGUILayout.HelpBox($"Glyph width ({font.GlyphWidth}) must divide 256 evenly. " +
|
||||
"Valid values: 4, 8, 16, 32.", MessageType.Error);
|
||||
|
||||
// Show preview
|
||||
EditorGUILayout.Space(4);
|
||||
EditorGUILayout.LabelField("Preview", EditorStyles.miniBoldLabel);
|
||||
Rect previewRect = EditorGUILayout.GetControlRect(false, 64);
|
||||
GUI.DrawTexture(previewRect, font.FontTexture, ScaleMode.ScaleToFit);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user