using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; /*************This class handles object selection, hovering capability and a picker canvas to clearly highlight objects**************/ public class ObjectSelector : MonoBehaviour { //General Ray ray; RaycastHit hit; //Selector canvas variables float left = 0; float top = 0; float right = 0; float bottom = 0; float cellSize; RectTransform cornerImage; Vector2 widthHeight; Vector2 canvasPos; float width; float height; float distance; bool adjusting = false; bool reset = false; //Hovering variables bool hovered = false; bool previewObj; bool dragMove; bool dragAfterSelect; GameObject hoveredObject; GameObject previousHoveredObject; //Cached variables GridSelector gridSelector; GridObjectOptions gridObjectOptions; ObjectRemover objectRemover; GridSquare gridSquare; GameObject selectedObj; //Serialized variable [SerializeField] Material selectedMaterial; [SerializeField] Material hoveredMaterial; [SerializeField] Canvas selectorCanvas; [SerializeField] bool hideCanvasOnPreview; [SerializeField] float selectorCanvasHeight; [SerializeField] bool smoothCornerAdjust; [SerializeField] float cornerMoveSpeedPerSecond; [SerializeField] float cornerAdjustPadding; //Accessors public Material SelectedMaterial { get { return selectedMaterial; } set { selectedMaterial = value; } } public GameObject SelectedObj { get { return selectedObj; } } public Canvas SelectorCanvas { get { return selectorCanvas; } } public float SelectorCanvasHeight { get { return selectorCanvasHeight; } } public bool HideCanvasOnPreview { get { return hideCanvasOnPreview; } } public GameObject HoveredObject { set { hoveredObject = value; } } public bool PreviewObj { get { return previewObj; } set { previewObj = value; } } void Awake() { gridSquare = FindObjectOfType(); if(gridSquare) { cellSize = gridSquare.CellSize; } } private void Start() { //Caches objects gridSelector = GridBuilder2Manager.Instance.GridSelector; objectRemover = GridBuilder2Manager.Instance.ObjectRemover; gridObjectOptions = GridBuilder2Manager.Instance.GridObjectOptions; if (gridObjectOptions) { dragMove = gridObjectOptions.DragMove; dragAfterSelect = gridObjectOptions.DragAfterSelect; } if (selectorCanvas) { ResetCanvas(); } } void Update() { ray = Camera.main.ScreenPointToRay(Input.mousePosition); //Checks to see if there is a grid selector and that the selector is not holding an object to place if(gridSelector && !gridSelector.SelectedGameObjectToPlace) { if (Physics.Raycast(ray, out hit)) { if (Input.GetMouseButtonDown(0) && !EventSystem.current.IsPointerOverGameObject()) { var hitGridObject = hit.collider.GetComponent(); //Hits a gridobject and selects it if (hitGridObject) { //Hits a different gridObject so deselects the old one if (hitGridObject.gameObject != selectedObj && selectedObj) { DeselectObject(); } //Before selecting, checks to see if the object remover is enabled so it doesnt select as well as delete. if(objectRemover && objectRemover.enabled) { return; } //Another check to see if it is building, usually you cannot select objects that are being built if(CheckForBuildingStatus()) { //Select if nothing is selected, on Deselect sets selectedObj to null if(!selectedObj) { if (!dragMove || dragAfterSelect) { //This line stops selection if you have just moved an object as you want to deselect it, not select it again. if (gridObjectOptions) { if (gridObjectOptions.MoveTimeout == 0) { selectedObj = hit.collider.gameObject; SelectObject(selectedObj); } } else { selectedObj = hit.collider.gameObject; SelectObject(selectedObj); } } else { if (!dragAfterSelect) { //Starts the drag move process selectedObj = hit.collider.gameObject; gridObjectOptions.SelectedObject = this.selectedObj; gridObjectOptions.DragMoveStart(); } } } //Allows selecting once from above if, and then to be able to drag else if(dragAfterSelect && dragMove) { if (selectedObj) { selectedObj = hit.collider.gameObject; SelectObject(selectedObj); //Starts the drag move process selectedObj = hit.collider.gameObject; gridObjectOptions.SelectedObject = this.selectedObj; gridObjectOptions.DragMoveStart(); } else { selectedObj = hit.collider.gameObject; SelectObject(selectedObj); } } } } //Doesnt hit a gridObject, deselects the old one else { if (!EventSystem.current.IsPointerOverGameObject()) { DeselectObject(); ResetCanvas(); } } } //Hovered preview if (hoveredMaterial || selectorCanvas) { //Not hovering over UI if (!EventSystem.current.IsPointerOverGameObject()) { //Hits a grid object if (hit.collider.gameObject.GetComponent()) { //Check that you are not already hovering if (!hovered) { //Sets the previously selected object to change it back when not hovering over it previousHoveredObject = hit.collider.gameObject; //Changes the material if there is one IsHovered(); hovered = true; //If you have Selector canvas, manipulate it to be the size of your object using the SelectObject dimensions if(selectorCanvas) { cornerImage = selectorCanvas.transform.GetChild(0).GetComponent(); ShowCanvas(); GetObjectWidthHeight(GetGridObjectCheckPositions()); AdjustCanvasImage(); } } //Different grid object if (previousHoveredObject && previousHoveredObject != hit.collider.gameObject) { if (previousHoveredObject != selectedObj) { ApplyOriginalMaterial(previousHoveredObject); hovered = false; } else { hovered = false; } } } //Doesnt hit a grid object else { if (previousHoveredObject != null) { if (hovered && selectedObj != hoveredObject) { ApplyOriginalMaterial(previousHoveredObject); ResetCanvas(); } if (selectedObj && !reset) { ResetCanvas(); } } else { ResetCanvas(); } } } //If hovering over UI else { if (previousHoveredObject != null) { if (hovered && selectedObj != hoveredObject) { ApplyOriginalMaterial(previousHoveredObject); ResetCanvas(); } } if(selectedObj != null && !hit.collider.gameObject.GetComponent()) { ResetCanvas(); } } } } //Outside grid area else { if (previousHoveredObject != null) { if (hovered) { ApplyOriginalMaterial(previousHoveredObject); ResetCanvas(); HideCanvas(); } } } } //Performs the smooth adjusting of the Selector canvas if(cornerImage && adjusting) { cornerImage.sizeDelta = Vector2.MoveTowards(cornerImage.sizeDelta, widthHeight, (distance / cornerMoveSpeedPerSecond) * Time.deltaTime); if(cornerImage.sizeDelta == widthHeight) { adjusting = false; } } } public void HideCanvas() { if (selectorCanvas) { selectorCanvas.gameObject.SetActive(false); } } public void ShowCanvas() { if (selectorCanvas) { selectorCanvas.gameObject.SetActive(true); } } //Changes the canvas back to your chosen cell size public void ResetCanvas() { if (!reset) { if (selectorCanvas && !EventSystem.current.IsPointerOverGameObject()) { width = cellSize; height = cellSize; widthHeight = new Vector2(width + cornerAdjustPadding, height + cornerAdjustPadding); cornerImage = selectorCanvas.transform.GetChild(0).GetComponent(); if (!smoothCornerAdjust) { cornerImage.sizeDelta = new Vector2(width + cornerAdjustPadding, height + cornerAdjustPadding); } else { CalcDistance(); adjusting = true; } hovered = false; previewObj = false; reset = true; } } } private void CalcDistance() { distance = Vector2.Distance(cornerImage.sizeDelta, widthHeight); } //Starts the adjusting process to a different size of canvas public void AdjustCanvasImage() { widthHeight = new Vector2(width + cornerAdjustPadding, height + cornerAdjustPadding); //Sets the position of the canvas to center of the object selectorCanvas.transform.position = new Vector3( canvasPos.x, selectorCanvasHeight + gridSelector.transform.position.y, canvasPos.y); if (smoothCornerAdjust) { CalcDistance(); adjusting = true; } else { cornerImage.sizeDelta = widthHeight; } reset = false; } private List GetGridObjectCheckPositions() { if (hoveredObject.GetComponent().data.CheckPositions != null) { return hoveredObject.GetComponent().data.CheckPositions; } else { return new List { hoveredObject.GetComponent().data.Position }; } } //Calculates the size the canvas should be based on what the checkedPositions are public Vector2 GetObjectWidthHeight(List checkPosList) { if (checkPosList.Count > 0) { left = checkPosList[0].x; right = checkPosList[0].x; top = checkPosList[0].z; bottom = checkPosList[0].z; foreach (Vector3 pos in checkPosList) { //Finds furthest left check pos if (pos.x < left) { left = pos.x; } //Finds furthest right check pos if (pos.x > right) { right = pos.x; } //Finds furthest top check pos if (pos.z > top) { top = pos.z; } //Finds furthest bottom check pos if (pos.z < bottom) { bottom = pos.z; } } GetCanvasPos(); //Works out the difference to give you the gap inbetween width = Mathf.Abs(left - right) + 1; height = Mathf.Abs(top - bottom) + 1; } else { width = cellSize; height = cellSize; } return new Vector2(width, height); } private Vector2 GetCanvasPos() { canvasPos = new Vector2((left + right) * 0.5f, (top + bottom) * 0.5f); return canvasPos; } //Checks to see if the object is timed and being built private bool CheckForBuildingStatus() { bool isBuilt = true; if (selectedObj && selectedObj.GetComponent()) { if (selectedObj.GetComponent().data.BuildTimeRemaining > 0) { isBuilt = false; } else { isBuilt = true; } } if (hit.collider.gameObject.GetComponent()) { if (hit.collider.gameObject.GetComponent().data.BuildTimeRemaining > 0) { isBuilt = false; } else { isBuilt = true; } } return isBuilt; } //Changes the material to the hovered material private void IsHovered() { if (gridSelector) { hoveredObject = hit.collider.gameObject; if(hoveredMaterial && selectedObj != hoveredObject) { if (CheckForBuildingStatus()) { gridSelector.ChangeObjMat(hoveredObject, hoveredMaterial); CallOnBuildingOverInt(hoveredObject); } } } } //Applies the original material aswell closing any menu if open public void DeselectObject() { if(selectedObj) { if (selectedMaterial) { if (CheckForBuildingStatus()) { ApplyOriginalMaterial(selectedObj); } } CallOnBuildingDeselectInt(selectedObj); } if (gridObjectOptions) { gridObjectOptions.CloseMenu(); } selectedObj = null; } //Applies the selected material and opens the menu for other options if GridObjectOptions are also in the scene public void SelectObject(GameObject selectedObj) { //Used if you call this function from outside but do not set the SelectedObj if(selectedObj != this.selectedObj) { this.selectedObj = selectedObj; } if(!EventSystem.current.IsPointerOverGameObject()) { if(selectedMaterial) { if(gridSelector) { gridSelector.ChangeObjMat(selectedObj, selectedMaterial); } } //Sets the selected object to use for more functions in gridObjectOptions and opens the menu if(gridObjectOptions) { gridObjectOptions.SelectedObject = this.selectedObj; CallOnBuildingSelectInt(this.selectedObj); gridObjectOptions.OpenMenu(selectedObj.transform.position, selectedObj); //Adjusts the canvas to match the selected object if (selectorCanvas) { if (selectedObj.GetComponent()) { GetObjectWidthHeight(selectedObj.GetComponent().data.CheckPositions); AdjustCanvasImage(); } } } hovered = false; } } //Applies the objects original material the GridObject class private void ApplyOriginalMaterial(GameObject obj) { if (obj.GetComponent()) { if (obj.GetComponent().data.BuildTimeRemaining <= 0) { GridObject hitObjectData = obj.GetComponent(); hitObjectData.ReapplyOriginalMaterials(); CallOnBuildingExitInt(obj); hovered = false; } } } private static void CallOnBuildingSelectInt(GameObject selectedObj) { IOnBuildingSelect[] onSelectedList = selectedObj.GetComponents(); for (int i = 0; i < onSelectedList.Length; i++) { onSelectedList[i].OnSelect(selectedObj); } } private static void CallOnBuildingDeselectInt(GameObject deselectedObj) { IOnBuildingDeselect[] onDeselectedList = deselectedObj.GetComponents(); for (int i = 0; i < onDeselectedList.Length; i++) { onDeselectedList[i].OnDeselect(deselectedObj); } } private static void CallOnBuildingOverInt(GameObject overObj) { IOnBuildingOver[] overList = overObj.GetComponents(); for (int i = 0; i < overList.Length; i++) { overList[i].OnBuildingOver(overObj); } } private static void CallOnBuildingExitInt(GameObject exitObj) { IOnBuildingExit[] exitList = exitObj.GetComponents(); for (int i = 0; i < exitList.Length; i++) { exitList[i].OnBuildingExit(exitObj); } } }