140 lines
3.5 KiB
C#
140 lines
3.5 KiB
C#
using UnityEngine;
|
|
using TMPro;
|
|
|
|
public class SelectionManager : MonoBehaviour
|
|
{
|
|
public static SelectionManager Instance { get; private set; }
|
|
|
|
[Header("Nameplate")]
|
|
public Canvas worldSpaceCanvas; // a World Space Canvas in scene
|
|
public GameObject nameplatePrefab; // prefab containing TextMeshProUGUI
|
|
public Vector3 nameplateOffset = new Vector3(0, 2.2f, 0);
|
|
|
|
[Header("Colors")]
|
|
public Color friendlyColor = Color.green;
|
|
public Color neutralColor = Color.cyan;
|
|
public Color enemyColor = Color.red;
|
|
|
|
Selectable current;
|
|
GameObject activeNameplate;
|
|
NameplateController nameplateController;
|
|
|
|
void Awake()
|
|
{
|
|
if (Instance != null && Instance != this)
|
|
{
|
|
Debug.LogWarning("Multiple SelectionManager instances detected. Destroying duplicate.", gameObject);
|
|
Destroy(gameObject);
|
|
return;
|
|
}
|
|
Instance = this;
|
|
}
|
|
|
|
void OnDestroy()
|
|
{
|
|
if (Instance == this) Instance = null;
|
|
}
|
|
|
|
public void Select(Selectable s)
|
|
{
|
|
if (s == null)
|
|
{
|
|
ClearSelection();
|
|
return;
|
|
}
|
|
|
|
if (current == s) return;
|
|
|
|
ClearSelection();
|
|
|
|
current = s;
|
|
current.OnSelected();
|
|
|
|
CreateNameplate(s.displayName, GetColorForAttitude(s.attitude));
|
|
}
|
|
|
|
public void Select(Building b)
|
|
{
|
|
if (b == null)
|
|
{
|
|
ClearSelection();
|
|
return;
|
|
}
|
|
|
|
ClearSelection();
|
|
b.OnSelected();
|
|
|
|
CreateNameplate(b.displayName, GetColorForAttitude(b.attitude));
|
|
}
|
|
|
|
void CreateNameplate(string displayName, Color color)
|
|
{
|
|
if (nameplatePrefab == null || worldSpaceCanvas == null) return;
|
|
|
|
activeNameplate = Instantiate(nameplatePrefab, worldSpaceCanvas.transform, false);
|
|
nameplateController = activeNameplate.GetComponent<NameplateController>();
|
|
|
|
if (nameplateController == null)
|
|
{
|
|
Debug.LogError("NameplateController not found on nameplate prefab!", nameplatePrefab);
|
|
DestroyNameplate();
|
|
return;
|
|
}
|
|
|
|
if (current != null)
|
|
{
|
|
nameplateController.Initialize(current, color, nameplateOffset);
|
|
}
|
|
else
|
|
{
|
|
// For buildings, we'll update in LateUpdate with the last known target
|
|
nameplateController.SetDisplayName(displayName);
|
|
nameplateController.ApplyColor(color);
|
|
}
|
|
}
|
|
|
|
public void ClearSelection()
|
|
{
|
|
if (current != null)
|
|
{
|
|
current.OnDeselected();
|
|
current = null;
|
|
}
|
|
|
|
DestroyNameplate();
|
|
}
|
|
|
|
void DestroyNameplate()
|
|
{
|
|
if (activeNameplate != null) Destroy(activeNameplate);
|
|
activeNameplate = null;
|
|
nameplateController = null;
|
|
}
|
|
|
|
Color GetColorForAttitude(Attitude a)
|
|
{
|
|
return a switch
|
|
{
|
|
Attitude.Friendly => friendlyColor,
|
|
Attitude.Neutral => neutralColor,
|
|
Attitude.Enemy => enemyColor,
|
|
_ => neutralColor
|
|
};
|
|
}
|
|
|
|
void LateUpdate()
|
|
{
|
|
// Update nameplate position if it exists and has a target
|
|
if (nameplateController != null && current != null)
|
|
{
|
|
nameplateController.FollowTarget(current.transform, nameplateOffset);
|
|
}
|
|
|
|
// Clean up orphaned nameplates if current object was destroyed
|
|
if (current == null && activeNameplate != null)
|
|
{
|
|
DestroyNameplate();
|
|
}
|
|
}
|
|
}
|