AsteroidGame/Assets/Handlers/BuildingHandler.cs

170 lines
5.1 KiB
C#

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<int, StructureBase> _availableStructures = new();
[SerializeField] private Color colorCurrent;
private Camera _camera;
[SerializeField] private List<StructureBase> 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(buildingSelector);
}
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(int index)
{
if (isBuilding) return;
isBuilding = true;
SetBuildingIndex(index);
SpawnGhostStructure();
}
private void SpawnGhostStructure()
{
_ghostStructure = Instantiate(_availableStructures[buildingSelector], GetPlanePoint(), Quaternion.identity, transform);
_ghostStructure.name = "GhostStructure";
var rb = _ghostStructure.gameObject.AddComponent<Rigidbody>();
rb.useGravity = false;
_ghostStructureMeshRenderers = _ghostStructure.GetComponentsInChildren<MeshRenderer>();
foreach (var meshRenderer in _ghostStructureMeshRenderers)
{
meshRenderer.material = ghostStructureMaterial;
}
_ghostStructure.GetComponent<StructureBase>().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<int, StructureBase> GetAvailableStructures()
{
return _availableStructures;
}
public List<StructureBase> GetActiveStructures()
{
return activeStructures;
}
#endregion
#region Setters
public void SetBuildingIndex(int index)
{
buildingSelector = index;
}
#endregion
}
}