using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using AIGame.EditorTools;
using Newtonsoft.Json.Linq;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
/// Pipeline-only migration and verification of the Common nine-slice controls.
public static class FixUiNineSlice
{
static string Repo => Directory.GetParent(Application.dataPath).Parent.FullName;
static readonly string[] Names = { "UI_MainHUD", "UI_ConfirmDialog" };
public static string Apply()
{
if (EditorApplication.isPlayingOrWillChangePlaymode) throw new Exception("Use Edit Mode.");
int changed = UiSpriteNineSliceRules.ApplyExisting();
foreach (string name in Names)
{
string path = Path.Combine(Repo, "Doc/UIPrefabCreater", name + ".json");
if (string.IsNullOrEmpty(JsonUIPrefabBuilder.BuildFromJsonFile(path)))
throw new Exception("Prefab build failed: " + name);
}
return "Updated " + changed + " standard control imports; rebuilt 2 JSON UI prefabs. " + Verify();
}
public static string Verify()
{
int checks = 0, controls = 0, slicedImages = 0, states = 0;
Action check = (ok, message) => { if (!ok) throw new Exception(message); checks++; };
var scene = EditorSceneManager.NewPreviewScene();
try
{
foreach (string guid in AssetDatabase.FindAssets("t:Texture2D", new[] { "Assets/Bundles/UI/Texture/Common" }))
{
string path = AssetDatabase.GUIDToAssetPath(guid);
if (!UiSpriteNineSliceRules.IsStandardControl(path)) continue;
controls++;
var importer = (TextureImporter)AssetImporter.GetAtPath(path);
importer.GetSourceTextureWidthAndHeight(out int width, out int height);
var sprite = AssetDatabase.LoadAssetAtPath(path);
check(sprite != null && sprite.border == UiSpriteNineSliceRules.GetBorder(path, width, height), "Border mismatch: " + path);
var settings = new TextureImporterSettings(); importer.ReadTextureSettings(settings);
check(settings.spriteMeshType == SpriteMeshType.FullRect, "Not Full Rect: " + path);
check(sprite.border.x > 0 && sprite.border.y > 0 && sprite.border.z > 0 && sprite.border.w > 0, "Empty border: " + path);
check(sprite.border.x + sprite.border.z < sprite.rect.width && sprite.border.y + sprite.border.w < sprite.rect.height, "No stretchable center: " + path);
var probeGo = new GameObject("NineSliceProbe", typeof(RectTransform), typeof(NineSliceProbe));
SceneManager.MoveGameObjectToScene(probeGo, scene);
try
{
var image = probeGo.GetComponent();
image.sprite = sprite; image.type = Image.Type.Sliced;
foreach (Vector2 size in new[] { sprite.rect.size, sprite.rect.size * 2f, sprite.rect.size * new Vector2(3f, 1.25f) })
{
image.rectTransform.sizeDelta = size;
using (var vh = new VertexHelper())
{
image.Populate(vh);
var vertices = new List(); vh.GetUIVertexStream(vertices);
var x = vertices.Select(v => v.position.x).Distinct().OrderBy(v => v).ToArray();
var y = vertices.Select(v => v.position.y).Distinct().OrderBy(v => v).ToArray();
check(x.Length == 4 && y.Length == 4, "Not a nine-slice mesh: " + path);
check(Mathf.Abs(x[1] - x[0] - sprite.border.x) < .01f && Mathf.Abs(x[3] - x[2] - sprite.border.z) < .01f
&& Mathf.Abs(y[1] - y[0] - sprite.border.y) < .01f && Mathf.Abs(y[3] - y[2] - sprite.border.w) < .01f,
"Stretched corner borders: " + path);
}
}
}
finally { UnityEngine.Object.DestroyImmediate(probeGo); }
}
check(controls == 26, "Expected 26 standard control sprites, found " + controls);
foreach (string name in Names)
{
string json = Path.Combine(Repo, "Doc/UIPrefabCreater", name + ".json");
check(JsonUIPrefabBuilder.Validate(json).Ok, "Schema validation failed: " + name);
var prefab = AssetDatabase.LoadAssetAtPath("Assets/Bundles/UI/Prefab/" + name + ".prefab");
foreach (var image in prefab.GetComponentsInChildren(true))
{
if (image.sprite == null || !UiSpriteNineSliceRules.IsStandardControl(AssetDatabase.GetAssetPath(image.sprite))) continue;
slicedImages++;
check(image.type == Image.Type.Sliced && image.hasBorder, "Prefab nine-slice missing: " + name + "/" + image.name);
}
foreach (var button in prefab.GetComponentsInChildren