using System; using System.Collections.Generic; using Cysharp.Threading.Tasks; using UnityEngine.Device; using UnityEngine.UIElements; namespace DanieleMarotta.RiversongCodeShowcase { [UIView("build-menu")] public class BuildMenuUIView : UIView { private VisualElement _buttons; private Dictionary _buttonViews = new(); private BuildMenuTooltipUIView _tooltip; public event Action ButtonClick; public override async UniTask InitializeAsync(UIService uiService, VisualElement rootElement) { await base.InitializeAsync(uiService, rootElement); _buttons = rootElement.Q(className: "build-menu__buttons"); _tooltip = (BuildMenuTooltipUIView)await uiService.CreateView(typeof(BuildMenuTooltipUIView), rootElement.Q(className: "build-menu__tooltip")); _tooltip.Show(false); } private void OnButtonClick(ClickEvent evt) { var element = (VisualElement)evt.currentTarget; var building = (BuildingDefinition)element.dataSource; ButtonClick?.Invoke(building); } private void OnButtonEnter(PointerEnterEvent evt) { var element = (VisualElement)evt.currentTarget; var building = (BuildingDefinition)element.dataSource; foreach (var buildingModel in Model.Buildings) { if (!ReferenceEquals(buildingModel.Building, building)) continue; _tooltip.SetModel(buildingModel); break; } _tooltip.Show(true); var position = RootElement.WorldToLocal(element.worldBound.center); _tooltip.RootElement.style.left = position.x; _tooltip.RootElement.style.top = position.y; _tooltip.RootElement.schedule.Execute(() => { var left = _tooltip.RootElement.resolvedStyle.left; var rect = _tooltip.RootElement.worldBound; if (rect.xMin < 0) left -= rect.xMin; if (rect.xMax > Screen.width) left -= rect.xMax - Screen.width; _tooltip.RootElement.style.left = left; }); } private void OnButtonLeave(PointerLeaveEvent evt) { _tooltip.Show(false); } public async UniTask CreateTeaserButtonAsync(BuildingDefinition building) { var view = await CreateButtonAsync(building); view.RootElement.RegisterCallback(OnButtonEnter); view.RootElement.RegisterCallback(OnButtonLeave); await view.PlayRevealAnimationAsync(); return view; } public async UniTask UnlockOrCreateUnlockedButtonAsync(BuildingDefinition building, Action onUnlockAnimationStarted = null) { if (!_buttonViews.TryGetValue(building.RuntimeId, out var view)) { view = await CreateTeaserButtonAsync(building); await UniTask.WaitForSeconds(0.5f, true); } await UniTask.WaitForSeconds(0.5f, true); onUnlockAnimationStarted?.Invoke(); await view.PlayUnlockAnimationAsync(); view.RootElement.RegisterCallback(OnButtonClick); } private async UniTask CreateButtonAsync(BuildingDefinition building) { var buttonTemplate = UIService.TemplateLibrary.BuildMenu.Button; var buttonElement = buttonTemplate.CloneTree(); _buttons.Add(buttonElement); var view = (BuildMenuButtonUIView)await UIService.CreateView(typeof(BuildMenuButtonUIView), buttonElement); _buttonViews.Add(building.RuntimeId, view); view.SetModel(building); return view; } protected override void OnModelPropertyChanged(object sender, BindablePropertyChangedEventArgs e) { base.OnModelPropertyChanged(sender, e); switch (e.propertyName) { case nameof(BuildMenuModel.SelectedBuilding): UpdateButtonsSelectedState(); break; } } private void UpdateButtonsSelectedState() { foreach (var element in _buttons.Children()) { var button = element.Q(className: "build-menu__button"); if (ReferenceEquals(element.dataSource, Model.SelectedBuilding)) button.AddToClassList("selected"); else button.RemoveFromClassList("selected"); } } } }