Files
VOIDRPG/Assets/90 - Scripts/Generic/Player/DraggingManager.cs
T
2026-07-09 21:33:33 +02:00

223 lines
7.5 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using VOID.Generic.Objects.Item;
using VOID.Generic.Player.DraggingOperation;
using VOID.Generic.Player.Input;
using VOID.Generic.Player.Util;
using VOID.UserInterface;
using VOID.UserInterface.Game;
using VOID.Generic.Util;
using VOID.ScriptableObjects.Abilities;
namespace VOID.Generic.Player
{
[DefaultExecutionOrder(-1)]
public class DraggingManager : MonoBehaviour
{
public static DraggingManager current {get; private set;}
// References
private PlayerController _playerController;
private PlayerInputManager _playerInputManager;
private GameUI _gameUI;
private DraggingUI _draggingUI;
// Configuration
[SerializeField] private float startDraggingAfter = 0.2f;
// Private properties
private List<AbstractDraggingOperation> _draggingOperations;
private SelectUtilResult _sourceSelect;
private SelectUtilResult _targetSelect;
private bool _isDragging;
private bool _isPreparing;
// Submodule that visualize player's dragging
private DraggingVisualizer _draggingVisualizer;
// Transform from those GameObjects used as start and end for trajectory
private GameObject _draggingFrom;
private GameObject _draggingTo;
private void Awake()
{
current = this;
var thisTransform = transform;
_draggingFrom = new GameObject("Dragging From");
_draggingFrom.transform.parent = thisTransform;
_draggingTo = new GameObject("Dragging To");
_draggingTo.transform.parent = thisTransform;
_draggingOperations = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(assembly => assembly.GetTypes())
.Where(type => type.IsSubclassOf(typeof(AbstractDraggingOperation)) && type.IsClass)
.Select(Activator.CreateInstance)
.Cast<AbstractDraggingOperation>()
.ToList();
}
private void Start()
{
_playerInputManager = PlayerInputManager.current;
_playerInputManager.OnDraggingPrepare += PrepareDragging;
_playerInputManager.OnDraggingStart += StartDragging;
_playerInputManager.OnDraggingEnd += EndDragging;
_playerController = PlayerController.current;
_gameUI = GameUI.current;
_draggingUI = DraggingUI.current;
}
private void FixedUpdate()
{
Dragging();
}
/// <summary>
/// Checks that the operation can be performed and prepares the data for use
/// </summary>
private void PrepareDragging()
{
if (_isPreparing || _isDragging) Clean();
var sourceSelect = SelectUtil.Select();
// Dragging only when ability or item selected (and can be dragged)
if (!sourceSelect.selectObject && !sourceSelect.selectAbility) return;
if (sourceSelect.selectObject is not null and not ItemObject) return;
var selectItem = (ItemObject)sourceSelect.selectObject;
if (selectItem && !selectItem.itemData.canBeMoved) return;
_draggingFrom.transform.position = sourceSelect.position;
_draggingTo.transform.position = sourceSelect.position;
_sourceSelect = sourceSelect;
_isPreparing = true;
}
/// <summary>
/// Initiate draging visualisation
/// Requied: PrepapreDragging to be done before
/// </summary>
private void StartDragging()
{
if(!_isPreparing) return;
_isDragging = true;
if(_sourceSelect.selectObject is ItemObject) StartDraggingItem((ItemObject)_sourceSelect.selectObject);
else if(_sourceSelect.selectAbility) StartDraggingAbility(_sourceSelect.selectAbility);
}
private void StartDraggingItem(ItemObject item)
{
// Prepare for Scene dragging
_draggingVisualizer = DraggingVisualizer.Create(_draggingFrom.transform, _draggingTo.transform, item);
// Prepare for UI dragging
_draggingUI.Set(item);
}
private void StartDraggingAbility(BasicAbility ability)
{
_draggingUI.Set(ability);
_draggingUI.Show();
}
private void Dragging()
{
if (!_isDragging) return;
if (_sourceSelect.selectObject && !_gameUI.isCursorOverUI) DraggingItemOnScene();
else if (_sourceSelect.selectObject && _gameUI.isCursorOverUI) DraggingItemOnUI();
else if (_sourceSelect.selectAbility) DraggingAbility();
}
private void DraggingItemOnScene()
{
_draggingUI.Hide();
var hit = SelectUtil.SelectHit();
_draggingTo.transform.position = hit.point;
// Dragging only onto STATIC objects (like floor)
if (hit.collider.gameObject.layer is not LayerManager.StaticIndex)
{
_draggingVisualizer.Hide();
return;
}
var isInRange = RangeUtil.IsInRange(
_draggingFrom.transform.position,
_draggingTo.transform.position,
_playerController.activeUnit.unitData.takeRange*2,
false
);
// Dragging only when in player's unit range (2 * take range)
if (!isInRange)
{
_draggingVisualizer.Hide();
return;
}
_draggingVisualizer.Show();
}
private void DraggingItemOnUI()
{
_draggingUI.Show();
_draggingVisualizer.Hide();
}
private void DraggingAbility()
{
}
/// <summary>
/// This function completes the transfer process. It contains the main logic responsible for moving an object from one place to another
/// Required: StartDragging to be done before
/// </summary>
private void EndDragging()
{
if (!_isDragging)
{
Clean();
return;
}
_targetSelect = SelectUtil.Select();
if (_gameUI.isCursorOverUI && _targetSelect.slotUI?.slotType == null)
{
Debug.LogWarning("Dragged into invalid place over UI");
Clean();
return;
}
var operation = _draggingOperations.FirstOrDefault(op => op.Check(_sourceSelect, _targetSelect));
if (operation != null)
{
operation.Perform(_playerController.activeUnit, _sourceSelect, _targetSelect);
Clean();
return;
}
Debug.LogWarning("Dragging between unsupported places: " +
$"'{_sourceSelect.slotUI?.slotType}' -> '{_targetSelect.slotUI?.slotType}'");
Clean();
}
private void Clean()
{
if (_draggingVisualizer)
{
Destroy(_draggingVisualizer.gameObject);
_draggingVisualizer = null;
}
_isDragging = false;
_isPreparing = false;
_sourceSelect = null;
_targetSelect = null;
_draggingUI.Hide();
}
}
}