Minimap!
This commit is contained in:
parent
f7720a9915
commit
6c37e569ab
18 changed files with 1169 additions and 323 deletions
|
|
@ -4,6 +4,7 @@ using UnityEngine;
|
|||
using UnityEngine.UIElements;
|
||||
using TD.Gameplay;
|
||||
using TD.Towers;
|
||||
using TD.UI.Minimap;
|
||||
|
||||
namespace TD.UI
|
||||
{
|
||||
|
|
@ -24,9 +25,9 @@ namespace TD.UI
|
|||
[Tooltip("The TowerPlacementManager NetworkObject in the scene.")]
|
||||
[SerializeField] private TowerPlacementManager placementManager;
|
||||
|
||||
[Header("Minimap")]
|
||||
[Tooltip("RenderTexture that the minimap camera renders into.")]
|
||||
[SerializeField] private RenderTexture minimapRenderTexture;
|
||||
[Tooltip("The local client's CameraController. Used by the minimap for click-to-jump " +
|
||||
"and drag-to-pan.")]
|
||||
[SerializeField] private CameraController cameraController;
|
||||
|
||||
[Header("Settings")]
|
||||
[SerializeField] private float rejectionMessageDuration = 2.5f;
|
||||
|
|
@ -48,6 +49,52 @@ namespace TD.UI
|
|||
private Coroutine rejectionFadeCoroutine;
|
||||
private bool gridPopulated;
|
||||
private bool uiInitialized;
|
||||
private MinimapView minimapView;
|
||||
private IPanel myPanel; // tracked separately so OnDestroy only clears the static if it still points at us
|
||||
|
||||
// ----- Static hit-test probe --------------------------------------
|
||||
|
||||
// Set when InitializeUI succeeds; cleared on OnDestroy. Non-UI systems (camera,
|
||||
// input handlers) can query IsPointerOverInteractiveHud without taking a direct
|
||||
// reference to HUDController.
|
||||
private static IPanel s_hudPanel;
|
||||
|
||||
/// <summary>
|
||||
/// True if <paramref name="screenMousePos"/> falls over an interactive (non-ignore)
|
||||
/// HUD element. Non-UI systems that consume mouse input (camera scroll-zoom, edge-pan)
|
||||
/// should gate their handling on this so a cursor over the minimap, command grid, or
|
||||
/// any other interactive HUD region doesn't drive both the HUD and the world at once.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Convention: <paramref name="screenMousePos"/> uses Unity Input System screen coords
|
||||
/// (origin bottom-left, y up). Returns false before the HUD has initialized; safe to
|
||||
/// call from any system at any time.
|
||||
/// </remarks>
|
||||
public static bool IsPointerOverInteractiveHud(Vector2 screenMousePos)
|
||||
{
|
||||
if (s_hudPanel == null) return false;
|
||||
|
||||
// Coord convention rabbit hole:
|
||||
// - Screen mouse position: origin bottom-left, y up (Unity Input System).
|
||||
// - UI Toolkit panel coords: origin top-left, y down.
|
||||
//
|
||||
// RuntimePanelUtils.ScreenToPanel converts the SCALE (e.g., reference resolution
|
||||
// vs. actual resolution) but does NOT flip Y. We flip manually using the visual
|
||||
// tree's height so the result works regardless of PanelSettings scale mode.
|
||||
//
|
||||
// Subtle: visualTree.worldBound height may be 0 for one frame on the very first
|
||||
// layout pass. The caller (CameraController) checks the result against "is over
|
||||
// interactive HUD"; a one-frame false positive (camera zooms when it shouldn't)
|
||||
// is harmless and self-corrects the next frame.
|
||||
Vector2 scaled = RuntimePanelUtils.ScreenToPanel(s_hudPanel, screenMousePos);
|
||||
float panelHeight = s_hudPanel.visualTree.worldBound.height;
|
||||
Vector2 panelPos = new Vector2(scaled.x, panelHeight - scaled.y);
|
||||
|
||||
// panel.Pick returns null when the topmost element under the point has
|
||||
// PickingMode.Ignore (or there's no element there at all). Non-null means an
|
||||
// interactive HUD element is under the cursor.
|
||||
return s_hudPanel.Pick(panelPos) != null;
|
||||
}
|
||||
|
||||
// ----- Lifecycle --------------------------------------------------
|
||||
|
||||
|
|
@ -101,15 +148,24 @@ namespace TD.UI
|
|||
SetEnabled(root, "upgrade-btn", false);
|
||||
SetEnabled(root, "sell-btn", false);
|
||||
|
||||
// Minimap RenderTexture.
|
||||
if (minimapRenderTexture != null)
|
||||
// Minimap. The MinimapView owns the two sub-elements (terrain + entity overlay)
|
||||
// and drives them; we just hand it the host container and the camera controller.
|
||||
// Bake is deferred until LevelLoader is ready — view tries each frame in Tick().
|
||||
var minimapContainer = root.Q<VisualElement>("minimap");
|
||||
if (minimapContainer != null)
|
||||
{
|
||||
var minimap = root.Q<VisualElement>("minimap");
|
||||
if (minimap != null)
|
||||
minimap.style.backgroundImage =
|
||||
Background.FromRenderTexture(minimapRenderTexture);
|
||||
if (cameraController == null)
|
||||
Debug.LogWarning("[HUDController] cameraController not assigned. " +
|
||||
"Click-to-jump and drag-to-pan on the minimap will be disabled.");
|
||||
minimapView = new MinimapView(minimapContainer, cameraController);
|
||||
}
|
||||
|
||||
// Publish the panel so non-UI systems can query "is pointer over the HUD".
|
||||
// Stored on `myPanel` too so OnDestroy only clears the static if it still
|
||||
// points at this instance (defensive against re-creation overlap).
|
||||
myPanel = root.panel;
|
||||
s_hudPanel = myPanel;
|
||||
|
||||
uiInitialized = true;
|
||||
}
|
||||
|
||||
|
|
@ -131,6 +187,17 @@ namespace TD.UI
|
|||
TryPopulateCommandGrid();
|
||||
|
||||
RefreshGoldDisplay();
|
||||
minimapView?.Tick();
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
minimapView?.Dispose();
|
||||
minimapView = null;
|
||||
|
||||
if (s_hudPanel != null && s_hudPanel == myPanel)
|
||||
s_hudPanel = null;
|
||||
myPanel = null;
|
||||
}
|
||||
|
||||
// ----- Gold display -----------------------------------------------
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue