You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
292 lines
9.5 KiB
292 lines
9.5 KiB
using System.Collections.Generic; |
|
using System.Linq; |
|
using UnityEngine; |
|
using UnityEngine.EventSystems; |
|
using HighlightPlus; |
|
|
|
|
|
|
|
public class SelectionManager : Singleton<SelectionManager> |
|
{ |
|
//物体列表 |
|
public List<GameObject> Sets = new List<GameObject>(); |
|
//启用选择 |
|
public bool CanMakeSelections = true; |
|
//多选 |
|
public KeyCode keyMultiselect = KeyCode.LeftControl; |
|
//减选 |
|
public KeyCode keyDeselect = KeyCode.LeftAlt; |
|
//框选 |
|
public KeyCode DracRectKey = KeyCode.LeftShift; |
|
private static List<SelectableObject> selectedGameObjects = new List<SelectableObject>(); |
|
private bool isSelecting = false; |
|
private Vector3 mousePosition; |
|
public GameObject SingleObject; |
|
|
|
//可选择物体 |
|
private struct SelectableObject |
|
{ |
|
public GameObject gameObject; |
|
public SelectableUnit selectable; |
|
public bool isActive; |
|
} |
|
|
|
private void Start() |
|
{ |
|
//检测相机 |
|
if (!Camera.main) |
|
Debug.Log("The SelectionManager requires a camera with the tag 'MainCamera'"); |
|
ClearSelection(); |
|
} |
|
private void Update() |
|
{ |
|
if (!Camera.main) |
|
return; |
|
if (Sets.Count > 0) |
|
{ |
|
//删除不存在的选定对象 |
|
selectedGameObjects = selectedGameObjects.Where(i => i.gameObject != null).ToList(); |
|
|
|
if (CanMakeSelections) |
|
{ |
|
// 如果按下鼠标左键, 保存鼠标位置并开始选择 |
|
if (Input.GetMouseButtonDown(0)) |
|
{ |
|
isSelecting = true; |
|
mousePosition = Input.mousePosition; |
|
} |
|
|
|
if (Input.GetMouseButtonUp(0)) |
|
{ |
|
if (!EventSystem.current.IsPointerOverGameObject()) |
|
{ |
|
if (isSelecting) |
|
{ |
|
//如果按住Shift键,则不删除已选内容 |
|
if (!(Input.GetKey(keyMultiselect)) && !(Input.GetKey(keyDeselect))) |
|
ClearSelection(); |
|
|
|
List<GameObject> newSelectedObjects = new List<GameObject>(); |
|
bool isFiltered = false; |
|
if (!isFiltered && newSelectedObjects.Count == 0) |
|
{ |
|
newSelectedObjects.AddRange(Utils.FindGameObjectsInList(Sets)); |
|
} |
|
|
|
if (Input.GetKey(DracRectKey)) |
|
{ |
|
foreach (GameObject selectedObject in newSelectedObjects) |
|
{ |
|
if (IsWithinSelectionBounds(selectedObject)) |
|
{ |
|
ParseGameObjectForSelection(selectedObject); |
|
} |
|
} |
|
} |
|
} |
|
|
|
isSelecting = false; |
|
if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out RaycastHit selectionHit)) |
|
{ |
|
ParseGameObjectForSelection(selectionHit.transform.gameObject); |
|
|
|
} |
|
|
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
#region Private Methods |
|
/// <summary> |
|
/// 减选物体 |
|
/// </summary> |
|
/// <param name="selectedObject"></param> |
|
void DetachSelection(SelectableObject selectedObject) |
|
{ |
|
if (selectedObject.gameObject != null) |
|
{ |
|
selectedObject.gameObject.GetComponent<HighlightEffect>().highlighted = false; |
|
SingleObject = null; |
|
if (selectedObject.selectable) |
|
{ |
|
selectedObject.selectable.OnEndSelection(); |
|
} |
|
} |
|
|
|
} |
|
/// <summary> |
|
/// 选择物体 |
|
/// </summary> |
|
/// <param name="sender"></param> |
|
private void ParseGameObjectForSelection(GameObject sender) |
|
{ |
|
var validObject = sender.GetComponent<Selectable>(); |
|
|
|
if (validObject) |
|
{ |
|
bool containsObject = false; |
|
List<SelectableObject> objectsToRemove = new List<SelectableObject>(); |
|
for (int x = 0; x < selectedGameObjects.Count; x++) |
|
{ |
|
SelectableObject selectedObject = selectedGameObjects[x]; |
|
|
|
if (selectedObject.gameObject == sender) |
|
{ |
|
containsObject = true; |
|
selectedObject.isActive = true; |
|
} |
|
|
|
selectedGameObjects[x] = selectedObject; |
|
|
|
if (Input.GetKey(keyDeselect) && selectedObject.gameObject == sender) |
|
{ |
|
DetachSelection(selectedObject); |
|
objectsToRemove.Add(selectedObject); |
|
} |
|
} |
|
selectedGameObjects = selectedGameObjects.Except(objectsToRemove).ToList(); |
|
|
|
if (!containsObject && !Input.GetKey(keyDeselect)) |
|
{ |
|
var selectable = sender.GetComponent<SelectableUnit>(); |
|
if (selectable && selectable != selectable.playerOwned) |
|
return; |
|
|
|
switch (sender.GetComponent<Selectable>().selectMode) |
|
{ |
|
case SelectMode.Single: |
|
var selected1 = new SelectableObject |
|
{ |
|
gameObject = sender, |
|
isActive = true |
|
}; |
|
if (selectable) |
|
{ |
|
selected1.selectable = selectable; |
|
selected1.selectable.OnBeginSelection(); |
|
} |
|
selectedGameObjects.Add(selected1); |
|
SingleObject = sender; |
|
break; |
|
case SelectMode.Multiple: |
|
foreach (Transform t in sender.transform.parent) |
|
{ |
|
var selected2 = new SelectableObject |
|
{ |
|
gameObject = t.gameObject, |
|
isActive = true |
|
}; |
|
|
|
if (selectable) |
|
{ |
|
selected2.selectable = selectable; |
|
selected2.selectable.OnBeginSelection(); |
|
} |
|
selectedGameObjects.Add(selected2); |
|
SingleObject = sender; |
|
} |
|
|
|
break; |
|
} |
|
|
|
//高亮显示 |
|
for (int i = 0; i < selectedGameObjects.Count; i++) |
|
{ |
|
selectedGameObjects[i].gameObject.GetComponent<HighlightEffect>().highlighted = true; |
|
} |
|
} |
|
} |
|
} |
|
|
|
void OnGUI() |
|
{ |
|
if (MainMenu.Instance.MenuMode != MainMenuMode.体验漫游) |
|
{ |
|
if (isSelecting && Input.GetKey(DracRectKey)) |
|
{ |
|
// Create a rect from both mouse positions |
|
var rect = Utils.GetScreenRect(mousePosition, Input.mousePosition); |
|
Utils.DrawScreenRect(rect, new Color(0.2f, 0.8f, 0.2f, 0.25f)); |
|
Utils.DrawScreenRectBorder(rect, 1, new Color(0.2f, 0.8f, 0.2f)); |
|
} |
|
} |
|
|
|
} |
|
|
|
/// <summary> |
|
/// 选择范围 |
|
/// </summary> |
|
/// <param name="gameObject"></param> |
|
/// <returns></returns> |
|
private bool IsWithinSelectionBounds(GameObject gameObject) |
|
{ |
|
if (!isSelecting) |
|
return false; |
|
|
|
var camera = Camera.main; |
|
var viewportBounds = Utils.GetViewportBounds(camera, mousePosition, Input.mousePosition); |
|
return viewportBounds.Contains(camera.WorldToViewportPoint(gameObject.transform.position)); |
|
} |
|
#endregion |
|
|
|
#region Public Methods |
|
/// <summary> |
|
/// 返回选择对象的列表 |
|
/// </summary> |
|
/// <returns></returns> |
|
public static List<GameObject> GetSelectedObjects() |
|
{ |
|
return selectedGameObjects.Select(i => i.gameObject).ToList(); |
|
} |
|
|
|
/// <summary> |
|
/// 将物体添加到选择列表 |
|
/// </summary> |
|
/// <param name="newObject"></param> |
|
public void AddGameObjectToSelection(GameObject newObject) |
|
{ |
|
ParseGameObjectForSelection(newObject); |
|
} |
|
/// <summary> |
|
/// 从选择列表中移除物体 |
|
/// </summary> |
|
/// <param name="removedObject"></param> |
|
public void RemoveGameObjectFromSelection(GameObject removedObject) |
|
{ |
|
foreach (SelectableObject selectedObject in selectedGameObjects) |
|
{ |
|
if (selectedObject.gameObject == removedObject) |
|
{ |
|
DetachSelection(selectedObject); |
|
selectedGameObjects.Remove(selectedObject); |
|
} |
|
} |
|
} |
|
/// <summary> |
|
/// 清空选择 |
|
/// </summary> |
|
public void ClearSelection() |
|
{ |
|
foreach (SelectableObject selectedObject in selectedGameObjects) |
|
{ |
|
DetachSelection(selectedObject); |
|
} |
|
selectedGameObjects.Clear(); |
|
} |
|
/// <summary> |
|
/// 检查物体是否被选择 |
|
/// </summary> |
|
/// <param name="go"></param> |
|
/// <returns></returns> |
|
public static bool IsContains(GameObject go) |
|
{ |
|
var obj = GetSelectedObjects().Find(o => o == go); |
|
return obj ? true : false; |
|
} |
|
#endregion |
|
} |
|
|
|
|
|
|
|
|