TH1/Unity/Assets/Scripts/TH1_UI/View/Outside/UIOutsideLibraryHeroPanelMono.cs

474 lines
18 KiB
C#

using System;
using System.Collections.Generic;
using Animancer;
using Logic.Multilingual;
using RuntimeData;
using TH1_UI.HintUI;
using TH1Resource;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
namespace TH1_UI.View.Outside
{
public class UIOutsideLibraryHeroPanelMono : MonoBehaviour
{
public TextMeshProUGUI TopTitle;
public Image Illustration;
public TextMeshProUGUI Name;
public TextMeshProUGUI CivName;
public Image CivBG;
public RectTransform CivRect;
public TextMeshProUGUI Desc;
public TextMeshProUGUI Dialogue;
public Image DialogueAvatar;
public List<UIOutsideLibraryAchieveItemMono> AchieveItems;
public Button SettingTabButton;
public Button BattleTabButton;
public Image SettingTabBG;
public Image BattleTabBG;
public RectTransform SettingContentRoot;
public RectTransform BattleContentRoot;
public Sprite TabButtonSprite;
public Button CloseButton;
public Button LeftButton;
public Button RightButton;
public AnimancerComponent Animancer;
private const string HeroHintPanelPath = "Prefab/UI/Hint/HeroHintPanel";
private const string TabButtonSpritePath = "TH1UI/Common/CommonButton/ItemButtonBG";
private static readonly Color SelectedTabColor = new Color(0.42f, 0.22f, 0.42f, 1f);
private static readonly Color NormalTabColor = new Color(1f, 1f, 1f, 0.88f);
private static readonly Color SelectedTabTextColor = Color.white;
private static readonly Color NormalTabTextColor = new Color(0.25f, 0.23f, 0.42f, 1f);
private GiantType _currentGiantType = GiantType.None;
private HeroHintPanel _battlePanel;
private enum HeroPanelTab
{
Setting,
Battle
}
public void Init(Action onStartClick)
{
EnsureTabStructure();
BindTabButtons();
}
public bool SetContent(GiantType giantType)
{
if (!ContentGate.CanShowHeroIntroduction(giantType)) return false;
if (!Table.Instance.LibraryDataAssets.GetLibraryInfoByGiant(giantType, out var info)) return false;
if (!Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(new UnitFullType(UnitType.Giant, giantType, 1),
out var unitInfo)) return false;
var empire = unitInfo.GiantEmpire;
if (!Table.Instance.PlayerDataAssets.GetPlayerInfo(empire, out var playerInfo)) return false;
_currentGiantType = giantType;
EnsureTabStructure();
BindTabButtons();
SetUITextOrRaw(TopTitle,info.Name);
Illustration.sprite = info.Illust;
SetUITextOrRaw(Name,info.Name);
SetUITextOrRaw(CivName,playerInfo.CivName);
CivBG.color = playerInfo.Color;
SetUITextOrRaw(Desc,info.Desc);
SetUITextOrRaw(Dialogue,info.Diag);
DialogueAvatar.sprite = unitInfo.Sprite;
//Step #3 设定成就
SetAchieveItems(giantType);
CloseButton.onClick.RemoveAllListeners();
CloseButton.onClick.AddListener(Hide);
SelectTab(HeroPanelTab.Setting);
return true;
}
private void BindTabButtons()
{
if (SettingTabButton != null)
{
SettingTabButton.onClick.RemoveAllListeners();
SettingTabButton.onClick.AddListener(() => SelectTab(HeroPanelTab.Setting));
}
if (BattleTabButton != null)
{
BattleTabButton.onClick.RemoveAllListeners();
BattleTabButton.onClick.AddListener(() => SelectTab(HeroPanelTab.Battle));
}
}
private void EnsureTabStructure()
{
if (SettingTabButton != null &&
BattleTabButton != null &&
SettingContentRoot != null &&
BattleContentRoot != null)
{
SettingTabBG ??= SettingTabButton.GetComponent<Image>();
BattleTabBG ??= BattleTabButton.GetComponent<Image>();
return;
}
var infoRoot = Name != null ? Name.transform.parent as RectTransform : null;
if (infoRoot == null) return;
var tabRoot = EnsureRect(infoRoot, "TabRoot");
tabRoot.SetAsFirstSibling();
tabRoot.anchorMin = new Vector2(0f, 1f);
tabRoot.anchorMax = new Vector2(0f, 1f);
tabRoot.pivot = new Vector2(0f, 1f);
tabRoot.anchoredPosition = new Vector2(40f, -76f);
tabRoot.sizeDelta = new Vector2(316f, 52f);
ConfigureHorizontalLayout(tabRoot, 12f);
ConfigureIgnoredLayoutElement(tabRoot.gameObject);
SettingTabButton = EnsureTabButton(tabRoot, "SettingTabButton", "设定", true);
BattleTabButton = EnsureTabButton(tabRoot, "BattleTabButton", "战斗", false);
SettingTabBG = SettingTabButton.GetComponent<Image>();
BattleTabBG = BattleTabButton.GetComponent<Image>();
SettingContentRoot = EnsureRect(infoRoot, "SettingContentRoot");
SettingContentRoot.SetSiblingIndex(1);
ConfigureVerticalLayout(SettingContentRoot);
ConfigureLayoutElement(SettingContentRoot.gameObject, 0f, -1f, 1f);
BattleContentRoot = EnsureRect(infoRoot, "BattleContentRoot");
BattleContentRoot.SetSiblingIndex(2);
ConfigureVerticalLayout(BattleContentRoot);
ConfigureLayoutElement(BattleContentRoot.gameObject, 0f, -1f, 1f);
BattleContentRoot.gameObject.SetActive(false);
MoveIntoSettingRoot(infoRoot, "Name");
MoveIntoSettingRoot(infoRoot, "CivName");
MoveIntoSettingRoot(infoRoot, "DescTitle");
MoveIntoSettingRoot(infoRoot, "DescText");
MoveIntoSettingRoot(infoRoot, "DialogGroup");
MoveIntoSettingRoot(infoRoot, "AchieveTitle");
MoveIntoSettingRoot(infoRoot, "AchieveGroup");
}
private RectTransform EnsureRect(Transform parent, string objectName)
{
var existing = parent.Find(objectName) as RectTransform;
if (existing != null) return existing;
var go = new GameObject(objectName, typeof(RectTransform));
go.layer = parent.gameObject.layer;
var rect = go.GetComponent<RectTransform>();
rect.SetParent(parent, false);
rect.anchorMin = Vector2.zero;
rect.anchorMax = Vector2.one;
rect.pivot = new Vector2(0.5f, 0.5f);
rect.anchoredPosition = Vector2.zero;
rect.sizeDelta = Vector2.zero;
return rect;
}
private Button EnsureTabButton(RectTransform parent, string objectName, string label, bool selected)
{
var rect = EnsureRect(parent, objectName);
rect.gameObject.SetActive(true);
ConfigureLayoutElement(rect.gameObject, 142f, 46f, -1f);
TabButtonSprite ??= ResourceLoader.Load<Sprite>(TabButtonSpritePath);
var image = rect.GetComponent<Image>();
if (image == null) image = rect.gameObject.AddComponent<Image>();
image.sprite = TabButtonSprite;
image.type = image.sprite != null && image.sprite.border != Vector4.zero
? Image.Type.Sliced
: Image.Type.Simple;
image.color = selected ? SelectedTabColor : NormalTabColor;
image.raycastTarget = true;
var button = rect.GetComponent<Button>();
if (button == null) button = rect.gameObject.AddComponent<Button>();
button.transition = Selectable.Transition.ColorTint;
button.targetGraphic = image;
var textRect = EnsureRect(rect, "Text");
textRect.anchorMin = Vector2.zero;
textRect.anchorMax = Vector2.one;
textRect.offsetMin = Vector2.zero;
textRect.offsetMax = Vector2.zero;
var text = textRect.GetComponent<TextMeshProUGUI>();
if (text == null) text = textRect.gameObject.AddComponent<TextMeshProUGUI>();
text.text = label;
if (Name != null && Name.font != null) text.font = Name.font;
text.fontSize = 26f;
text.color = selected ? SelectedTabTextColor : NormalTabTextColor;
text.alignment = TextAlignmentOptions.Center;
text.raycastTarget = false;
var multilingual = textRect.GetComponent<MultilingualTextMono>();
if (multilingual == null) multilingual = textRect.gameObject.AddComponent<MultilingualTextMono>();
multilingual.Ban = true;
multilingual.NoExport = true;
multilingual.FontBan = true;
multilingual.ID = 0;
return button;
}
private void MoveIntoSettingRoot(RectTransform infoRoot, string childName)
{
if (SettingContentRoot == null) return;
var child = infoRoot.Find(childName);
if (child == null || child == SettingContentRoot) return;
child.SetParent(SettingContentRoot, false);
}
private static void ConfigureHorizontalLayout(RectTransform rect, float spacing)
{
var layout = rect.GetComponent<HorizontalLayoutGroup>();
if (layout == null) layout = rect.gameObject.AddComponent<HorizontalLayoutGroup>();
layout.padding = new RectOffset(0, 0, 0, 0);
layout.childAlignment = TextAnchor.MiddleLeft;
layout.spacing = spacing;
layout.childControlWidth = false;
layout.childControlHeight = false;
layout.childForceExpandWidth = false;
layout.childForceExpandHeight = false;
}
private static void ConfigureVerticalLayout(RectTransform rect)
{
var layout = rect.GetComponent<VerticalLayoutGroup>();
if (layout == null) layout = rect.gameObject.AddComponent<VerticalLayoutGroup>();
layout.padding = new RectOffset(0, 0, 0, 0);
layout.childAlignment = TextAnchor.UpperLeft;
layout.spacing = 0f;
layout.childControlWidth = true;
layout.childControlHeight = false;
layout.childForceExpandWidth = true;
layout.childForceExpandHeight = false;
}
private static void ConfigureLayoutElement(GameObject go, float preferredWidth, float preferredHeight, float flexibleHeight)
{
var element = go.GetComponent<LayoutElement>();
if (element == null) element = go.AddComponent<LayoutElement>();
element.ignoreLayout = false;
element.preferredWidth = preferredWidth;
element.preferredHeight = preferredHeight;
element.flexibleHeight = flexibleHeight;
}
private static void ConfigureIgnoredLayoutElement(GameObject go)
{
var element = go.GetComponent<LayoutElement>();
if (element == null) element = go.AddComponent<LayoutElement>();
element.ignoreLayout = true;
}
private void SelectTab(HeroPanelTab tab)
{
if (SettingContentRoot != null) SettingContentRoot.gameObject.SetActive(tab == HeroPanelTab.Setting);
if (BattleContentRoot != null) BattleContentRoot.gameObject.SetActive(tab == HeroPanelTab.Battle);
SetTabVisual(SettingTabBG, tab == HeroPanelTab.Setting);
SetTabVisual(BattleTabBG, tab == HeroPanelTab.Battle);
SetTabTextVisual(SettingTabButton, tab == HeroPanelTab.Setting);
SetTabTextVisual(BattleTabButton, tab == HeroPanelTab.Battle);
if (tab == HeroPanelTab.Battle) RefreshBattlePanel();
}
private static void SetTabVisual(Image image, bool selected)
{
if (image == null) return;
image.color = selected ? SelectedTabColor : NormalTabColor;
}
private static void SetTabTextVisual(Button button, bool selected)
{
if (button == null) return;
var text = button.GetComponentInChildren<TextMeshProUGUI>(true);
if (text == null) return;
text.color = selected ? SelectedTabTextColor : NormalTabTextColor;
}
private void RefreshBattlePanel()
{
if (_currentGiantType == GiantType.None || BattleContentRoot == null) return;
if (_battlePanel == null)
{
var prefab = ResourceLoader.Load<GameObject>(HeroHintPanelPath);
if (prefab == null) return;
var go = Instantiate(prefab, BattleContentRoot, false);
go.name = "BattleHeroHintPanel";
_battlePanel = go.GetComponent<HeroHintPanel>();
if (_battlePanel == null) return;
_battlePanel.SetEmbeddedMode(true, true);
var rect = go.GetComponent<RectTransform>();
if (rect != null)
{
rect.anchorMin = new Vector2(0f, 1f);
rect.anchorMax = new Vector2(0f, 1f);
rect.pivot = new Vector2(0f, 1f);
rect.anchoredPosition = Vector2.zero;
rect.localScale = Vector3.one;
}
}
_battlePanel.gameObject.SetActive(true);
_battlePanel.SetEmbeddedMode(true, true);
_battlePanel.SetHeroInfo(_currentGiantType);
}
public void SetNavigationButtons(bool canMoveLeft, bool canMoveRight, Action onLeftClick, Action onRightClick)
{
EnsureNavigationButtons();
SetNavigationButton(LeftButton, canMoveLeft, onLeftClick);
SetNavigationButton(RightButton, canMoveRight, onRightClick);
}
private void EnsureNavigationButtons()
{
if (LeftButton == null)
{
LeftButton = FindNavigationButton("LeftButton");
}
if (RightButton == null)
{
RightButton = FindNavigationButton("RightButton");
}
}
private Button FindNavigationButton(string buttonName)
{
var buttons = GetComponentsInChildren<Button>(true);
for (int i = 0; i < buttons.Length; i++)
{
if (buttons[i] != null && buttons[i].name == buttonName) return buttons[i];
}
return null;
}
private static void SetNavigationButton(Button button, bool active, Action onClick)
{
if (button == null) return;
button.gameObject.SetActive(active);
button.onClick.RemoveAllListeners();
if (active && onClick != null) button.onClick.AddListener(() => onClick.Invoke());
}
private static void SetUITextOrRaw(TextMeshProUGUI text, string value)
{
if (text == null) return;
var multilingual = text.gameObject.GetComponent<MultilingualTextMono>();
if (string.IsNullOrEmpty(value))
{
if (multilingual != null)
{
multilingual.ID = 0;
multilingual.Ban = true;
}
text.text = string.Empty;
return;
}
if (uint.TryParse(value, out _))
{
if (multilingual != null) multilingual.Ban = false;
MultilingualManager.Instance.SetUIText(text, value);
}
else
{
if (multilingual != null)
{
multilingual.ID = 0;
multilingual.Ban = true;
}
text.text = value;
}
}
private void SetAchieveItems(GiantType giantType)
{
if (AchieveItems.Count != 3) return;
if (!UIOutsideLibraryAchievementVisibility.ShouldShowHeroAchievements(giantType))
{
SetAchievementSectionActive(false);
return;
}
if (!AchievementDataManager.Instance.GetSmallIdByGiantType(giantType, out var smallid))
{
SetAchievementSectionActive(false);
return;
}
SetAchievementSectionActive(true);
for (int i = 0; i < 3; i++)
{
AchieveItems[i].gameObject.SetActive(true);
AchieveItems[i].SetContent(2,smallid,(uint)i + 1);
}
}
private void SetAchievementSectionActive(bool active)
{
Transform group = null;
if (AchieveItems.Count > 0 && AchieveItems[0] != null)
group = AchieveItems[0].transform.parent;
if (group != null)
{
group.gameObject.SetActive(active);
var title = group.parent != null ? group.parent.Find("AchieveTitle") : null;
if (title != null) title.gameObject.SetActive(active);
}
for (int i = 0; i < AchieveItems.Count; i++)
{
if (AchieveItems[i] != null) AchieveItems[i].gameObject.SetActive(active);
}
}
public void Show()
{
gameObject.SetActive(true);
LayoutRebuilder.ForceRebuildLayoutImmediate(CivRect);
Animancer.Play(ResourceCache.Instance.AnimCache.UICommonPanelFadeIn);
}
public void Hide()
{
var state = Animancer.Play(ResourceCache.Instance.AnimCache.UICommonPanelFadeOut);
state.Events.OnEnd = () => { gameObject.SetActive(false); };
}
void Start()
{
}
// Update is called once per frame
void Update()
{
}
}
}