AsteroidGame/Assets/Handlers/BuildingHandler.cs

162 lines
4.6 KiB
C#

using AsteroidGame.Entities;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.Serialization;
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;
[FormerlySerializedAs("_availableSStructures")]
[FormerlySerializedAs("_availableStructures")]
[Header("Structures")]
[SerializeField] private SoStructureBaseList _availableSoStructures;
#region Private
private Color _colorCurrent;
private Camera _camera;
private Vector3 _tempVec;
private Plane _buildPlane;
private StructureBase _tempStructure;
private StructureBase _ghostStructure;
private MeshRenderer[] _ghostStructureMeshRenderers;
#endregion
protected override void OnEnable()
{
base.OnEnable();
_camera = Camera.main;
_buildPlane = new Plane(Vector3.up, Vector3.zero);
}
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);
}
private void PlaceStructure()
{
if (!_isBuilding) return;
if (_ghostStructure.BuildPlacementBlocked) return;
if (!Keyboard.current.shiftKey.isPressed)
{
DestroyGhostStructure();
_isBuilding = false;
}
SpawnStructure();
}
private 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(_availableSoStructures._structureList[_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(_availableSoStructures._structureList[_buildingSelector], GetPlanePoint(),
Quaternion.identity,
transform);
}
#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;
}
#endregion
#region Setters
public void SetBuildingIndex(int index)
{
_buildingSelector = index;
}
#endregion
}
}