using Cysharp.Threading.Tasks; using Unity.Mathematics; using UnityEngine.InputSystem; namespace DanieleMarotta.RiversongCodeShowcase { public abstract class DragTool : EditTool { private IPointerService _pointerService; private ITileSpace _tileSpace; private bool _isDragging; private int2 _startTile; private int2 _endTile; private bool _isValid; protected DragTool(IServiceLocator serviceLocator) : base(serviceLocator) { } protected virtual DeletedGameObjectsFilter DeletedGameObjectsFilter => DeletedGameObjectsFilter.None; public override async UniTask InitializeAsync() { await base.InitializeAsync(); _pointerService = ServiceLocator.GetService(); _tileSpace = ServiceLocator.GetService(); } public override void OnDisabled() { base.OnDisabled(); _isDragging = false; } public override void Update() { base.Update(); AffectedTiles.Clear(); var lmb = Mouse.current.leftButton; var isPointerOnTerrain = _pointerService.TryGetPositionOnTerrain(out var position); if (!isPointerOnTerrain) { _isDragging &= lmb.isPressed; _isValid = false; return; } if (!_isDragging) { _startTile = _tileSpace.WorldToTile(position); _endTile = _startTile; } _isDragging |= _pointerService.TryConsumeLeftClick(); if (_isDragging && !_pointerService.IsPointerOverUI) _endTile = _tileSpace.WorldToTile(position); _isValid = Validate(ref _startTile, ref _endTile); UpdateAffectedTiles(_isValid, _startTile, _endTile); if (lmb.wasReleasedThisFrame) { if (_isValid && !_pointerService.IsPointerOverUI) DoTool(_startTile, _endTile); _isDragging = false; } } protected abstract bool Validate(ref int2 startTile, ref int2 endTile); protected abstract void UpdateAffectedTiles(bool isValid, int2 startTile, int2 endTile); protected abstract void DoTool(int2 startTile, int2 endTile); public override void GetDeleteGameObjectsPreviewInfo(out DeletedGameObjectsFilter filter, out TileRect rect) { if (!_isValid) { filter = DeletedGameObjectsFilter.None; rect = TileRect.Empty; return; } filter = DeletedGameObjectsFilter; rect = new TileRect(_startTile, _endTile); } } }