上海虹口龙之梦项目
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.

293 lines
9.5 KiB

12 months ago
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
}