Forest_Client/Forest/Assets/Scripts/Gameplay2/GameBuild/BuildBoot.cs

711 lines
22 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using TMPro;
using System;
using PhxhSDK;
using UnityEngine;
using Framework.UI;
using UnityEngine.UI;
using Gameplay.Level;
using Framework.Event;
using Gameplay.Manager;
using Framework.Manager;
using Sirenix.OdinInspector;
using System.Collections.Generic;
public class BuildBoot : MonoBehaviour
{
[LabelText("当前条件")] public int CurCondition;
/// <summary>
/// 节点类
/// </summary>
private class Node
{
public string Name;
public GameObject NodeObj;
public GameObject BubbleObj;
public Dictionary<string, Option> Options;
public Node(GameObject root)
{
Name = root.name;
Options = new Dictionary<string, Option>();
foreach (Transform child in root.transform)
{
if (!child.gameObject.name.Equals("Btn"))
{
var option = new Option(child.gameObject);
Options.Add(child.gameObject.name, option);
}
else
{
BubbleObj = child.gameObject;
}
}
}
public Option GetOption(string optionName)
{
return Options.GetValueOrDefault(optionName);
}
/// <summary>
/// 关闭其他选项表现
/// </summary>
public void OptionDisplay(Option option)
{
if (option == null)
{
CloseAllOptionButBubble(true);
return;
}
foreach (var optionInfo in Options.Values)
{
optionInfo.SetOptionActive(option);
}
BubbleObj.SetActive(false);
}
public void CloseAllOptionButBubble(bool butBubble)
{
foreach (var optionInfo in Options.Values)
{
optionInfo.SetOptionActive(false);
}
BubbleObj.SetActive(butBubble);
}
}
/// <summary>
/// 选项类
/// </summary>
private class Option
{
public string Name;
public GameObject NodeObj;
public GameObject OptionObj;
public GameObject NormalObj;
public Option(GameObject root)
{
Name = root.name;
NodeObj = root.transform.parent.gameObject;
OptionObj = root;
NormalObj = root.transform.Find("Normal").gameObject;
}
public void SetOptionActive(Option option)
{
if (option == null)
{
OptionObj.SetActive(false);
return;
}
OptionObj.SetActive(Name.Equals(option.Name));
}
public void SetOptionActive(bool active)
{
OptionObj.SetActive(active);
}
}
/// <summary>
/// 物品栏类
/// </summary>
private class BuildBar
{
private GameObject _bar;
private Dictionary<string, BuildItem> _buildItem;
private Dictionary<string, Transform> _itemTrans;
private TMP_Text _condition;
private const string ContentPath = "Bar_Tip/Scroll View/Viewport/Content";
private const string IconItemTemplate = "Bar_Tip/Scroll View/Viewport/Content/Item";
private const string TipPath = "Bar_Tip";
private const string ConditionText = "Level\n{0}/{1}";
private const string ItemName = "Item{0}";
private readonly Color _lockColor = new Color(152f / 255f, 0f, 0f);
private readonly Color _unlockColor = new Color(255f, 255f, 255f);
private Action<Option> _optionCallBack;
public BuildBar(GameObject root)
{
_bar = root;
_condition = root.transform.Find(TipPath).GetComponent<TMP_Text>();
_buildItem = new Dictionary<string, BuildItem>();
_itemTrans = new Dictionary<string, Transform>();
}
public void Open(Node node, Action<Option> callBack, Action lockCallBack, int reachCondition, int condition)
{
_optionCallBack = callBack;
_bar.SetActive(true);
_condition.text = string.Format(ConditionText, reachCondition, condition);
_condition.color = reachCondition < condition ? _lockColor : _unlockColor;
var content = _bar.transform.Find(ContentPath);
var iconTemplate = _bar.transform.Find(IconItemTemplate);
_buildItem.Clear();
var index = 1;
foreach (var option in node.Options)
{
var optionName = option.Value.OptionObj.name;
var iconName = string.Format(ItemName, index);
if (!_itemTrans.TryGetValue(iconName, out var iconItem))
{
iconItem = Instantiate(iconTemplate, content);
iconItem.name = iconName;
_itemTrans.Add(iconName, iconItem);
}
iconItem.gameObject.SetActive(true);
var sprite = BuildManager.Instance.GetOptionIcon(node.Name, optionName);
var unlock = reachCondition >= condition;
var item = new BuildItem(iconItem.gameObject, option.Value);
_buildItem.Add(optionName, item);
item.SetInfo(sprite, unlock, ItemCallBack, lockCallBack);
index++;
//DebugUtil.Log("Bar添加物品Icon{0}", iconItem.name);
}
}
private void ItemCallBack(Option option)
{
_optionCallBack?.Invoke(option);
PickItemDisplay(option.OptionObj.name);
}
public void PickItemDisplay(string optionName)
{
foreach (var item in _buildItem)
{
item.Value.SetPickActive(item.Key.Equals(optionName));
}
}
public void Close()
{
_bar.SetActive(false);
foreach (var item in _buildItem)
{
item.Value.SetPickActive(false);
}
}
}
/// <summary>
/// 物品栏Icon类
/// </summary>
private class BuildItem
{
public Option Option;
private Button _btn;
private Button _lockBtn;
private Image _imgIcon;
private GameObject _lock;
private GameObject _imgPick;
public BuildItem(GameObject root, Option option)
{
this.Option = option;
_btn = root.transform.Find("Img_Item").GetComponent<Button>();
_imgIcon = root.transform.Find("Img_Item").GetComponent<Image>();
_lock = root.transform.Find("Img_Lock").gameObject;
_lockBtn = _lock.GetComponent<Button>();
_imgPick = root.transform.Find("Bg_Pick").gameObject;
}
public void SetInfo(Sprite sprite, bool unlock, Action<Option> callBack, Action lockCallBack)
{
_lock.SetActive(!unlock);
_btn.onClick.RemoveAllListeners();
_btn.onClick.AddListener(() => { callBack?.Invoke(Option); });
_lockBtn.onClick.RemoveAllListeners();
_lockBtn.onClick.AddListener(() => { lockCallBack?.Invoke(); });
_imgIcon.sprite = sprite;
}
public void SetPickActive(bool pick)
{
_imgPick.SetActive(pick);
}
}
//适配安全区
private GameObject _topLiuHai;
private GameObject _bottomLiuHai;
private Vector2 _offsets;
//物品栏
private BuildBar _buildBar;
private Button _btnBarClose;
private Button _btnBarYes;
//当前点击的泡泡按钮
private GameObject _curBubble;
//当前选择的选项
private Option _newOption;
private Option _curOption;
private Node _curNode;
//当前节点条件
private int _curCondition;
//当前节点字典
private Dictionary<string, Node> _nodes;
//提示弹窗
private GameObject _tipObj;
private Button _btnTipGoGame;
private Button _btnTipClose;
private TMP_Text _txtTip;
//遮罩
private GameObject _mask;
private bool _isChanging;
private GameObject _pickItem;
private SpriteRenderer _pickSpriteRenderer;
//UI界面
private GameObject _uiMainBuild;
private void Awake()
{
RegisterEvent();
InitUI();
InitBuildData();
}
private void Start()
{
InitCamera();
InitScreenAdaption();
UpdateScreenAdaption();
UpdateBuildDisplay();
}
private void OnDisable()
{
UnregisterClickEvent();
}
#region Build相关
/// <summary>
/// 初始化建造物数据
/// </summary>
private void InitBuildData()
{
_nodes = new Dictionary<string, Node>();
var nodeRoot = GameObject.Find("BuildRoot");
foreach (Transform child in nodeRoot.transform)
{
var node = new Node(child.gameObject);
_nodes.Add(child.name, node);
}
}
/// <summary>
/// 刷新建造物表现
/// </summary>
private void UpdateBuildDisplay()
{
var chooseNodeInfo = BuildManager.Instance.BuildInfo.ChooseNodeInfo;
if (chooseNodeInfo == null || chooseNodeInfo.Count <= 0)
{
DebugUtil.LogError("Build Boot: 玩家在该场景的建造信息获取错误");
return;
}
/*foreach (var choose in BuildManager.Instance.BuildInfo.ChooseNodeInfo)
{
DebugUtil.LogError("{0} 的选择为: {1}", choose.Key, choose.Value);
}*/
CurCondition = BuildManager.Instance.ReachCondition < 0
? CurCondition
: BuildManager.Instance.ReachCondition;
var nextLockNode = BuildManager.Instance.GetNextLockNode();
if (string.IsNullOrEmpty(nextLockNode))
{
foreach (var chooseNode in chooseNodeInfo)
{
if (_nodes.TryGetValue(chooseNode.Key, out var node))
{
var option = node.GetOption(chooseNode.Value);
node.OptionDisplay(option);
}
}
}
else
{
foreach (var node in _nodes)
{
if (!chooseNodeInfo.TryGetValue(node.Key, out var unlockNode)) return;
//已选择节点
if (!string.IsNullOrEmpty(unlockNode))
{
var option = node.Value.GetOption(unlockNode);
node.Value.OptionDisplay(option);
}
//需解锁节点
else if (node.Key.Equals(nextLockNode) && string.IsNullOrEmpty(unlockNode))
{
_curBubble = node.Value.BubbleObj;
node.Value.CloseAllOptionButBubble(true);
}
//未解锁
else if (!node.Key.Equals(nextLockNode) && string.IsNullOrEmpty(unlockNode))
{
node.Value.CloseAllOptionButBubble(false);
}
}
}
}
#endregion
#region UI相关
/// <summary>
/// 初始化相机 区别游戏内外
/// </summary>
private void InitCamera()
{
if (BuildManager.Instance.CurBuildCamera == null) return;
GameObject.Find("BuildCamera").Destroy();
var canvas = transform.Find("BuildUIRoot").GetComponent<Canvas>();
canvas.worldCamera = BuildManager.Instance.CurBuildCamera;
}
/// <summary>
/// 初始化屏幕适配
/// </summary>
private void InitScreenAdaption()
{
var offset = DeviceHelper.GetHeightOffset();
_bottomLiuHai = transform.Find("BuildUIRoot/UIMainBuild/UI_LiuHaiBottom").gameObject;
_topLiuHai = transform.Find("BuildUIRoot/UIMainBuild/UI_LiuHaiTop").gameObject;
if (_topLiuHai)
{
var rectTrans = _topLiuHai.GetComponent<RectTransform>();
var originPos = rectTrans.anchoredPosition;
_offsets = new Vector2(originPos.y - offset.x, 0);
}
if (_bottomLiuHai)
{
var rectTrans = _bottomLiuHai.GetComponent<RectTransform>();
var originPos = rectTrans.anchoredPosition;
_offsets = new Vector2(_offsets.x, originPos.y + offset.y);
}
}
/// <summary>
/// 更新屏幕适配
/// </summary>
private void UpdateScreenAdaption()
{
if (_topLiuHai)
{
var rectTrans = _topLiuHai.GetComponent<RectTransform>();
var originPos = rectTrans.anchoredPosition;
rectTrans.anchoredPosition = new Vector2(originPos.x, _offsets.x);
}
if (_bottomLiuHai)
{
var rectTrans = _bottomLiuHai.GetComponent<RectTransform>();
var originPos = rectTrans.anchoredPosition;
rectTrans.anchoredPosition = new Vector2(originPos.x, _offsets.y);
}
}
/// <summary>
/// 初始化UI
/// </summary>
private void InitUI()
{
var otherRoot = GameObject.Find("OtherRoot").gameObject;
_mask = otherRoot.transform.Find("Mask").gameObject;
_pickItem = GameObject.Find("OtherRoot/PickItem").gameObject;
_pickSpriteRenderer = _pickItem.GetComponent<SpriteRenderer>();
_uiMainBuild = transform.Find("BuildUIRoot/UIMainBuild").gameObject;
InitTipPanel();
InitBuildBar();
}
/// <summary>
/// 初始化上锁提示界面
/// </summary>
private void InitTipPanel()
{
_tipObj = transform.Find("BuildUIRoot/UIMainBuild/Build_Tip").gameObject;
_btnTipClose = _tipObj.transform.Find("Btn_Close").GetComponent<Button>();
_btnTipGoGame = _tipObj.transform.Find("Btn_Game").GetComponent<Button>();
_btnTipClose.onClick.AddListener(CloseTipPanel);
_btnTipGoGame.onClick.AddListener(TipGoGame);
_txtTip = _tipObj.transform.Find("Text_Content").GetComponent<TMP_Text>();
}
/// <summary>
/// 初始化物品栏
/// </summary>
private void InitBuildBar()
{
var bar = transform.Find("BuildUIRoot/UIMainBuild/UI_LiuHaiBottom/Build_Bar").gameObject;
_btnBarClose = bar.transform.Find("Btn_Close").GetComponent<Button>();
_btnBarClose.onClick.AddListener(CloseBar);
_btnBarYes = bar.transform.Find("Btn_Yes").GetComponent<Button>();
_btnBarYes.onClick.AddListener(YesBar);
_buildBar = new BuildBar(bar);
}
/// <summary>
/// 关闭提示界面
/// </summary>
private void CloseTipPanel()
{
_tipObj.SetActive(false);
BuildManager.Instance.PlaySound();
}
/// <summary>
/// 开始游戏
/// </summary>
private void TipGoGame()
{
var levelID = $"level{LevelSelectManager.Instance.CurPassLevelIndex + 1}";
if (LevelManager.Instance.IsLevelExist(levelID))
{
GameStateManager.Instance.ChangeState(new LevelState(levelID));
EventManager.Instance.Send(EventManager.EventName.EnterGame);
}
BuildManager.Instance.PlaySound();
}
/// <summary>
/// 关闭物品栏
/// </summary>
private void CloseBar()
{
BuildManager.Instance.PlaySound();
_isChanging = false;
_buildBar.Close();
_mask.SetActive(false);
_pickItem.SetActive(false);
if (_curBubble != null)
_curBubble.SetActive(true);
EventManager.Instance.Send(EventManager.EventName.ShowMainUI);
//放弃修改
if (_curNode == null) return;
_curNode.OptionDisplay(_curOption);
_curNode = null;
_curOption = null;
_newOption = null;
}
/// <summary>
/// 保存更改
/// </summary>
private void YesBar()
{
BuildManager.Instance.PlaySound();
_isChanging = false;
_mask.SetActive(false);
_pickItem.SetActive(false);
_buildBar.Close();
EventManager.Instance.Send(EventManager.EventName.CloseUI);
EventManager.Instance.Send(EventManager.EventName.ShowMainUI);
if (_curNode == null || _newOption == null)
{
_curBubble?.SetActive(true);
return;
}
//DebugUtil.LogError("保存更改,当前节点:{0},当前选项:{1}", _curNode.Name, _newOption.Name);
BuildManager.Instance.SaveNodeInfo(_curNode.Name, _newOption.Name);
_curNode = null;
_curOption = null;
_newOption = null;
_curBubble = null;
UpdateBuildDisplay();
}
private void ShowUI()
{
_uiMainBuild.SetActive(true);
if (_curBubble != null)
_curBubble.SetActive(true);
}
private void HideUI()
{
_uiMainBuild.SetActive(false);
if (_curBubble != null)
_curBubble.SetActive(false);
}
#endregion
#region 点击事件
/// <summary>
/// 建造物节点点击
/// </summary>
private void OnBuildItemClick(GameObject obj)
{
if (_isChanging) return;
_isChanging = true;
_mask.SetActive(true);
EventManager.Instance.Send(EventManager.EventName.HideMainUI);
var optionObj = obj.transform.parent.gameObject;
var nodeName = optionObj.transform.parent.name;
var optionName = optionObj.name;
BuildManager.Instance.PlaySound();
if (_nodes.TryGetValue(nodeName, out var node))
{
_curNode = node;
_curOption = node.GetOption(optionName);
_curCondition = BuildManager.Instance.GetCondition(nodeName);
_buildBar.Open(node, BuildIconClick, BuildLockIconClick, CurCondition, _curCondition);
_buildBar.PickItemDisplay(optionName);
if (_curOption != null)
OutlinePickItem(_curOption);
EventManager.Instance.Send(EventManager.EventName.OpenUI);
}
else
{
DebugUtil.LogError("节点获取信息错误: {0}", nodeName);
}
}
/// <summary>
/// 泡泡点击
/// </summary>
private void OnBuildBubbleClick(GameObject obj)
{
if (_isChanging) return;
_isChanging = true;
_mask.SetActive(true);
_curBubble = obj;
obj.SetActive(false);
var nodeName = obj.transform.parent.name;
EventManager.Instance.Send(EventManager.EventName.HideMainUI);
BuildManager.Instance.PlaySound();
if (_nodes.TryGetValue(nodeName, out var node))
{
_curCondition = BuildManager.Instance.GetCondition(nodeName);
_curNode = node;
_buildBar.Open(node, BuildIconClick, BuildLockIconClick, CurCondition, _curCondition);
EventManager.Instance.Send(EventManager.EventName.OpenUI);
}
else
{
DebugUtil.LogError("节点获取信息错误: {0}", nodeName);
}
}
/// <summary>
/// 解锁图标点击
/// </summary>
private void BuildIconClick(Option option)
{
EventManager.Instance.Send(EventManager.EventName.ChangeBuild);
if (option == _newOption)
return;
var nodeName = option.NodeObj.name;
//切换UI表现
if (_nodes.TryGetValue(nodeName, out var node))
{
foreach (var optionInfo in node.Options.Values)
{
optionInfo.OptionObj.SetActive(option.Name.Equals(optionInfo.Name));
}
}
_newOption = option;
BuildManager.Instance.PlaySound();
OutlinePickItem(option);
//DebugUtil.LogError("点击了{0}节点的{1}选项", nodeName, option.OptionObj.name);
}
/// <summary>
/// 未解锁图标点击
/// </summary>
private void BuildLockIconClick()
{
var keyString = StringManager.Instance.GetTextByKey("Build_Tip");
var content = string.Format(keyString, _curCondition);
_txtTip.text = content;
_mask.SetActive(true);
_tipObj.SetActive(true);
BuildManager.Instance.PlaySound();
EventManager.Instance.Send(EventManager.EventName.OpenUI);
}
/// <summary>
/// 描边展示
/// </summary>
private void OutlinePickItem(Option option)
{
_pickItem.SetActive(true);
_pickItem.transform.position = option.OptionObj.transform.position;
_pickSpriteRenderer.sprite =
option.NormalObj.GetComponent<SpriteRenderer>().sprite;
}
private void UpdateReachCondition()
{
//TODO 不同类型的条件
CurCondition = LevelSelectManager.Instance.CurPassLevelIndex;
BuildManager.Instance.UpdateReachCondition(CurCondition);
}
#endregion
private void RegisterEvent()
{
InputManager.Instance.OnBuildItemClick += OnBuildItemClick;
InputManager.Instance.OnBuildBubbleClick += OnBuildBubbleClick;
EventManager.Instance.Register(EventManager.EventName.HideBuildUI, HideUI);
EventManager.Instance.Register(EventManager.EventName.ShowBuildUI, ShowUI);
EventManager.Instance.Register(EventManager.EventName.ChangeBuildScene, UpdateBuildDisplay);
EventManager.Instance.Register(EventManager.EventName.RefreshGameData, UpdateReachCondition);
}
private void UnregisterClickEvent()
{
if (InputManager.Instance)
{
InputManager.Instance.OnBuildItemClick -= OnBuildItemClick;
InputManager.Instance.OnBuildBubbleClick -= OnBuildBubbleClick;
}
EventManager.Instance.Unregister(EventManager.EventName.HideBuildUI, HideUI);
EventManager.Instance.Unregister(EventManager.EventName.ShowBuildUI, ShowUI);
EventManager.Instance.Unregister(EventManager.EventName.ChangeBuildScene, UpdateBuildDisplay);
EventManager.Instance.Unregister(EventManager.EventName.RefreshGameData, UpdateReachCondition);
}
}