TH1/Unity/Assets/Scripts/TH1_UI/View/Bottom/UIBottomBottomBarView.cs
2026-05-21 02:00:00 +08:00

386 lines
11 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using Animancer;
using Logic;
using Logic.Action;
using Logic.Audio;
using Logic.CrashSight;
using Logic.Multilingual;
using RuntimeData;
using TH1_Core.Events;
using TH1_Core.Managers;
using TH1_Logic.Core;
using TH1_Logic.Config;
using TH1_Logic.Net;
using TH1_Logic.Steam;
using TH1_UI.Components;
using TH1_UI.HintUI;
using TH1Renderer;
using TH1Resource;
using TMPro;
using UI.HintUI;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
namespace TH1_UI.View.Bottom
{
public class UIBottomBottomBarView : Base.View
{
//public Button closeButton;
public ViDelegateAssisstant.Dele OnBtnCloseClick;
public ViDelegateAssisstant.Dele OnBtnQuitClick;
public Button TechButton;
public Button HeroButton;
public Button NextButton;
public Button TabButton;
public GameObject HeroButtonIconHint;
public GameObject HeroButtonTextHint;
public Image HeroButtonAvatar;
public Button SettingButton;
public Button QuitButton;
public Button SLButton;
public Button RankingButton;
public Button WikiButton;
public UIBottomBottomBarQuitPanelMono QuitPanel;
public UIBottomBottomBarNextTurnConfirmPanelMono NextTurnConfirmPanel;
public int _tabUnitCount = 0;
protected override void OnInit()
{
base.OnInit();
//closeButton.onClick.RemoveAllListeners();
//closeButton.onClick.AddListener(() => { OnBtnCloseClick.Invoke(); });
//CheckPanel.InitStart(RefreshStatus);
if (QuitPanel != null)
{
QuitPanel.OnInit();
QuitPanel.OnQuitConfirm += OnQuitConfirmed;
}
if (NextTurnConfirmPanel != null)
{
NextTurnConfirmPanel.OnInit();
NextTurnConfirmPanel.OnNextTurnConfirm += ExecuteNextTurn;
}
}
public bool CheckHasTabUnit(out GridData grid)
{
grid = null;
if (Main.MapData == null) return false;
bool ret = false;
GridData firstGrid = null;
int tt = 0;
foreach (var u in Main.MapData.UnitMap.UnitList)
{
if (u.Player(Main.MapData) == Main.MapData.PlayerMap.SelfPlayerData &&
//u.Renderer(Main.MapData).isGlow())
(u.Renderer(Main.MapData)?.isGlow() ?? false))
{
grid = u.Grid(Main.MapData);
if (firstGrid == null) firstGrid = grid;
ret = true;
if(tt < _tabUnitCount)
tt++;
else
{
tt++;
_tabUnitCount = tt;
return ret;
}
}
}
if (ret)
{
grid = firstGrid;
_tabUnitCount = 1;
}
return ret;
}
public void SetTabButtonVisible(bool visible)
{
if(visible) ShowButton(TabButton);
else HideButton(TabButton);
}
public void SetNextTurnButtonVisible(bool visible)
{
if(visible) ShowButton(NextButton);
else HideButton(NextButton);
}
//通常一局只会set一次,每次都是完全清空,然后绑定新的一个对局的按钮
public void SetContent()
{
if (QuitPanel != null)
QuitPanel.gameObject.SetActive(false);
if (NextTurnConfirmPanel != null)
NextTurnConfirmPanel.gameObject.SetActive(false);
QuitButton.onClick.RemoveAllListeners();
QuitButton.onClick.AddListener(OnQuitButtonClicked);
SettingButton.onClick.RemoveAllListeners();
SettingButton.onClick.AddListener(OnSettingButtonClicked);
TechButton.onClick.RemoveAllListeners();
TechButton.onClick.AddListener(OnTechButtonClicked);
NextButton.onClick.RemoveAllListeners();
NextButton.onClick.AddListener(OnNextButtonClicked);
HeroButton.onClick.RemoveAllListeners();
HeroButton.onClick.AddListener(OnHeroButtonClicked);
SLButton.onClick.RemoveAllListeners();
SLButton.gameObject.SetActive(false);
if (Main.MapData.Net.Mode == NetMode.Single)
{
SLButton.gameObject.SetActive(true);
SLButton.onClick.AddListener(OnSLButtonClicked);
}
RankingButton.onClick.RemoveAllListeners();
RankingButton.onClick.AddListener(OnRankingButtonClicked);
TabButton.onClick.RemoveAllListeners();
TabButton.onClick.AddListener(OnTabButtonClicked);
if (WikiButton != null)
{
WikiButton.onClick.RemoveAllListeners();
WikiButton.onClick.AddListener(OnWikiButtonClicked);
}
UpdateHeroButtonAvatar();
// 初始检查 TabButton 是否显示
SetTabButtonVisible(CheckHasTabUnit(out var _));
}
private void OnQuitButtonClicked()
{
if (QuitPanel != null)
{
QuitPanel.Open();
}
else
{
OnQuitConfirmed();
}
}
private void OnQuitConfirmed()
{
OnBtnCloseClick.Invoke();
OnBtnQuitClick.Invoke();
}
private void OnSettingButtonClicked()
{
EventManager.Publish(new ShowUITopSetting(){});
}
private void OnTechButtonClicked()
{
//if (Main.MapData.CurPlayer != Main.MapData.PlayerMap.SelfPlayerData) return;
EventManager.Publish(new ShowUIInfoTechTree(){});
Main.Instance.MapInteractionLogic.CancelAllHighlight();
}
private void OnHeroButtonClicked()
{
//if (Main.MapData.CurPlayer != Main.MapData.PlayerMap.SelfPlayerData) return;
EventManager.Publish(new ShowUIInfoHero(){});
}
private void OnNextButtonClicked()
{
if (Main.MapData.CurPlayer != Main.MapData.PlayerMap.SelfPlayerData) return;
// 二次确认开关打开 → 弹窗,等用户按 CheckOnNextTurnConfirm → ExecuteNextTurn
if (ConfigManager.Instance.Config.ConfirmBeforeNextTurn && NextTurnConfirmPanel != null)
{
NextTurnConfirmPanel.Open();
return;
}
ExecuteNextTurn();
}
// 真正结束本回合的逻辑。CancelAllHighlight / HideUIInfoGridInfo 放在这里,
// 是为了让"弹窗确认"分支也走同一份清场代码;如果在弹窗里 Cancel则现场完全保持。
private void ExecuteNextTurn()
{
Main.Instance.MapInteractionLogic.CancelAllHighlight();
EventManager.Publish(new HideUIInfoGridInfo(){});
if (Main.MapData.Net.Mode == NetMode.Multi && !LobbyManager.Instance.Lobby.IsLobbyOwner())
{
GameNetSender.Instance.TurnEndConfirm();
}
// 单机或者是房主直接切
else Main.PlayerLogic.EndPlayerTurn(Main.MapData, Main.MapData.PlayerMap.SelfPlayerId);
}
private void OnSLButtonClicked()
{
if (Main.MapData == null) return;
if (!Main.MapData.CurPlayer.IsSelfPlayer()) return;
if (Main.MapData.Net.Mode != NetMode.Single) return;
// 切到 Menu 状态前先抓 EmpireMenuState.Enter 会调 Main.Instance.Clear() 清空 MapData
var loadingEvt = new ShowUIOutsideLoading();
var selfData = Main.MapData.PlayerMap?.SelfPlayerData;
if (selfData != null) loadingEvt.Empire = selfData.Empire;
Main.Instance.GameLogic.ChangeState(GameState.Menu);
//TODO 这里的时间控制要处理
//播放loading
EventManager.Publish(loadingEvt);
//重置游戏
Timer.Instance.TimerRegister(this, () => { Main.Instance.ResumeMatch(); }, 0.3f,"MainUI_ShowLoadingAndRusume");
//关闭loading
Timer.Instance.TimerRegister(this,()=> { EventManager.Publish(new HideUIOutsideLoading()); },1f,"MainUI_ShowLoadingAndRusume2");
}
private void OnRankingButtonClicked()
{
EventManager.Publish(new ShowUIBottomRanking());
}
private void OnWikiButtonClicked()
{
// Inside 界面通过全局 EventManager 调起 Outside 的 Wiki 浮窗:
// UIEventManagerBinder 订阅 ShowUIOutsideWiki 后会调 UIOutsideManager.OpenWiki
// Wiki 不占用 Outside 的 _task 槽位,可叠加在战内 UI 之上
EventManager.Publish(new ShowUIOutsideWiki());
}
private void OnTabButtonClicked()
{
SetTabButtonVisible(CheckHasTabUnit(out var grid));
if (grid == null) return;
// Tab 切换单位前先清掉所有 attack/ally 高亮,避免目标 unit 被当作技能目标释放技能
Main.Instance.MapInteractionLogic.CancelAllHighlight();
Main.Instance.MapInteractionLogic.OnTileClicked(Main.MapData,grid);
}
public void CloseView()
{
AudioManager.Instance.StopMusic();
}
public void UpdateHeroButtonAvatar()
{
if (Main.MapData?.PlayerMap?.SelfPlayerData?.PlayerHeroData == null) return;
bool newHero = Main.MapData.PlayerMap.SelfPlayerData.PlayerHeroData.GetHeroButtonHint();
HeroButtonTextHint.SetActive(newHero);
HeroButtonIconHint.SetActive(newHero);
HeroButtonAvatar.sprite = Main.MapData.PlayerMap.SelfPlayerData.PlayerHeroData.GetHeroButtonSprite();
}
public void ExecuteButtonClick(Button button)
{
var pointer = new PointerEventData(EventSystem.current);
var go = button.gameObject;
ExecuteEvents.Execute(go, pointer, ExecuteEvents.pointerDownHandler);
ExecuteEvents.Execute(go, pointer, ExecuteEvents.pointerUpHandler);
button.onClick.Invoke();
}
public void HideBottomBarNextTurn()
{
//HideButton(TechButton);
//HideButton(HeroButton);
HideButton(NextButton);
}
public void HideBottomBarTabUnit()
{
//HideButton(TechButton);
//HideButton(HeroButton);
HideButton(TabButton);
}
public void ShowBottomBarTabUnit()
{
//HideButton(TechButton);
//HideButton(HeroButton);
ShowButton(TabButton);
}
public void ShowBottomBarNextTurn()
{
//ShowButton(TechButton);
ShowButton(NextButton);
//ShowButton(HeroButton);
}
public void SetTechButtonVisible(bool visible)
{
if(visible)ShowButton(TechButton);
else HideButton(TechButton);
}
public void SetHeroButtonVisible(bool visible)
{
if(visible)ShowButton(HeroButton);
else HideButton(HeroButton);
}
// 每个 Button 的最新可见意图 token。每次 Show/Hide 调用递增;
// HideButton 在 OnEnd 里比对 token若期间已经被新的 Show/Hide 覆盖则不再 SetActive(false)
// 避免 FadeOut 动画的旧 OnEnd 把已经 ShowButton 显示出来的按钮又关掉
// NextTurn 按钮联机模式不显示的根因之一)。
private readonly Dictionary<Button, int> _buttonVisibleToken = new Dictionary<Button, int>();
private void HideButton(Button t)
{
_buttonVisibleToken.TryGetValue(t, out var token);
token++;
_buttonVisibleToken[t] = token;
int snapshot = token;
var cpn = t.GetComponent<AnimancerComponent>();
if (cpn == null)
{
t.gameObject.SetActive(false);
return;
}
var state = cpn.Play(ResourceCache.Instance.AnimCache.UICommonPanelFadeOut);
state.Events.OnEnd = () =>
{
// 仅在期间没有新的 Show/Hide 覆盖时才真正隐藏
if (_buttonVisibleToken.TryGetValue(t, out var cur) && cur == snapshot)
t.gameObject.SetActive(false);
state.Events.OnEnd = null;
};
}
private void ShowButton(Button t)
{
_buttonVisibleToken.TryGetValue(t, out var token);
_buttonVisibleToken[t] = token + 1;
t.gameObject.SetActive(true);
var cpn = t.GetComponent<AnimancerComponent>();
if (cpn == null) return;
cpn.Play(ResourceCache.Instance.AnimCache.UICommonPanelFadeIn);
}
}
}