175 lines
5.2 KiB
C#
175 lines
5.2 KiB
C#
using System.Collections.Generic;
|
|
using AsteroidGame.Entities;
|
|
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 readonly Dictionary<int, StructureBase> _availableStructures = new();
|
|
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);
|
|
}
|
|
|
|
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(_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
|
|
|
|
}
|
|
} |