2024-07-10 19:06:07 +08:00
|
|
|
using System;
|
2024-07-11 14:45:15 +08:00
|
|
|
using System.IO;
|
|
|
|
using UnityEditor;
|
|
|
|
using UnityEngine;
|
|
|
|
using UnityEngine.UI;
|
2024-07-10 19:06:07 +08:00
|
|
|
using Framework.Manager;
|
|
|
|
using Sirenix.Utilities;
|
2024-07-11 14:45:15 +08:00
|
|
|
using Framework.GameBuild;
|
|
|
|
using Sirenix.OdinInspector;
|
2024-07-10 19:06:07 +08:00
|
|
|
using Sirenix.Utilities.Editor;
|
2024-07-11 14:45:15 +08:00
|
|
|
using System.Collections.Generic;
|
|
|
|
using UnityEngine.SceneManagement;
|
|
|
|
using UnityEditor.SceneManagement;
|
|
|
|
using Sirenix.OdinInspector.Editor;
|
2024-07-10 19:06:07 +08:00
|
|
|
|
|
|
|
public class GameBuildWindow : OdinEditorWindow
|
|
|
|
{
|
|
|
|
[Serializable]
|
|
|
|
public class NodeEditor
|
|
|
|
{
|
|
|
|
[LabelText("挂点")] [ReadOnly] public string name;
|
|
|
|
|
|
|
|
[LabelText("选项数量")] [ReadOnly] public int count;
|
|
|
|
|
2024-07-11 14:45:15 +08:00
|
|
|
[LabelText("选项实例")] public List<GameObject> optionObj;
|
|
|
|
|
2024-07-11 16:14:51 +08:00
|
|
|
[LabelText("选项资源路径")] [FolderPath] public string optionPath = "Assets/Art/GameBuild/Texture";
|
|
|
|
|
|
|
|
[HideInInspector] public BuildData.BuildNode BuildNode;
|
2024-07-10 19:06:07 +08:00
|
|
|
|
|
|
|
public NodeEditor(string name, int count)
|
|
|
|
{
|
|
|
|
this.name = name;
|
|
|
|
this.count = count;
|
2024-07-11 14:45:15 +08:00
|
|
|
optionObj = new List<GameObject>();
|
2024-07-10 19:06:07 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-07-17 17:56:02 +08:00
|
|
|
private const string NodeRootPath = "BuildRoot";
|
2024-07-10 19:06:07 +08:00
|
|
|
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}";
|
2024-07-11 14:45:15 +08:00
|
|
|
private const string BtnBubble = "Btn";
|
2024-07-12 17:10:33 +08:00
|
|
|
private const int BuildItemLayer = 10;
|
2024-07-10 19:06:07 +08:00
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// 当前窗口
|
|
|
|
/// </summary>
|
|
|
|
private static GameBuildWindow _curWindow;
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// 当前建造编辑器数据
|
|
|
|
/// </summary>
|
|
|
|
private BuildEditor _buildEditor;
|
|
|
|
|
2024-07-11 16:14:51 +08:00
|
|
|
private List<GameObject> _tempNodeObj = new List<GameObject>();
|
|
|
|
|
2024-07-10 19:06:07 +08:00
|
|
|
[LabelText("当前建造数据")] [VerticalGroup("BuildInfo")]
|
|
|
|
public BuildData curBuildData;
|
|
|
|
|
2024-07-11 14:45:15 +08:00
|
|
|
/// <summary>
|
|
|
|
/// 打开窗口
|
|
|
|
/// </summary>
|
2024-07-10 19:06:07 +08:00
|
|
|
public static void OpenWindow(BuildEditor buildEditor)
|
|
|
|
{
|
|
|
|
_curWindow = GetWindow<GameBuildWindow>();
|
|
|
|
_curWindow.position = GUIHelper.GetEditorWindowRect().AlignCenter(800, 600);
|
|
|
|
_curWindow._buildEditor = buildEditor;
|
2024-07-11 14:45:15 +08:00
|
|
|
_curWindow.LoadBuildData(buildEditor.BuildData);
|
2024-07-10 19:06:07 +08:00
|
|
|
}
|
|
|
|
|
2024-07-11 14:45:15 +08:00
|
|
|
private void LoadBuildData(BuildData buildData)
|
|
|
|
{
|
|
|
|
_curWindow.curBuildData = buildData;
|
2024-07-17 18:56:07 +08:00
|
|
|
curBuildData.buildID = GameBuildUtils.GetFileNameWithoutExtension(_buildEditor.BuildDataJson.name);
|
2024-07-11 14:45:15 +08:00
|
|
|
var root = GameObject.Find(NodeRootPath);
|
2024-07-17 18:56:07 +08:00
|
|
|
if (buildData.NodeInfos == null)
|
2024-07-17 17:56:02 +08:00
|
|
|
{
|
|
|
|
DebugUtil.LogError("需要重启该场景");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-07-11 14:45:15 +08:00
|
|
|
editorNodes = new List<NodeEditor>(buildData.nodeCount);
|
2024-07-17 18:56:07 +08:00
|
|
|
foreach (var node in buildData.NodeInfos)
|
2024-07-11 14:45:15 +08:00
|
|
|
{
|
2024-07-17 18:56:07 +08:00
|
|
|
var nodeObj = root.transform.Find(node.Name).gameObject;
|
2024-07-11 14:45:15 +08:00
|
|
|
if (nodeObj != null)
|
|
|
|
{
|
2024-07-17 18:56:07 +08:00
|
|
|
var editorNode = new NodeEditor(node.Name, buildData.thematicCount);
|
2024-07-11 14:45:15 +08:00
|
|
|
foreach (Transform child in nodeObj.transform)
|
|
|
|
{
|
|
|
|
if (!child.gameObject.name.Equals(BtnBubble))
|
|
|
|
{
|
|
|
|
editorNode.optionObj.Add(child.gameObject);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-07-11 16:14:51 +08:00
|
|
|
editorNode.BuildNode = node;
|
2024-07-12 17:10:33 +08:00
|
|
|
if (!string.IsNullOrEmpty(node.IconPath))
|
|
|
|
editorNode.optionPath = node.IconPath.Replace("Icon", "Normal");
|
2024-07-11 14:45:15 +08:00
|
|
|
editorNodes.Add(editorNode);
|
|
|
|
}
|
|
|
|
}
|
2024-07-11 16:14:51 +08:00
|
|
|
|
|
|
|
_tempNodeObj.Clear();
|
|
|
|
foreach (Transform child in root.transform)
|
|
|
|
{
|
|
|
|
_tempNodeObj.Add(child.gameObject);
|
|
|
|
}
|
2024-07-11 14:45:15 +08:00
|
|
|
}
|
|
|
|
|
2024-07-10 19:06:07 +08:00
|
|
|
[VerticalGroup("BuildInfo/Create")]
|
|
|
|
[Button("创建/更新 节点实例")]
|
2024-07-11 20:03:13 +08:00
|
|
|
[InfoBox("会重新创建物体!!!")]
|
2024-07-10 19:06:07 +08:00
|
|
|
public void UpdateNode()
|
|
|
|
{
|
2024-07-11 14:45:15 +08:00
|
|
|
editorNodeResource = false;
|
|
|
|
if (editorNodes != null)
|
|
|
|
editorNodes.Clear();
|
|
|
|
|
2024-07-10 19:06:07 +08:00
|
|
|
switch (curBuildData.unlockType)
|
|
|
|
{
|
|
|
|
case UnlockType.ForGroup:
|
|
|
|
InitBuildInfo(curBuildData.nodeCount);
|
|
|
|
break;
|
|
|
|
case UnlockType.ForThematic:
|
|
|
|
InitBuildInfo(curBuildData.thematicCount);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
DebugUtil.LogError("解锁条件错误");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
CreateNodeObj();
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// 初始化建造数据
|
|
|
|
/// </summary>
|
|
|
|
private void InitBuildInfo(int count)
|
|
|
|
{
|
|
|
|
//挂点初始化
|
2024-07-17 18:56:07 +08:00
|
|
|
curBuildData.NodeInfos = new List<BuildData.BuildNode>(curBuildData.nodeCount);
|
2024-07-10 19:06:07 +08:00
|
|
|
for (int i = 0; i < curBuildData.nodeCount; i++)
|
|
|
|
{
|
2024-07-19 15:27:04 +08:00
|
|
|
var node = new BuildData.BuildNode
|
|
|
|
{
|
|
|
|
Name = string.Format(NodeName, i + 1)
|
|
|
|
};
|
2024-07-17 18:56:07 +08:00
|
|
|
curBuildData.NodeInfos.Add(node);
|
2024-07-10 19:06:07 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
//解锁条件初始化
|
|
|
|
curBuildData.unlockInfos = new List<BuildData.UnlockInfo>(count);
|
|
|
|
for (int i = 0; i < count; i++)
|
|
|
|
{
|
|
|
|
var unlock = new BuildData.UnlockInfo();
|
|
|
|
curBuildData.unlockInfos.Add(unlock);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
2024-07-11 14:45:15 +08:00
|
|
|
/// 创建实例
|
2024-07-10 19:06:07 +08:00
|
|
|
/// </summary>
|
|
|
|
private void CreateNodeObj()
|
|
|
|
{
|
|
|
|
//清除
|
|
|
|
DeleteNode();
|
|
|
|
|
2024-07-11 16:14:51 +08:00
|
|
|
var root = GameObject.Find(NodeRootPath);
|
2024-07-10 19:06:07 +08:00
|
|
|
editorNodes = new List<NodeEditor>(curBuildData.nodeCount);
|
|
|
|
var nodeTemplate = AssetDatabase.LoadAssetAtPath<GameObject>(NodeTemplatePath);
|
2024-07-17 18:56:07 +08:00
|
|
|
foreach (var node in curBuildData.NodeInfos)
|
2024-07-10 19:06:07 +08:00
|
|
|
{
|
2024-07-11 14:45:15 +08:00
|
|
|
//生成节点
|
2024-07-11 16:14:51 +08:00
|
|
|
var nodeObj = Instantiate(nodeTemplate, root.transform);
|
2024-07-17 18:56:07 +08:00
|
|
|
nodeObj.name = node.Name;
|
2024-07-11 20:03:13 +08:00
|
|
|
_tempNodeObj.Add(nodeObj);
|
2024-07-10 19:06:07 +08:00
|
|
|
|
2024-07-11 14:45:15 +08:00
|
|
|
//生成选项
|
2024-07-12 17:10:33 +08:00
|
|
|
|
2024-07-17 18:56:07 +08:00
|
|
|
node.Options = new List<string>(curBuildData.thematicCount);
|
2024-07-12 17:10:33 +08:00
|
|
|
|
2024-07-10 19:06:07 +08:00
|
|
|
var optionTemplate = nodeObj.transform.Find(OptionTemplatePath).gameObject;
|
2024-07-17 18:56:07 +08:00
|
|
|
var tempEditorNode = new NodeEditor(node.Name, curBuildData.thematicCount);
|
2024-07-10 19:06:07 +08:00
|
|
|
for (int i = 0; i < curBuildData.thematicCount; i++)
|
|
|
|
{
|
|
|
|
var optionObj = Instantiate(optionTemplate, nodeObj.transform);
|
|
|
|
optionObj.name = string.Format(OptionName, i + 1);
|
2024-07-11 14:45:15 +08:00
|
|
|
tempEditorNode.optionObj.Add(optionObj);
|
2024-07-17 18:56:07 +08:00
|
|
|
node.Options.Add(optionObj.name);
|
2024-07-11 16:14:51 +08:00
|
|
|
if (i != 0)
|
|
|
|
optionObj.SetActive(false);
|
2024-07-10 19:06:07 +08:00
|
|
|
}
|
|
|
|
|
2024-07-11 16:14:51 +08:00
|
|
|
tempEditorNode.BuildNode = node;
|
2024-07-10 19:06:07 +08:00
|
|
|
editorNodes.Add(tempEditorNode);
|
2024-07-11 14:45:15 +08:00
|
|
|
DestroyImmediate(optionTemplate);
|
2024-07-10 19:06:07 +08:00
|
|
|
|
2024-07-12 17:10:33 +08:00
|
|
|
//置顶泡泡按钮 UI操作
|
|
|
|
/*var btn = nodeObj.transform.Find(BtnBubble);
|
|
|
|
btn.transform.SetSiblingIndex(curBuildData.thematicCount);*/
|
2024-07-10 19:06:07 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
[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()
|
|
|
|
{
|
2024-07-12 17:10:33 +08:00
|
|
|
var root = GameObject.Find(NodeRootPath);
|
|
|
|
var sortingOrder = 1;
|
2024-07-10 19:06:07 +08:00
|
|
|
foreach (var editorNode in editorNodes)
|
|
|
|
{
|
2024-07-11 14:45:15 +08:00
|
|
|
//加载路径下的资源
|
|
|
|
var fileEntries = Directory.GetFiles(editorNode.optionPath, "*.png");
|
|
|
|
var spriteList = new List<Sprite>();
|
|
|
|
foreach (var filePath in fileEntries)
|
2024-07-10 19:06:07 +08:00
|
|
|
{
|
2024-07-11 14:45:15 +08:00
|
|
|
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];
|
2024-07-12 17:10:33 +08:00
|
|
|
//UI处理
|
|
|
|
/*var normalObj = option.transform.Find("Normal").gameObject.GetComponent<Image>();
|
2024-07-11 14:45:15 +08:00
|
|
|
normalObj.sprite = spriteList[i];
|
|
|
|
var rect = normalObj.GetComponent<RectTransform>();
|
2024-07-12 17:10:33 +08:00
|
|
|
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;
|
2024-07-11 14:45:15 +08:00
|
|
|
}
|
2024-07-10 19:06:07 +08:00
|
|
|
}
|
2024-07-11 16:14:51 +08:00
|
|
|
|
2024-07-12 17:10:33 +08:00
|
|
|
sortingOrder++;
|
2024-07-11 16:14:51 +08:00
|
|
|
//初始化Icon资源路径
|
|
|
|
editorNode.BuildNode.IconPath = editorNode.optionPath.Replace("Normal", "Icon");
|
2024-07-10 19:06:07 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-07-11 14:45:15 +08:00
|
|
|
[VerticalGroup("Save")]
|
|
|
|
[Button("保存")]
|
|
|
|
public void Save()
|
|
|
|
{
|
|
|
|
_buildEditor.SaveData();
|
|
|
|
|
2024-07-11 16:14:51 +08:00
|
|
|
//保存场景
|
|
|
|
var activeScene = SceneManager.GetActiveScene();
|
2024-07-11 14:45:15 +08:00
|
|
|
var saveResult = EditorSceneManager.SaveScene(activeScene);
|
|
|
|
if (!saveResult)
|
|
|
|
DebugUtil.LogError("保存失败!!!");
|
|
|
|
}
|
|
|
|
|
2024-07-10 19:06:07 +08:00
|
|
|
private void DeleteNode()
|
|
|
|
{
|
2024-07-11 16:14:51 +08:00
|
|
|
foreach (var obj in _tempNodeObj)
|
2024-07-10 19:06:07 +08:00
|
|
|
{
|
2024-07-11 16:14:51 +08:00
|
|
|
DestroyImmediate(obj);
|
2024-07-10 19:06:07 +08:00
|
|
|
}
|
2024-07-11 16:14:51 +08:00
|
|
|
|
|
|
|
_tempNodeObj.Clear();
|
2024-07-10 19:06:07 +08:00
|
|
|
}
|
|
|
|
}
|