using HarmonyLib; using Helpers; using UI.Common; using UI.Map; using UnityEngine; namespace S3.Modules.Popout { // Locates the map panel at runtime. // // MapWindow.instance is private in the current game build, so we use // FindObjectOfType() instead. All the useful fields (_renderTexture, // _window, mapDrag) are also private — accessed via Harmony Traverse. // // MapBuilder.Shared and MapBuilder.mapCamera are public. internal static class PanelFinder { private static MapWindow? _cachedMapWindow; // Returns the live MapWindow MonoBehaviour, or null if the map isn't loaded. // Cached after first find; Unity's == null catches destroyed instances and // triggers a fresh search on the next call. public static MapWindow? GetMapWindow() { if (_cachedMapWindow == null) _cachedMapWindow = Object.FindObjectOfType(); return _cachedMapWindow; } // Returns the RenderTexture the map camera renders to each frame. public static RenderTexture? GetMapRenderTexture() { var mw = GetMapWindow(); return mw == null ? null : Traverse.Create(mw).Field("_renderTexture").Value; } // Returns the Window UI component (exposes public IsShown / ShowWindow). public static Window? GetMapWindowUI() { var mw = GetMapWindow(); return mw == null ? null : Traverse.Create(mw).Field("_window").Value; } // Returns the MapDrag component (exposes public OnZoom / OnDragChange actions). public static MapDrag? GetMapDrag() { var mw = GetMapWindow(); return mw == null ? null : Traverse.Create(mw).Field("mapDrag").Value; } public static bool IsMapReady() { var mw = GetMapWindow(); if (mw == null) return false; return GetMapRenderTexture() != null && MapBuilder.Shared?.mapCamera != null; } // Recomputes map icon scale for the current orthographic size. // MapBuilder.UpdateForZoom() is private in the current game build (it used to // be public), so we invoke it via Traverse. Called after we set // orthographicSize directly (zoom / RT setup) so icons rescale to match. public static void UpdateMapForZoom() { var mb = MapBuilder.Shared; if (mb != null) Traverse.Create(mb).Method("UpdateForZoom").GetValue(); } // Builds the toolbar status string shared by the popout and the in-game overlay. // ASCII separators only — ImGui's default font has no non-ASCII glyphs. public static string BuildStatusText(Camera mapCamera) { string follow = MapEnhancerBridge.IsInstalled ? (MapEnhancerBridge.FollowMode ? " | Following" : "") : ""; string mapCoord = "", camCoord = ""; try { var mapPt = WorldTransformer.WorldToGame(mapCamera.transform.position); mapCoord = $" | Map ({(int)mapPt.x}, {(int)mapPt.z})"; if (Camera.main != null) { var camPt = WorldTransformer.WorldToGame(Camera.main.transform.position); camCoord = $" | Cam ({(int)camPt.x}, {(int)camPt.z})"; } } catch { /* WorldTransformer not ready yet — omit coords */ } return $"Zoom: {(int)mapCamera.orthographicSize}{follow}{mapCoord}{camCoord}"; } } }