TH1/Unity/Assets/Scripts/TH1_UI/View/Info/UIInfoGridInfoView.cs
2025-11-26 23:36:09 +08:00

574 lines
21 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 Logic.Skill;
using RuntimeData;
using TH1_Core.Events;
using TH1_Core.Managers;
using TH1_Logic.Core;
using TH1_UI.Components;
using TH1_UI.HintUI;
using TH1Renderer;
using TH1Resource;
using TMPro;
using UI.HintUI;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.UI;
namespace TH1_UI.View.Info
{
public class UIInfoGridInfoView : Base.View
{
public Button closeButton;
public ViDelegateAssisstant.Dele OnBtnCloseClick;
[Header("GridInfo相关")]
public GameObject GridInfoArea;
public GameObject GridPreview;
public GameObject GridCamera;
public TextMeshProUGUI GridInfoTitle;
public TextMeshProUGUI GridInfoDesc;
public TextMeshProUGUI GridInfoTerrainTxt;
public TextMeshProUGUI GridInfoResourceTxt;
public TextMeshProUGUI GridInfoBuildingTxt;
[Header("CityInfo相关")]
public GameObject CityInfoArea;
public GameObject CityPreview;
public GameObject CityCamera;
public GameObject CityInfoDataArea;
public TextMeshProUGUI CityInfoTitle;
public TextMeshProUGUI CityInfoDesc;
public TextMeshProUGUI CityInfoCoinTxt;
public TextMeshProUGUI CityInfoTechTxt;
public TextMeshProUGUI CityInfoDiamondTxt;
public TextMeshProUGUI CityInfoPopulationTxt;
public TextMeshProUGUI CityInfoConnectTxt;
[Header("UnitInfo相关")]
public GameObject UnitInfoArea;
public GameObject UnitPreview;
public GameObject SkillArea;
public TextMeshProUGUI UnitInfoTitle;
public TextMeshProUGUI UnitInfoDesc;
public TextMeshProUGUI UnitInfoAttackTxt;
public TextMeshProUGUI UnitInfoDefendTxt;
public TextMeshProUGUI UnitInfoHealthTxt;
public TextMeshProUGUI UnitInfoMoveTxt;
public TextMeshProUGUI UnitInfoRangeTxt;
[Header("CommonInfo相关")]
public GameObject AvatarArea;
public GameObject AvatarHint;
public GameObject Avatar;
public GameObject AvatarTitleArea;
public TextMeshProUGUI AvatarTitle;
public Image AvatarImg;
public Button AvatarBtn;
public GameObject TaskArea;
public GameObject ActionArea;
public TextMeshProUGUI ActionHint;
public RectTransform VerticalGroup;
public GameObject ActionCirclePrefab;
public GameObject SkillCirclePrefab;
private List<UIInfoCommonBaseActionCircleMono> ActionCircleMonoList = null;
private List<UIInfoCommonBaseSkillCircleMono> SkillCircleMonoList = null;
protected override void InitStart()
{
base.InitStart();
ActionCircleMonoList = new List<UIInfoCommonBaseActionCircleMono>();
SkillCircleMonoList = new List<UIInfoCommonBaseSkillCircleMono>();
ActionAreaInit();
SkillAreaInit();
closeButton.onClick.RemoveAllListeners();
closeButton.onClick.AddListener(() => { OnBtnCloseClick.Invoke(); });
//CheckPanel.InitStart(RefreshStatus);
}
//清除所有actioncircle,重新开始生成
private void ActionAreaInit()
{
if (gameObject == null) return;
for (int i = ActionArea.transform.childCount - 1; i >= 0; i--)
{
Transform child = ActionArea.transform.GetChild(i);
// 判断组件是否存在
if (child.GetComponent<UIInfoCommonBaseActionCircleMono>() != null)
{
// 正确调用 Destroy 方法,销毁子对象的 GameObject
Destroy(child.gameObject);
}
}
ActionCircleMonoList.Clear();
ActionCircleMonoList = new List<UIInfoCommonBaseActionCircleMono>();
}
private void SkillAreaInit()
{
if (gameObject == null) return;
for (int i = SkillArea.transform.childCount - 1; i >= 0; i--)
{
Transform child = SkillArea.transform.GetChild(i);
// 判断组件是否存在
if (child.GetComponent<UIInfoCommonBaseSkillCircleMono>() != null)
{
// 正确调用 Destroy 方法,销毁子对象的 GameObject
Destroy(child.gameObject);
}
}
SkillCircleMonoList.Clear();
SkillCircleMonoList = new List<UIInfoCommonBaseSkillCircleMono>();
}
public void SetContent(ShowUIInfoGridInfo evt)
{
SetContentAvatar(evt);
SetContentGrid(evt);
SetContentUnit(evt);
SetContentCity(evt);
SetContentSkill(evt);
SetContentAction(evt);
SetContentTask(evt);
LayoutRebuilder.ForceRebuildLayoutImmediate(VerticalGroup);
}
private void SetContentAvatar(ShowUIInfoGridInfo evt)
{
AvatarArea.SetActive(true);
PlayerData player = null;
switch (evt.type)
{
case UIGridInfoType.grid: // City is on a grid, so its ID is a GID
Main.MapData.GetPlayerDataByTerritoryGridId(evt.id, out player);
break;
case UIGridInfoType.unit:
Main.MapData.GetPlayerDataByUnitId(evt.id, out player);
break;
}
if (player == null || !Table.Instance.PlayerDataAssets.GetPlayerInfo(player, out var info))
{
AvatarTitleArea.SetActive(false);
AvatarHint.SetActive(false);
Avatar.SetActive(false);
return;
}
AvatarTitleArea.SetActive(true);
AvatarHint.SetActive(true);
Avatar.SetActive(true);
if(!Main.MapData.PlayerMap.SelfPlayerData.MeetPlayers.Contains(player.Id))
{
AvatarBtn.onClick.RemoveAllListeners();
AvatarImg.sprite = Table.Instance.PlayerDataAssets.CommonPlayerAvatar;
AvatarTitle.text = "???";
LayoutRebuilder.ForceRebuildLayoutImmediate(AvatarTitleArea.GetComponent<RectTransform>());
return;
}
AvatarImg.sprite = info.LeaderAvatar;
MultilingualManager.Instance.SetUIText(AvatarTitle,info.ForceName);
LayoutRebuilder.ForceRebuildLayoutImmediate(AvatarTitleArea.GetComponent<RectTransform>());
AvatarBtn.onClick.RemoveAllListeners();
AvatarBtn.onClick.AddListener(() =>
{
EventManager.Publish(new ShowUIInfoDiplomacy() { Pid = player.Id });
OnBtnCloseClick.Invoke();
});
}
private void SetContentGrid(ShowUIInfoGridInfo evt)
{
if (evt.type != UIGridInfoType.grid || !Main.MapData.GridMap.GetGridDataByGid(evt.id, out var grid) || Main.MapData.GetCityDataByGid(evt.id, out var _))
{
GridInfoArea.SetActive(false);
return;
}
GridInfoArea.SetActive(true);
//Step #1 GridPreview
GameObject clone =
Instantiate(MapRenderer.Instance.ROGridMap[evt.id].GetROGrid() as GameObject);
for (int i = GridPreview.transform.childCount - 1; i >= 0; i--)
Destroy(GridPreview.transform.GetChild(i).gameObject);
clone.transform.SetParent(GridPreview.transform);
clone.transform.localPosition = new Vector3(0,15,0);
clone.transform.Find("SelectHighlight").gameObject.SetActive(false);
SetLayerRecursively(clone, LayerMask.NameToLayer("Preview"));
GridCamera.SetActive(true);
Timer.Instance.TimerRegister(GridCamera, () => { CityCamera.SetActive(false); }, 0.001f,"HideCamera");
//Step #2 Title & Desc
//title 逻辑 -> building > resource > forest > mountain > plain
string title = "";
string desc = "";
//如果显示建筑或者资源
if (grid.Resource != ResourceType.None && Main.MapData.PlayerMap.SelfPlayerData.CanShowResource(grid.Resource))
{
title = Table.Instance.GridAndResourceDataAssets.GetResourceNameWithLevel(grid);
//var spr = Table.Instance.GridAndResourceDataAssets.GetResourceSprite(grid.Resource, grid.Player(Main.MapData), grid);
Table.Instance.GridAndResourceDataAssets.GetResourceInfo(grid.Resource, out var resourceInfo);
desc = resourceInfo.ResourceDesc;
}
//如果显示树木
else if(grid.Vegetation == Vegetation.Trees)
{
Table.Instance.GridAndResourceDataAssets.GetVegetationInfo(out var vegetationInfo);
title = vegetationInfo.ResourceName;
desc = vegetationInfo.ResourceDesc;
}
//如果显示山脉
else if(grid.Feature == TerrainFeature.Mountain)
{
Table.Instance.GridAndResourceDataAssets.GetMountainInfo(out var mountainInfo);
title = mountainInfo.ResourceName;
desc = mountainInfo.ResourceDesc;
}
//如果显示地形
else
{
Table.Instance.GridAndResourceDataAssets.GetTerrainInfo(grid.Terrain, out var terrainInfo);
title = terrainInfo.ResourceName;
desc = terrainInfo.ResourceDesc;
}
MultilingualManager.Instance.SetUIText(GridInfoTitle, title);
MultilingualManager.Instance.SetUIText(GridInfoDesc, desc);
//Step #3 设置详细info
//resource
if (grid.Resource != ResourceType.None && Table.Instance.GridAndResourceDataAssets.GetResourceInfo(grid.Resource, out var resourceInfo2))
{
if (resourceInfo2.ResourceSubType == ResourceSubType.Building)
{
MultilingualManager.Instance.SetUIText(GridInfoBuildingTxt,Table.Instance.GridAndResourceDataAssets.GetResourceNameWithLevel(grid));
//处理盖在建筑下面的资源
if (grid.ResourceUnderBuilding != ResourceType.None &&
Table.Instance.GridAndResourceDataAssets.GetResourceInfo(grid.ResourceUnderBuilding,
out var resourceInfo3) && resourceInfo3.ResourceSubType == ResourceSubType.Resource)
MultilingualManager.Instance.SetUIText(GridInfoResourceTxt,
Table.Instance.GridAndResourceDataAssets.GetResourceName(grid.ResourceUnderBuilding));
else GridInfoResourceTxt.text = "-";
}
else
{
GridInfoBuildingTxt.text = "-";
if(Main.MapData.PlayerMap.SelfPlayerData.CanShowResource(grid.Resource))
MultilingualManager.Instance.SetUIText(GridInfoResourceTxt, Table.Instance.GridAndResourceDataAssets.GetResourceName(grid.Resource));
else GridInfoResourceTxt.text = "-";
}
}
else
{
GridInfoBuildingTxt.text = "-";
GridInfoResourceTxt.text = "-";
}
//terrain
if (grid.Feature == TerrainFeature.Mountain)
{
Table.Instance.GridAndResourceDataAssets.GetMountainInfo(out var mountainInfo);
MultilingualManager.Instance.SetUIText(GridInfoTerrainTxt, mountainInfo.ResourceName);
}
else if (grid.Vegetation == Vegetation.Trees)
{
Table.Instance.GridAndResourceDataAssets.GetVegetationInfo(out var vegetationInfo);
MultilingualManager.Instance.SetUIText(GridInfoTerrainTxt, vegetationInfo.ResourceName);
}
else
{
Table.Instance.GridAndResourceDataAssets.GetTerrainInfo(grid.Terrain,out var terrainInfo);
MultilingualManager.Instance.SetUIText(GridInfoTerrainTxt, terrainInfo.ResourceName);
}
}
private void SetContentUnit(ShowUIInfoGridInfo evt)
{
if (evt.type != UIGridInfoType.unit || !Main.MapData.UnitMap.GetUnitDataByUnitId(evt.id, out var unitData))
{
UnitInfoArea.SetActive(false);
return;
}
UnitInfoArea.SetActive(true);
// 获取关联数据
Main.MapData.GetPlayerDataByUnitId(unitData.Id, out var playerData);
Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(unitData.UnitFullType, out var unitTypeInfo);
// Step #1: Unit Preview (Placeholder, assumes a 2D sprite on an Image component)
// 清理旧的预览
for (int i = UnitPreview.transform.childCount - 1; i >= 0; i--)
Destroy(UnitPreview.transform.GetChild(i).gameObject);
// 这里假设预览是一个简单的Image你需要根据你的UnitPreview Prefab结构调整
// 例如var previewImage = Instantiate(SomePrefab, UnitPreview.transform).GetComponent<Image>();
// previewImage.sprite = Table.Instance.QueryUnitSprite(unitData.UnitType, unitData.GiantType, unitData.Level, playerData);
// Step #2: Title & Description
// 逻辑参考 BottomInfoUI.cs -> UpdateInfoUnit
string title = MultilingualManager.Instance.GetMultilingualText(uint.Parse(unitTypeInfo.Name));
if (unitData.Veteran) title += " (已升级)"; // 示例
MultilingualManager.Instance.SetUIText(UnitInfoTitle, title);
MultilingualManager.Instance.SetUIText(UnitInfoDesc, unitTypeInfo.Desc);
// Step #3: Core Stats
UnitInfoHealthTxt.text = $"{unitData.Health}/{unitData.GetMaxHealth()}";
UnitInfoAttackTxt.text = unitData.GetAttackShowString(Main.MapData);
UnitInfoDefendTxt.text = unitData.GetDefenseShowString(Main.MapData); // 参照BottomInfoUI
UnitInfoMoveTxt.text = unitData.GetMoveRange().ToString();
UnitInfoRangeTxt.text = unitData.GetAttackRange().ToString();
}
private void SetContentCity(ShowUIInfoGridInfo evt)
{
if (evt.type != UIGridInfoType.grid || !Main.MapData.GetCityDataByGid(evt.id,out var city)
|| !Main.MapData.GetPlayerDataByCityId(city.Id, out var player))
{
CityInfoArea.SetActive(false);
return;
}
CityInfoArea.SetActive(true);
// Step 1: Preview (Placeholder)
GameObject clone =
Instantiate(MapRenderer.Instance.ROGridMap[evt.id].GetROGrid() as GameObject);
for (int i = CityPreview.transform.childCount - 1; i >= 0; i--)
Destroy(CityPreview.transform.GetChild(i).gameObject);
clone.transform.SetParent(CityPreview.transform);
clone.transform.localPosition = new Vector3(0,15,0);
clone.transform.Find("SelectHighlight").gameObject.SetActive(false);
SetLayerRecursively(clone, LayerMask.NameToLayer("Preview"));
CityCamera.SetActive(true);
Timer.Instance.TimerRegister(CityCamera, () => { CityCamera.SetActive(false); }, 0.001f,"HideCamera");
// Step 2: Title & Description
Table.Instance.CivDataAssets.GetCityInfo(city.Name, out var cityInfo);
CityInfoTitle.text = MultilingualManager.Instance.GetMultilingualText(uint.Parse(cityInfo.CityName)) + " Lv." + city.Level;
MultilingualManager.Instance.SetUIText(CityInfoDesc, cityInfo.CityDescription);
// Step 3: Detailed Info (differs for self vs. others)
if (player.Id == Main.MapData.PlayerMap.SelfPlayerData.Id)
{
CityInfoDataArea.SetActive(true);
var tb = Table.Instance.TextDataAssets;
CityInfoCoinTxt.text = "+" + Main.CityLogic.GetCityStarsPerTurn(Main.MapData, city)+ MultilingualManager.Instance.GetMultilingualText(uint.Parse(tb.GridInfoText_PerTurn));
CityInfoTechTxt.text = "+" + Main.CityLogic.GetCityTechPointPerTurn(Main.MapData, city) + MultilingualManager.Instance.GetMultilingualText(uint.Parse(tb.GridInfoText_PerTurn));
CityInfoPopulationTxt.text = MultilingualManager.Instance.GetMultilingualText(uint.Parse(tb.GridInfoText_Population)) + Main.MapData.GetUnitCount(city.Id) + "/" + city.Level;
CityInfoDiamondTxt.text = (city.ParkCount + (city.Workshop ? 1 : 0)) + MultilingualManager.Instance.GetMultilingualText(uint.Parse(tb.GridInfoText_Diamond));
CityInfoConnectTxt.text = city.IsCapital ? MultilingualManager.Instance.GetMultilingualText(uint.Parse(tb.GridInfoText_Capital)) : (city.IsConnectedCapital ? MultilingualManager.Instance.GetMultilingualText(uint.Parse(tb.GridInfoText_Connected)) :
MultilingualManager.Instance.GetMultilingualText(uint.Parse(tb.GridInfoText_Unconnected)));
}
else
CityInfoDataArea.SetActive(false);
}
private void SetContentSkill(ShowUIInfoGridInfo evt)
{
if (evt.type != UIGridInfoType.unit)
{
SkillArea.SetActive(false);
return;
}
if (!Main.MapData.UnitMap.GetUnitDataByUnitId(evt.id, out var unit)) return;
var skillList = new List<SkillBase>();
foreach (var skill in unit.Skills)
{
if(!Table.Instance.SkillDataAssets.GetSkillInfo(skill.GetSkillType(), out var info)
|| info.NotShow)continue;
skillList.Add(skill);
}
if (skillList.Count == 0)
{
SkillArea.SetActive(false);
return;
}
SkillArea.SetActive(true);
//Step #2 确定格位够不够
while (SkillCircleMonoList.Count < skillList.Count)
{
GameObject actionCircle = Instantiate(SkillCirclePrefab, SkillArea.transform, true);
actionCircle.GetComponent<RectTransform>().localScale = Vector3.one;
actionCircle.GetComponent<RectTransform>().localPosition = Vector3.zero;
SkillCircleMonoList.Add(actionCircle.GetComponent<UIInfoCommonBaseSkillCircleMono>());
}
//Step #3 设置每一个action
for (int i = 0; i < SkillCircleMonoList.Count; i++)
{
SkillCircleMonoList[i].gameObject.SetActive(i < skillList.Count);
if (i >= skillList.Count) continue;
SkillCircleMonoList[i].SetContent(skillList[i]);
}
}
private void SetContentAction(ShowUIInfoGridInfo evt)
{
//Step #1 获取actionList
//ResourceCache.Instance.SpriteCache.ActionBGAvailable
var actionList = new List<ActionLogicBase>();
bool showAction = false;
var subType = evt.type;
CommonActionParams param = null;
if (subType == UIGridInfoType.unit && Main.MapData.UnitMap.GetUnitDataByUnitId(evt.id,out var unit))
{
param = new CommonActionParams(mapData:Main.MapData,playerData:Main.MapData.PlayerMap.SelfPlayerData,unitData:unit,mainObjectType:MainObjectType.Unit);
showAction = ActionLogicFactory.MainObjectCanShowAction(param, out actionList);
MultilingualManager.Instance.SetUIText(ActionHint,Table.Instance.TextDataAssets.GridInfoText_UnitInfoHint);
}
else if (subType == UIGridInfoType.grid && Main.MapData.GetCityDataByGid(evt.id,out var city))
{
param = new CommonActionParams(mapData:Main.MapData,playerData:Main.MapData.PlayerMap.SelfPlayerData,cityData:city,mainObjectType:MainObjectType.City);
showAction = ActionLogicFactory.MainObjectCanShowAction(param,out actionList);
MultilingualManager.Instance.SetUIText(ActionHint,Table.Instance.TextDataAssets.GridInfoText_CityInfoHint);
}
else if (subType == UIGridInfoType.grid && Main.MapData.GridMap.GetGridDataByGid(evt.id,out var grid))
{
param = new CommonActionParams(mapData:Main.MapData,Main.MapData.PlayerMap.SelfPlayerData,gridData:grid,mainObjectType:MainObjectType.Grid);
showAction = ActionLogicFactory.MainObjectCanShowAction(param,out actionList);
if(grid.Resource is ResourceType.Military or ResourceType.RemiliaMilitary)
MultilingualManager.Instance.SetUIText(ActionHint,Table.Instance.TextDataAssets.GridInfoText_CityInfoHint);
MultilingualManager.Instance.SetUIText(ActionHint,Table.Instance.TextDataAssets.GridInfoText_GridInfoHint);
}
if (!showAction)
{
ActionArea.SetActive(false);
return;
}
ActionArea.SetActive(true);
//Step #2 确定格位够不够
while (ActionCircleMonoList.Count < actionList.Count)
{
GameObject actionCircle = Instantiate(ActionCirclePrefab, ActionArea.transform, true);
actionCircle.GetComponent<RectTransform>().localScale = Vector3.one;
actionCircle.GetComponent<RectTransform>().localPosition = Vector3.zero;
ActionCircleMonoList.Add(actionCircle.GetComponent<UIInfoCommonBaseActionCircleMono>());
}
//Step #3 设置每一个action
for (int i = 0; i < ActionCircleMonoList.Count; i++)
{
ActionCircleMonoList[i].gameObject.SetActive(i < actionList.Count);
if (i >= actionList.Count) continue;
ActionCircleMonoList[i].SetContent(actionList[i].ActionId,param,OnActionCircleClicked);
}
}
private void OnActionCircleClicked(CommonActionId actionId, CommonActionParams param)
{
var action = ActionLogicFactory.GetActionLogic(actionId);
if (action.CheckCan(param) && action.CompleteExecute(param))
OnBtnCloseClick();
}
private void SetLayerRecursively(GameObject obj, int newLayer)
{
obj.layer = newLayer;
foreach (Transform child in obj.transform)
{
SetLayerRecursively(child.gameObject, newLayer);
}
}
private void SetContentTask(ShowUIInfoGridInfo evt)
{
if (evt.type != UIGridInfoType.unit ||
!Main.MapData.UnitMap.GetUnitDataByUnitId(evt.id, out var unitData) ||
!Main.MapData.GetPlayerDataByUnitId(evt.id, out var playerData))
{
TaskArea.SetActive(false);
return;
}
// 参考 BottomInfoUI -> UpdateInfoUnit -> Step #6 设置MissionDesc
bool shouldShowTask = unitData.UnitType == UnitType.Giant &&
unitData.UnitLevel < 3 && // 假设最大等级为3
playerData.Id == Main.MapData.PlayerMap.SelfPlayerId;
if (!shouldShowTask)
{
TaskArea.SetActive(false);
return;
}
TaskArea.SetActive(true);
var missionDescText = TaskArea.transform.Find("TaskDesc")?.GetComponent<TextMeshProUGUI>(); // 假设任务描述文本组件路径
if (missionDescText == null)
{
Debug.LogError("TaskArea is missing 'TaskDesc' child with TextMeshProUGUI component.");
TaskArea.SetActive(false);
return;
}
if (!Table.Instance.HeroDataAssets.GetHeroInfo(unitData.GiantType, out var heroInfo) ||
heroInfo.TaskList.Count <= unitData.UnitLevel ||
!Main.MapData.PlayerMap.SelfPlayerData.PlayerHeroData.GetHeroTask(unitData.GiantType, out var task))
{
TaskArea.SetActive(false);
return;
}
if (task.IsForceFinished)
{
MultilingualManager.Instance.SetUIText(missionDescText, Table.Instance.TextDataAssets.HeroTaskFinishedDesc);
}
else
{
var param1 = task.LevelShowString();
var param2 = task.TargetLevelShowString();
var param3 = "";
if (task.SkillType != SkillType.NONE && Table.Instance.SkillDataAssets.GetSkillInfo(task.SkillType, out var skillInfo))
{
param3 = MultilingualManager.Instance.GetMultilingualText(uint.Parse(skillInfo.SkillName));
}
var taskDesc = heroInfo.TaskList[(int)unitData.UnitLevel].Desc;
MultilingualManager.Instance.SetUIText(missionDescText, taskDesc, new List<string> { param1, param2, param3 });
}
}
public void CloseView()
{
AudioManager.Instance.StopMusic();
}
}
}