217 lines
6.5 KiB
C#
217 lines
6.5 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
using Cysharp.Threading.Tasks;
|
|
|
|
namespace DanieleMarotta.RiversongCodeShowcase
|
|
{
|
|
public class BuildMenuUIController : UIControllerSystem<BuildMenuUIView>, IUpdatable, IDisposable
|
|
{
|
|
[InjectService]
|
|
private IGameDatabase _gameDatabase;
|
|
|
|
[InjectService]
|
|
private IEditingService _editingService;
|
|
|
|
[InjectService]
|
|
private ISignalBus _signalBus;
|
|
|
|
[InjectService]
|
|
private World _world;
|
|
|
|
[InjectService]
|
|
private TextFormatHelper _textFormatHelper;
|
|
|
|
[InjectService]
|
|
private ICancelAction _cancelAction;
|
|
|
|
private BuildMenuModel _model;
|
|
|
|
private List<BuildingDefinition> _pendingBuildings = new();
|
|
|
|
private List<BuildingDefinition> _pendingTeasers = new();
|
|
|
|
private bool _isPlayingButtonAnimation;
|
|
|
|
private Action _onUnlockAnimationStarted;
|
|
|
|
public BuildMenuUIController(IServiceLocator serviceLocator) : base(serviceLocator)
|
|
{
|
|
}
|
|
|
|
protected override BuildMenuUIView View => UIRoot.GetView<BuildMenuUIView>();
|
|
|
|
public override async UniTask InitializeAsync()
|
|
{
|
|
await base.InitializeAsync();
|
|
|
|
var buildings = _gameDatabase.OfType<BuildingDefinition>();
|
|
buildings.Sort((x, y) => x.UIOrder.CompareTo(y.UIOrder));
|
|
|
|
_model = new BuildMenuModel();
|
|
var sb = new StringBuilder();
|
|
foreach (var building in buildings)
|
|
{
|
|
if (_world.UnlocksState.TryGetBuildingUnlock(building, out var unlockId))
|
|
{
|
|
var unlock = _gameDatabase.WithId<UnlockDefinition>(unlockId);
|
|
_textFormatHelper.FormatUnlockConditions(unlock, sb);
|
|
}
|
|
|
|
var buildingModel = new BuildMenuBuildingModel
|
|
{
|
|
Building = building,
|
|
UnlockConditions = sb.ToString()
|
|
};
|
|
_model.Buildings.Add(buildingModel);
|
|
|
|
sb.Clear();
|
|
}
|
|
|
|
View.SetModel(_model);
|
|
View.ButtonClick += OnButtonClick;
|
|
|
|
_editingService.ActiveToolChanged += OnActiveToolChanged;
|
|
|
|
_signalBus.Subscribe<UnlockUnlockedSignal>(OnUnlockUnlocked);
|
|
foreach (var unlockId in _world.UnlocksState.Unlocked)
|
|
{
|
|
var unlock = _gameDatabase.WithId<UnlockDefinition>(unlockId);
|
|
OnUnlockUnlocked(unlock);
|
|
}
|
|
|
|
_cancelAction.AddHandler(
|
|
(int)CancelActions.CloseBuildMenu,
|
|
_ =>
|
|
{
|
|
if (!View.IsOpen()) return false;
|
|
|
|
CloseView();
|
|
|
|
return true;
|
|
});
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
View.ButtonClick -= OnButtonClick;
|
|
|
|
_editingService.ActiveToolChanged -= OnActiveToolChanged;
|
|
|
|
_signalBus.Unsubscribe<UnlockUnlockedSignal>(OnUnlockUnlocked);
|
|
}
|
|
|
|
private void OnButtonClick(BuildingDefinition building)
|
|
{
|
|
if (!_world.UnlocksState.UnlockedBuildings.Contains(building.RuntimeId)) return;
|
|
|
|
var buildTool = _editingService.EditingState.BuildTool;
|
|
buildTool.Building = building;
|
|
|
|
_editingService.ActivateTool(buildTool);
|
|
}
|
|
|
|
private void OnActiveToolChanged(EditTool tool)
|
|
{
|
|
BuildingDefinition selectedBuilding = null;
|
|
if (tool is BuildTool buildTool) selectedBuilding = buildTool.Building;
|
|
_model.SelectedBuilding = selectedBuilding;
|
|
}
|
|
|
|
private void OnUnlockUnlocked(UnlockDefinition unlock)
|
|
{
|
|
if (unlock.Building)
|
|
{
|
|
_pendingBuildings.Add(unlock.Building);
|
|
_pendingBuildings.Sort();
|
|
}
|
|
|
|
if (unlock.TeasedBuildings.Count > 0)
|
|
{
|
|
foreach (var teasedBuilding in unlock.TeasedBuildings) _pendingTeasers.Add(teasedBuilding);
|
|
_pendingTeasers.Sort();
|
|
}
|
|
}
|
|
|
|
private void OnUnlockUnlocked(UnlockUnlockedSignal signal)
|
|
{
|
|
OnUnlockUnlocked(signal.Unlock);
|
|
}
|
|
|
|
public void Update()
|
|
{
|
|
UpdateModels();
|
|
UpdateButtons();
|
|
}
|
|
|
|
private void UpdateModels()
|
|
{
|
|
foreach (var buildingModel in _model.Buildings) buildingModel.IsUnlocked = _world.UnlocksState.UnlockedBuildings.Contains(buildingModel.Building.RuntimeId);
|
|
}
|
|
|
|
private void UpdateButtons()
|
|
{
|
|
if (!View.IsOpen() || _isPlayingButtonAnimation || (_pendingBuildings.Count <= 0 && _pendingTeasers.Count <= 0)) return;
|
|
|
|
if (_pendingBuildings.Count > 0)
|
|
{
|
|
var building = _pendingBuildings[0];
|
|
_pendingBuildings.RemoveAt(0);
|
|
|
|
_ = UnlockButtonAsync(building);
|
|
|
|
return;
|
|
}
|
|
|
|
while (_pendingTeasers.Count > 0)
|
|
{
|
|
var teaserBuilding = _pendingTeasers[0];
|
|
_pendingTeasers.RemoveAt(0);
|
|
|
|
if (_world.UnlocksState.UnlockedBuildings.Contains(teaserBuilding.RuntimeId)) continue;
|
|
|
|
_ = CreateTeaserButtonAsync(teaserBuilding);
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
private async UniTask UnlockButtonAsync(BuildingDefinition building)
|
|
{
|
|
_isPlayingButtonAnimation = true;
|
|
|
|
try
|
|
{
|
|
_onUnlockAnimationStarted ??= () => _signalBus.Raise(new BuildMenuButtonUnlockAnimationStartedSignal());
|
|
await View.UnlockOrCreateUnlockedButtonAsync(building, _onUnlockAnimationStarted);
|
|
await UniTask.WaitForSeconds(0.5f, true);
|
|
}
|
|
finally
|
|
{
|
|
_isPlayingButtonAnimation = false;
|
|
}
|
|
}
|
|
|
|
private async UniTask CreateTeaserButtonAsync(BuildingDefinition building)
|
|
{
|
|
_isPlayingButtonAnimation = true;
|
|
|
|
try
|
|
{
|
|
await View.CreateTeaserButtonAsync(building);
|
|
await UniTask.WaitForSeconds(0.5f, true);
|
|
}
|
|
finally
|
|
{
|
|
_isPlayingButtonAnimation = false;
|
|
}
|
|
}
|
|
|
|
protected override void CloseView(bool animate = true)
|
|
{
|
|
if (_isPlayingButtonAnimation) return;
|
|
|
|
base.CloseView(animate);
|
|
}
|
|
}
|
|
} |