Forest_Client/Forest/Assets/Editor/GameBuild/GameBuildWindow.cs

354 lines
13 KiB
C#

using System;
using System.IO;
using UnityEditor;
using UnityEngine;
using Framework.Manager;
using Sirenix.Utilities;
using Framework.GameBuild;
using Sirenix.OdinInspector;
using Sirenix.Utilities.Editor;
using System.Collections.Generic;
using UnityEngine.SceneManagement;
using UnityEditor.SceneManagement;
using Sirenix.OdinInspector.Editor;
public class GameBuildWindow : OdinEditorWindow
{
[Serializable]
public class NodeEditor
{
[LabelText("挂点")] [ReadOnly] public string name;
[LabelText("选项实例")] [HideInInspector] public List<GameObject> optionObj;
[LabelText("选项资源路径")] [ReadOnly] public string optionPath = "Assets/Art/GameBuild/Texture";
[HideInInspector] public BuildData.BuildNode BuildNode;
public NodeEditor(string name, int count)
{
this.name = name;
optionObj = new List<GameObject>();
}
}
private const string NodeRootPath = "BuildRoot";
private const string NodeTemplatePath = "Assets/Art/GameBuild/Prefab/Node.prefab";
private const string OptionTemplatePath = "Option";
private const string NodeName = "Node{0}";
private const string OptionName = "Option{0}";
private const string BtnBubble = "Btn";
private const int BuildItemLayer = 10;
private const string BuildTexturePath = "Assets/Art/GameBuild/Texture/{0}";
/// <summary>
/// 当前窗口
/// </summary>
private static GameBuildWindow _curWindow;
/// <summary>
/// 当前建造编辑器数据
/// </summary>
private BuildEditor _buildEditor;
private readonly List<GameObject> _tempNodeObj = new List<GameObject>();
[LabelText("当前建造数据")] [VerticalGroup("BuildInfo")]
public BuildData curBuildData;
[LabelText("当前建造资源文件夹")] [VerticalGroup("BuildInfo")] [FolderPath]
public string buildDataPath;
/// <summary>
/// 打开窗口
/// </summary>
public static void OpenWindow(BuildEditor buildEditor)
{
_curWindow = GetWindow<GameBuildWindow>();
_curWindow.position = GUIHelper.GetEditorWindowRect().AlignCenter(800, 600);
_curWindow._buildEditor = buildEditor;
_curWindow.LoadBuildData(buildEditor.BuildData);
}
private void LoadBuildData(BuildData buildData)
{
editorNodeResource = false;
var assetName = _buildEditor.BuildDataJson.name;
buildDataPath = string.Format(BuildTexturePath, assetName.Replace(".json", ""));
DebugUtil.LogError("问价家:{0}", buildDataPath);
_curWindow.curBuildData = buildData;
curBuildData.buildID = GameBuildUtils.GetFileNameWithoutExtension(_buildEditor.BuildDataJson.name);
var root = GameObject.Find(NodeRootPath);
if (buildData.NodeInfos == null)
{
DebugUtil.LogError("需要重启该场景");
return;
}
editorNodes = new List<NodeEditor>(buildData.nodeCount);
foreach (var node in buildData.NodeInfos)
{
var nodeObj = root.transform.Find(node.Name).gameObject;
if (nodeObj != null)
{
var editorNode = new NodeEditor(node.Name, buildData.thematicCount);
foreach (Transform child in nodeObj.transform)
{
if (!child.gameObject.name.Equals(BtnBubble))
{
editorNode.optionObj.Add(child.gameObject);
}
}
editorNode.BuildNode = node;
if (!string.IsNullOrEmpty(node.IconPath))
editorNode.optionPath = node.IconPath.Replace("Icon/{0}.png", "Normal");
editorNodes.Add(editorNode);
}
}
_tempNodeObj.Clear();
foreach (Transform child in root.transform)
{
_tempNodeObj.Add(child.gameObject);
}
}
[VerticalGroup("BuildInfo/Create")]
[Button("生成挂点实例")]
[InfoBox("会重新创建物体!!! 需要重新调整位置")]
public void Create()
{
if (string.IsNullOrEmpty(buildDataPath) || !Directory.Exists(buildDataPath)) return;
string[] directories = Directory.GetDirectories(buildDataPath);
curBuildData.nodeCount = directories.Length;
var iconPaths = new Dictionary<string, string>();
var optionPaths = new Dictionary<string, string>();
var optionCount = new int[curBuildData.nodeCount];
for (int i = 0; i < curBuildData.nodeCount; i++)
{
var nodePath = directories[i];
var nodeName = Path.GetFileName(nodePath);
//图标路径
var iconDir = Path.Combine(nodePath, "Icon");
var iconPath = Path.Combine("Assets", Path.GetFullPath(iconDir).Substring(Application.dataPath.Length + 1));
iconPaths.Add(nodeName, iconPath);
//选项路径
var normalDir = Path.Combine(nodePath, "Normal");
var normalPath = Path.Combine("Assets",
Path.GetFullPath(normalDir).Substring(Application.dataPath.Length + 1));
optionPaths.Add(nodeName, normalPath);
//选项数量
var optionFiles = Directory.GetFiles(normalDir, "*.png");
optionCount[i] = optionFiles.Length;
DebugUtil.LogError("挂点:{2},选项路径:{0},图标路径:{1}", normalPath, iconPath, nodeName);
}
if (optionCount.Length > 0)
{
curBuildData.thematicCount = optionCount[0];
DebugUtil.LogError("有挂点:{0} 个", curBuildData.thematicCount);
}
UpdateNode(iconPaths, optionPaths);
}
private void UpdateNode(Dictionary<string, string> iconPaths, Dictionary<string, string> optionPaths)
{
editorNodeResource = false;
if (editorNodes != null)
editorNodes.Clear();
switch (curBuildData.unlockType)
{
case UnlockType.ForGroup:
InitBuildInfo(curBuildData.nodeCount, iconPaths);
break;
case UnlockType.ForThematic:
InitBuildInfo(curBuildData.thematicCount, iconPaths);
break;
default:
DebugUtil.LogError("解锁条件错误");
break;
}
CreateNodeObj(optionPaths);
}
/// <summary>
/// 初始化建造数据
/// </summary>
private void InitBuildInfo(int count, Dictionary<string, string> iconPaths)
{
//挂点初始化
curBuildData.NodeInfos = new List<BuildData.BuildNode>(curBuildData.nodeCount);
for (int i = 0; i < curBuildData.nodeCount; i++)
{
var nodeName = string.Format(NodeName, i + 1);
if (!iconPaths.TryGetValue(nodeName, out var iconPath))
{
DebugUtil.LogError("没有检测到{0}的选项图标路径!!!", nodeName);
}
else
{
iconPath = iconPath.Replace("Icon", "Icon/{0}.png");
}
var node = new BuildData.BuildNode
{
Name = nodeName,
IconPath = iconPath
};
curBuildData.NodeInfos.Add(node);
}
//解锁条件初始化
curBuildData.unlockInfos = new List<BuildData.UnlockInfo>(count);
for (int i = 0; i < count; i++)
{
var unlock = new BuildData.UnlockInfo();
curBuildData.unlockInfos.Add(unlock);
}
}
/// <summary>
/// 创建实例挂点
/// </summary>
private void CreateNodeObj(Dictionary<string, string> optionPaths)
{
//清除
DeleteNode();
var root = GameObject.Find(NodeRootPath);
editorNodes = new List<NodeEditor>(curBuildData.nodeCount);
var nodeTemplate = AssetDatabase.LoadAssetAtPath<GameObject>(NodeTemplatePath);
foreach (var node in curBuildData.NodeInfos)
{
//生成节点
var nodeObj = Instantiate(nodeTemplate, root.transform);
nodeObj.name = node.Name;
_tempNodeObj.Add(nodeObj);
//生成选项
node.Options = new List<string>(curBuildData.thematicCount);
var optionTemplate = nodeObj.transform.Find(OptionTemplatePath).gameObject;
var tempEditorNode = new NodeEditor(node.Name, curBuildData.thematicCount);
for (int i = 0; i < curBuildData.thematicCount; i++)
{
var optionObj = Instantiate(optionTemplate, nodeObj.transform);
optionObj.name = string.Format(OptionName, i + 1);
tempEditorNode.optionObj.Add(optionObj);
node.Options.Add(optionObj.name);
if (i != 0)
optionObj.SetActive(false);
}
if (optionPaths.TryGetValue(node.Name, out var optionPath))
{
tempEditorNode.optionPath = optionPath;
}
else
{
DebugUtil.LogError("没有检测到{0}的选项路径!!!", node.Name);
}
tempEditorNode.BuildNode = node;
editorNodes.Add(tempEditorNode);
DestroyImmediate(optionTemplate);
//置顶泡泡按钮 UI操作
/*var btn = nodeObj.transform.Find(BtnBubble);
btn.transform.SetSiblingIndex(curBuildData.thematicCount);*/
}
}
[VerticalGroup("Node")] [LabelText("编辑挂点资源")]
public bool editorNodeResource;
[VerticalGroup("Node/Info")] [LabelText("挂点资源")] [ShowIf("@editorNodeResource")]
public List<NodeEditor> editorNodes;
[VerticalGroup("Node/NodeCreate")]
[Button("填充挂点资源")]
[ShowIf("@editorNodeResource")]
public void CreateNodeResource()
{
var sortingOrder = curBuildData.nodeCount;
foreach (var editorNode in editorNodes)
{
//加载路径下的资源
var fileEntries = Directory.GetFiles(editorNode.optionPath, "*.png");
var spriteList = new List<Sprite>();
foreach (var filePath in fileEntries)
{
var assetPath = filePath.Replace(Application.dataPath, "").Replace('\\', '/');
var sprite = AssetDatabase.LoadAssetAtPath<Sprite>(assetPath);
if (sprite != null)
{
spriteList.Add(sprite);
}
}
//应用资源
for (var i = 0; i < editorNode.optionObj.Count; i++)
{
if (i < spriteList.Count)
{
var spriteSize = new Vector2(spriteList[i].texture.width, spriteList[i].texture.height);
var option = editorNode.optionObj[i];
//UI处理
/*var normalObj = option.transform.Find("Normal").gameObject.GetComponent<Image>();
normalObj.sprite = spriteList[i];
var rect = normalObj.GetComponent<RectTransform>();
rect.sizeDelta = spriteSize;*/
var normalObj = option.transform.Find("Normal").gameObject;
var normalSprite = normalObj.GetComponent<SpriteRenderer>();
normalSprite.sortingOrder = sortingOrder;
normalSprite.sprite = spriteList[i];
normalObj.AddComponent<PolygonCollider2D>();
normalObj.layer = BuildItemLayer;
var btn = option.transform.parent.Find(BtnBubble);
btn.GetComponent<SpriteRenderer>().sortingOrder = sortingOrder;
}
}
sortingOrder--;
//初始化Icon资源路径
editorNode.BuildNode.IconPath = editorNode.optionPath.Replace("Normal", "Icon/{0}.png");
}
}
[VerticalGroup("Save")]
[Button("保存")]
public void Save()
{
_buildEditor.SaveData();
//保存场景
var activeScene = SceneManager.GetActiveScene();
var saveResult = EditorSceneManager.SaveScene(activeScene);
if (!saveResult)
DebugUtil.LogError("保存失败!!!");
}
private void DeleteNode()
{
foreach (var obj in _tempNodeObj)
{
DestroyImmediate(obj);
}
_tempNodeObj.Clear();
}
}