Files

133 lines
9.1 KiB
C#

using System;
using System.IO;
using AIGame.EditorTools;
using AOT.Editor.YooAssetTools;
using UnityEditor;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using System.Collections.Generic;
public static class IntegrateHomeCamp
{
public static string Status() => "frame=" + Time.frameCount + " paused=" + EditorApplication.isPaused + " background=" + Application.runInBackground;
public static string ExplorerStatus()
{
var presenter = UnityEngine.Object.FindObjectOfType<HotUpdate.UI.HomeExplorerPresenter>();
var stage = GameObject.Find("HomeExplorerStage");
if (!stage) return "No explorer stage";
var animator = stage.GetComponentInChildren<Animator>(true);
return "ready=" + (presenter && presenter.Ready) + " animator=" + (animator != null) + " controller=" + (animator && animator.runtimeAnimatorController ? animator.runtimeAnimatorController.name : "null") + " avatar=" + (animator && animator.avatar ? animator.avatar.name : "null");
}
public static string EnablePreviewFrames() { Application.runInBackground = true; return Status(); }
public static async System.Threading.Tasks.Task<string> CheckArtManifest()
{
if (!EditorApplication.isPlaying) throw new InvalidOperationException("Play Mode required");
if (!YooAsset.YooAssets.IsInitialized) YooAsset.YooAssets.Initialize();
if (!YooAsset.YooAssets.TryGetPackage("Art", out var package)) package = YooAsset.YooAssets.CreatePackage("Art");
var build = YooAsset.EditorSimulateBuildInvoker.Build("Art", (int)YooAsset.EBundleType.VirtualAssetBundle);
var init = package.InitializePackageAsync(new YooAsset.EditorSimulateModeOptions {
EditorFileSystemParameters = YooAsset.FileSystemParameters.CreateDefaultEditorFileSystemParameters(build.PackageRootDirectory)
});
await init;
if (init.Status != YooAsset.EOperationStatus.Succeeded) throw new InvalidOperationException(init.Error);
var version = package.RequestPackageVersionAsync(); await version;
if (version.Status != YooAsset.EOperationStatus.Succeeded) throw new InvalidOperationException(version.Error);
var manifest = package.LoadPackageManifestAsync(new YooAsset.LoadPackageManifestOptions(version.PackageVersion, 60)); await manifest;
if (manifest.Status != YooAsset.EOperationStatus.Succeeded) throw new InvalidOperationException(manifest.Error);
if (!package.IsLocationValid("HomeCamp")) throw new InvalidOperationException("HomeCamp missing from Art manifest");
return "PASS simulated Art manifest resolves HomeCamp";
}
public static async System.Threading.Tasks.Task<string> CheckArtSceneLoad()
{
var manager = HotUpdate.UI.UiManager.Instance;
var oldHud = manager.Get("UI_MainHUD");
manager.Close("UI_MainHUD", true);
for (int i = 0; i < 100 && UnityEngine.SceneManagement.SceneManager.GetSceneByPath("Assets/Bundles/Scenes/Town/HomeCamp/HomeCamp.unity").isLoaded; i++)
await System.Threading.Tasks.Task.Delay(50);
GameObject hud = null;
manager.StartCoroutine(manager.OpenAsync("UI_MainHUD", loaded => hud = loaded));
for (int i = 0; i < 200 && !hud; i++) await System.Threading.Tasks.Task.Delay(50);
if (!hud) throw new InvalidOperationException("HUD reload failed");
var view = hud.GetComponent<HotUpdate.UI.MainHudView>() ?? hud.AddComponent<HotUpdate.UI.MainHudView>();
view.Bind();
for (int i = 0; i < 200 && (!hud || !hud.GetComponentInChildren<HotUpdate.UI.HomeCampPresenter>(true) || !hud.GetComponentInChildren<HotUpdate.UI.HomeCampPresenter>(true).Ready); i++)
await System.Threading.Tasks.Task.Delay(50);
var presenter = hud.GetComponentInChildren<HotUpdate.UI.HomeCampPresenter>(true);
var field = typeof(HotUpdate.UI.HomeCampPresenter).GetField("_handle", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
if (presenter == null || !presenter.Ready || !(field.GetValue(presenter) is YooAsset.SceneHandle handle) || handle.Status != YooAsset.EOperationStatus.Succeeded)
throw new InvalidOperationException("YooAsset scene handle did not load HomeCamp");
return "PASS YooAsset additive scene load and HUD render";
}
public static string CheckPreview()
{
var hud = HotUpdate.UI.UiManager.Instance?.Get("UI_MainHUD");
if (!hud) throw new InvalidOperationException("HUD not ready");
var camp = hud.GetComponentInChildren<HotUpdate.UI.HomeCampPresenter>(true);
if (!camp || !camp.Ready) throw new InvalidOperationException("Camp preview not ready");
var image = camp.GetComponent<RawImage>();
if (!image.enabled || image.raycastTarget || !(image.texture is RenderTexture rt))
throw new InvalidOperationException("Camp render target or hit testing invalid");
var camera = GameObject.Find("HomeCampCamera")?.GetComponent<Camera>();
if (!camera || camera.targetTexture != rt || !camera.enabled)
throw new InvalidOperationException("Camp camera is not rendering into HUD");
var explorer = hud.transform.Find("ExplorerStage");
if (!explorer || explorer.gameObject.activeSelf || hud.transform.Find("Btn_Explorer").gameObject.activeSelf)
throw new InvalidOperationException("Legacy explorer overlay should be hidden over the 3D camp");
hud.SetActive(false);
if (camera.enabled && camera.gameObject.activeInHierarchy) throw new InvalidOperationException("Hidden HUD still renders camp");
hud.SetActive(true);
if (!camera.enabled || !camera.gameObject.activeInHierarchy) throw new InvalidOperationException("Camp did not resume");
return "PASS camp render " + rt.width + "x" + rt.height + "; FOV=" + camera.fieldOfView + "; legacy overlay hidden; hide/resume passed";
}
public static string Capture()
{
var hud = HotUpdate.UI.UiManager.Instance.Get("UI_MainHUD");
var camera = GameObject.Find("HomeMobileTestCamera").GetComponent<Camera>();
var canvas = hud.GetComponent<Canvas>();
Canvas.ForceUpdateCanvases();
foreach (var button in hud.transform.Find("Layout_Top").GetComponentsInChildren<Button>())
{
var rect = (RectTransform)button.transform;
var hits = new List<RaycastResult>();
EventSystem.current.RaycastAll(new PointerEventData(EventSystem.current) { position = rect.TransformPoint(rect.rect.center) }, hits);
if (hits.Count == 0 || ExecuteEvents.GetEventHandler<IPointerClickHandler>(hits[0].gameObject) != button.gameObject)
throw new InvalidOperationException("Header hit blocked: " + button.name);
}
var target = new RenderTexture(Screen.width, Screen.height, 24);
var pixels = new Texture2D(Screen.width, Screen.height, TextureFormat.RGB24, false);
var mode = canvas.renderMode; var canvasCamera = canvas.worldCamera; var mask = camera.cullingMask;
var previous = RenderTexture.active;
try
{
camera.targetTexture = target; camera.cullingMask = 1 << LayerMask.NameToLayer("UI");
canvas.renderMode = RenderMode.ScreenSpaceCamera; canvas.worldCamera = camera; canvas.planeDistance = 1;
Canvas.ForceUpdateCanvases(); camera.Render(); RenderTexture.active = target;
pixels.ReadPixels(new Rect(0, 0, Screen.width, Screen.height), 0, 0); pixels.Apply();
var dir = Path.GetFullPath(Path.Combine(Application.dataPath, "../../Tools/output/homecamp_integration"));
Directory.CreateDirectory(dir); var path = Path.Combine(dir, "home_" + Screen.width + "x" + Screen.height + ".png");
File.WriteAllBytes(path, pixels.EncodeToPNG()); return "PASS header hit targets; " + path;
}
finally
{
RenderTexture.active = previous; camera.targetTexture = null; camera.cullingMask = mask;
canvas.renderMode = mode; canvas.worldCamera = canvasCamera;
target.Release(); UnityEngine.Object.Destroy(target); UnityEngine.Object.Destroy(pixels);
}
}
public static string Build()
{
if (EditorApplication.isPlaying) throw new InvalidOperationException("Stop Play Mode before building the HUD.");
var json = Path.GetFullPath(Path.Combine(Application.dataPath, "../../Doc/UIPrefabCreater/UI_MainHUD.json"));
var validation = JsonUIPrefabBuilder.Validate(json);
if (!validation.Ok) throw new InvalidOperationException(string.Join("\n", validation.Errors));
var path = JsonUIPrefabBuilder.BuildFromJsonFile(json);
var prefab = AssetDatabase.LoadAssetAtPath<GameObject>(path);
if (prefab == null || prefab.transform.Find("CampWorld")?.GetComponent<RawImage>() == null)
throw new InvalidOperationException("HUD CampWorld missing");
if (prefab.transform.Find("CampWorld").GetComponent<RawImage>().raycastTarget)
throw new InvalidOperationException("Camp image must not intercept buttons");
return "HUD: " + path + "; " + BuildAndStageArt.EnsureLoadableScenePrefabs();
}
}