using System; using Cysharp.Threading.Tasks; using UnityEngine; using UnityEngine.Pool; using IServiceProvider = DanieleMarotta.RiversongCodeShowcase.IServiceProvider; namespace DanieleMarotta.RiversongCodeShowcase { [RequiresWorldReadyForUpdate] public class EditingStateGameSystem : GameSystem, IServiceProvider, IInitializable, IDisposable, IUpdatable, IEditingService { [InjectService] private ICancelAction _cancelAction; [InjectService] private WorldRenderingState _renderingState; [InjectService] private GameConfig _config; [InjectService] private World _world; [InjectService] private ISignalBus _signalBus; [InjectService] private MaterialReplacementCache _materialReplacementCache; public EditingStateGameSystem(IServiceLocator serviceLocator) : base(serviceLocator) { } public EditingState EditingState { get; private set; } public event Action ActiveToolChanged; public void RegisterServices(IServiceLocator serviceLocator) { serviceLocator.RegisterService(this); EditingState = new EditingState(); serviceLocator.RegisterService(EditingState); } public async UniTask InitializeAsync() { EditingState.BuildTool = new BuildTool(ServiceLocator); EditingState.DeleteTool = new DeleteTool(ServiceLocator); EditingState.RoadTool = new RoadTool(ServiceLocator); await EditingState.InitializeAsync(); _cancelAction.AddHandler( (int)CancelActions.CancelEditTool, _ => { if (EditingState.ActiveTool == null) return false; DeactivateTool(); return true; }); } public void Dispose() { EditingState?.Dispose(); EditingState = null; } public void ActivateTool(EditTool tool) { EditingState.ActiveTool?.OnDisabled(); EditingState.ActiveTool = tool; EditingState.ActiveTool?.OnEnabled(); ActiveToolChanged?.Invoke(EditingState.ActiveTool); } public void DeactivateTool() { ActivateTool(null); } public void Update() { UpdateActiveTool(); UpdateHighlightedGameObjects(); } private void UpdateActiveTool() { if (EditingState.ActiveTool == null) return; EditingState.ActiveTool.Update(); UpdateAffectedTiles(); UpdateDeletedGameObjects(); } private void UpdateAffectedTiles() { foreach (var (tile, type) in EditingState.ActiveTool.AffectedTiles) { if (_world.BlockMap.IsBlocked(tile, BlockReason.InvalidElevation)) continue; Color32 color; var config = _config.UI.TileHighlight; switch (type) { case TileHighlightType.ValidTile: color = config.ValidColor; break; case TileHighlightType.InvalidTile: color = config.InvalidColor; break; case TileHighlightType.DeletePreview: color = config.DeletePreviewColor; break; default: color = Color.magenta; break; } _renderingState.TileHighlight.AddTile(tile, color); } } private void UpdateDeletedGameObjects() { EditingState.ActiveTool.GetDeleteGameObjectsPreviewInfo(out var filter, out var rect); if (filter == DeletedGameObjectsFilter.None) return; using var gameObjectsScope = ListPool.Get(out var gameObjects); _signalBus.Raise(new CollectDeletedGameObjectsSignal(filter, rect, gameObjects)); _materialReplacementCache.ReplaceMaterials(gameObjects, _config.UI.DeletedGameObjectsMaterial); } private void UpdateHighlightedGameObjects() { using var gameObjectsScope = ListPool.Get(out var gameObjects); _signalBus.Raise(new CollectHighlightedGameObjectsSignal(gameObjects)); _materialReplacementCache.ReplaceMaterials(gameObjects, _config.UI.HighlightedGameObjectsMaterial); } } }