using System.Collections.Generic; using AsteroidGame.Entities.Structures.Scripts; using UnityEngine; using UnityEngine.InputSystem; namespace AsteroidGame.Handlers { public class BuildingHandler : HandlerBase { [Header("Config")] [SerializeField] private Color colorGhost = new Color(1f, 1f, 1f, 0.12f); [SerializeField] private Color colorBuildingBlocked = new Color(1f, 0f, 0f, 0.12f); [SerializeField] private Material ghostStructureMaterial; [Header("State")] [SerializeField] private bool isBuilding; [SerializeField] private int buildingSelector; [Header("Structures")] [SerializeField] private StructureBaseScriptableObject availableStructuresObject; #region Private private Dictionary _availableStructures = new(); [SerializeField] private Color colorCurrent; private Camera _camera; [SerializeField] private List activeStructures; private Vector3 _tempVec; private Plane _buildPlane; private StructureBase _tempStructure; private StructureBase _ghostStructure; private MeshRenderer[] _ghostStructureMeshRenderers; #endregion protected override void OnEnable() { base.OnEnable(); for (int i = 0; i < availableStructuresObject.structureList.Count; i++) { _availableStructures.Add(i, availableStructuresObject.structureList[i]); } _camera = Camera.main; _buildPlane = new Plane(Vector3.up, Vector3.zero); activeStructures.Clear(); } private void Update() { if (!isBuilding) return; _ghostStructure.transform.position = GetPlanePoint(); SetGhostColor(_ghostStructure.BuildPlacementBlocked ? colorBuildingBlocked : colorGhost); } private void SetGhostColor(Color newColor) { if (newColor == colorCurrent) return; foreach (var meshRenderer in _ghostStructureMeshRenderers) { meshRenderer.material.color = newColor; } colorCurrent = newColor; } protected override void OnLeftClick(InputAction.CallbackContext context) { PlaceStructure(); } protected override void OnRightClick(InputAction.CallbackContext context) { AbortPlaceStructure(); } protected override void OnBuild(InputAction.CallbackContext context) { EnterBuildMode(); } public void PlaceStructure() { if (!isBuilding) return; if (_ghostStructure.BuildPlacementBlocked) return; DestroyGhostStructure(); SpawnStructure(); isBuilding = false; } public void AbortPlaceStructure() { if (!isBuilding) return; DestroyGhostStructure(); isBuilding = false; } public void EnterBuildMode() { if (isBuilding) return; isBuilding = true; SpawnGhostStructure(); } private void SpawnGhostStructure() { _ghostStructure = Instantiate(_availableStructures[buildingSelector], GetPlanePoint(), Quaternion.identity, transform); _ghostStructure.name = "GhostStructure"; var rb = _ghostStructure.gameObject.AddComponent(); rb.useGravity = false; _ghostStructureMeshRenderers = _ghostStructure.GetComponentsInChildren(); foreach (var meshRenderer in _ghostStructureMeshRenderers) { meshRenderer.material = ghostStructureMaterial; } _ghostStructure.GetComponent().enabled = false; } private void DestroyGhostStructure() { Destroy(_ghostStructure.gameObject); } private void SpawnStructure() { _tempStructure = Instantiate(_availableStructures[buildingSelector], GetPlanePoint(), Quaternion.identity, transform); activeStructures.Add(_tempStructure); } #region Getters private Vector3 GetPlanePoint() { Ray ray = _camera.ScreenPointToRay(Mouse.current.position.ReadValue()); if (_buildPlane.Raycast(ray, out float distance)) { return ray.GetPoint(distance); } print("BuildPlaneNotHit"); return Vector3.zero; } public Dictionary GetAvailableStructures() { return _availableStructures; } public List GetActiveStructures() { return activeStructures; } #endregion #region Setters public void SetBuildingIndex(int index) { buildingSelector = index; } #endregion } }