using Cysharp.Threading.Tasks; namespace DanieleMarotta.RiversongCodeShowcase { [UpdateAfter(typeof(EditingStateGameSystem))] public class BuildingSelectionSystem : GameSystem, IInitializable, IUpdatable { [InjectService] private GameConfig _gameConfig; [InjectService] private IPointerService _pointerService; [InjectService] private UIState _uiState; [InjectService] private ITileSpace _tileSpace; [InjectService] private IEntityCollection _entityCollection; [InjectService] private ICancelAction _cancelAction; [InjectService] private EditingState _editingState; [InjectService] private ISignalBus _signalBus; [InjectService] private IBuildingVisualizationCollection _buildingVisualizationCollection; [InjectService] private World _world; [InjectService] private MaterialReplacementCache _materialReplacementCache; public BuildingSelectionSystem(IServiceLocator serviceLocator) : base(serviceLocator) { } public UniTask InitializeAsync() { _cancelAction.AddHandler( (int)CancelActions.CancelSelection, _ => { if (_uiState.SelectedBuilding == null) return false; SetSelectedBuilding(null); return true; }); return UniTask.CompletedTask; } public void Update() { if (_uiState.SelectedBuilding != null && !_entityCollection.Exists(_uiState.SelectedBuilding.Id)) { SetSelectedBuilding(null); return; } if (_editingState.ActiveTool != null) { SetSelectedBuilding(null); return; } var buildingUnderPointer = GetBuildingUnderPointer(); if (_pointerService.TryConsumeLeftClick()) SetSelectedBuilding(buildingUnderPointer); HighlightBuilding(buildingUnderPointer); HighlightBuilding(_uiState.SelectedBuilding); } private Building GetBuildingUnderPointer() { if (_pointerService.IsPointerOverUI) return null; if (!_pointerService.TryGetPositionOnTerrain(out var position)) return null; var tile = _tileSpace.WorldToTile(position); ref var entityIdMapValue = ref _world.EntityIdMap.GetValueRW(tile); if (entityIdMapValue.BuildingId == Entity.InvalidId) return null; return _entityCollection.TryGet(entityIdMapValue.BuildingId, out var building) ? building : null; } private void HighlightBuilding(Building building) { if (building == null) return; if (!_buildingVisualizationCollection.TryGetVisualization(building.Id, out var visualization)) return; _materialReplacementCache.ReplaceMaterials(visualization.gameObject, _gameConfig.UI.HighlightedGameObjectsMaterial); } private void SetSelectedBuilding(Building selectedBuilding) { if (_uiState.SelectedBuilding == selectedBuilding) return; var oldSelection = _uiState.SelectedBuilding; _uiState.SelectedBuilding = selectedBuilding; _signalBus.Raise(new SelectedBuildingChangedSignal(oldSelection, _uiState.SelectedBuilding)); } } }