TH1/Unity/Assets/Scripts/TH1_Logic/Editor/ComicEditorWindow.cs

410 lines
17 KiB
C#

/*
* @Author: 白哉
* @Description: 回放编辑器
* @Date: 2025年04月22日 星期二 15:04:14
* @Modify:
*/
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using RuntimeData;
using TH1_Logic.Comic;
using TH1_Logic.Core;
using UnityEditor;
using UnityEngine;
namespace Logic.Editor
{
public class ComicEditorWindow : EditorWindow
{
// 滑条
private Vector2 _barPosition;
// 背景
private GUIStyle _redBoxStyle;
private GUIStyle _whiteBoxStyle;
private List<string> _bigImageList;
private List<string> _itemImageList;
private List<string> _dialogList;
private List<string> _comicList;
private string _selectedName;
private List<string> _itemIdList;
private bool _isPlaying = false;
private GameObject _root;
private string _newName = "comic";
[MenuItem("Tools/漫画编辑器")]
private static void ShowWindow()
{
var window = CreateWindow<ComicEditorWindow>();
window.titleContent = new GUIContent("漫画编辑器");
window.Show();
}
protected virtual void OnEnable()
{
EditorApplication.update += OnEditorUpdate;
RefreshStrList();
}
private void OnDisable()
{
EditorApplication.update -= OnEditorUpdate;
Refresh();
// 从后往前删除,避免索引变化
for (int i = _root.transform.childCount - 1; i >= 0; i--)
{
DestroyImmediate(_root.transform.GetChild(i).gameObject);
}
}
private void OnEditorUpdate()
{
// 每帧刷新窗口
Repaint();
}
private void Refresh()
{
if (!_root) _root = GameObject.Find($"UICanvas/Comic");
}
private void OnGUI()
{
Refresh();
ComicManager.Instance.Refresh();
if(_isPlaying) ComicManager.Instance.ComicControl.Update();
if (_redBoxStyle == null)
{
_redBoxStyle = InspectorUtils.GetHelpBoxStyle();
InspectorUtils.AddBorder(_redBoxStyle, new Color(0.5f, 0.4f, 0.4f, 0.6f));
}
if (_whiteBoxStyle == null)
{
_whiteBoxStyle = InspectorUtils.GetHelpBoxStyle();
InspectorUtils.AddBorder(_whiteBoxStyle, new Color(1f, 1f, 1f, 0.2f));
}
GUI.skin.button.wordWrap = true;
_barPosition = EditorGUILayout.BeginScrollView(_barPosition);
EditorGUILayout.BeginHorizontal();
InspectorUtils.InspectorTextWidthRich($"<b> 新漫画 : </b>");
_newName = EditorGUILayout.TextField(_newName, GUILayout.Width(300));
if (InspectorUtils.InspectorButtonWithTextWidth("创建"))
{
ComicManager.Instance.AddComicSheet(_newName);
}
if (InspectorUtils.InspectorButtonWithTextWidth("刷新"))
{
RefreshStrList();
}
if (InspectorUtils.InspectorButtonWithTextWidth("保存"))
{
ComicManager.Instance.SaveComicData();
}
if (InspectorUtils.InspectorButtonWithTextWidth("检索图片库并保存"))
{
ComicManager.Instance.RefreshImageData();
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
if (_isPlaying)
{
var actionIndex = ComicManager.Instance.ComicControl.ActionIndex;
var maxIndex = ComicManager.Instance.ComicControl.MaxIndex;
var sheet = ComicManager.Instance.ComicControl.ComicSheet;
var progress = ComicManager.Instance.ComicControl.Progress;
var duration = ComicManager.Instance.ComicControl.Duration;
InspectorUtils.InspectorTextWidthRich($"<b> 播放中</b>");
InspectorUtils.InspectorTextWidthRich($"<b> 漫画:{sheet.Name} </b>");
InspectorUtils.InspectorTextWidthRich($"<b> Action : {actionIndex} / {maxIndex}</b>");
InspectorUtils.InspectorTextWidthRich($"<b> 进度 : {progress} / {duration}</b>");
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
InspectorUtils.InspectorTextWidthRich($"<b> 选择漫画 : </b>");
var index = GetIndexInComicList(_selectedName);
index = EditorGUILayout.Popup(index, _comicList.ToArray(), GUILayout.Width(300));
if (_comicList.Count != 0) _selectedName = _comicList[index];
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space();
var comicSheet = ComicManager.Instance.Asset.GetComicSheetByName(_selectedName);
if (comicSheet != null)
{
EditorGUILayout.BeginHorizontal();
if (InspectorUtils.InspectorButtonWithTextWidth($"删除漫画 {comicSheet.Name}"))
ComicManager.Instance.Asset.ComicSheets.Remove(comicSheet);
if (InspectorUtils.InspectorButtonWithTextWidth($"添加一页"))
comicSheet.AddComicData();
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
if (_isPlaying) InspectorUtils.InspectorTextWidthRich($"播放中, 请勿操作 GameObject");
else InspectorUtils.InspectorTextWidthRich($"编辑中, 可以操作 GameObject");
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
if (InspectorUtils.InspectorButtonWithTextWidth($"播放"))
{
// 从后往前删除,避免索引变化
for (int i = _root.transform.childCount - 1; i >= 0; i--)
{
DestroyImmediate(_root.transform.GetChild(i).gameObject);
}
ComicManager.Instance.InitComic(comicSheet.Name, _root);
_isPlaying = true;
}
if (_isPlaying && InspectorUtils.InspectorButtonWithTextWidth($"模拟点击"))
{
ComicManager.Instance.Next();
}
if (_isPlaying && InspectorUtils.InspectorButtonWithTextWidth($"停止播放"))
{
_isPlaying = false;
ComicManager.Instance.ComicControl.Clear();
}
EditorGUILayout.EndHorizontal();
if (!_isPlaying)
{
int deleteIndex = -1;
int upIndex = -1;
int downIndex = -1;
for (int i = 0; i < comicSheet.ComicDatas.Count; i++)
{
OnGUIComicData(comicSheet.ComicDatas[i], i, out bool delete, out bool up, out bool down);
if (up) upIndex = i;
if (down) downIndex = i;
if (delete) deleteIndex = i;
EditorGUILayout.Space();
}
if (deleteIndex >= 0) comicSheet.ComicDatas.RemoveAt(deleteIndex);
else if (upIndex >= 0) comicSheet.MoveComicData(comicSheet.ComicDatas[upIndex], -1);
else if (downIndex >= 0) comicSheet.MoveComicData(comicSheet.ComicDatas[downIndex], 1);
}
}
EditorGUILayout.EndScrollView();
}
private void OnGUIComicData(ComicData data, int id, out bool isDelete, out bool up, out bool down)
{
up = false;
down = false;
isDelete = false;
EditorGUILayout.BeginVertical(_whiteBoxStyle, GUILayout.Width(500));
EditorGUILayout.BeginHorizontal();
InspectorUtils.InspectorTextWidthRich($"第 {id + 1} 页");
if (InspectorUtils.InspectorButtonWithTextWidth($"↑")) up = true;
if (InspectorUtils.InspectorButtonWithTextWidth($"↓")) down = true;
if (InspectorUtils.InspectorButtonWithTextWidth($"x")) isDelete = true;
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
if (InspectorUtils.InspectorButtonWithTextWidth($"预览并编辑此页"))
{
// 从后往前删除,避免索引变化
for (int i = _root.transform.childCount - 1; i >= 0; i--)
{
DestroyImmediate(_root.transform.GetChild(i).gameObject);
}
ComicManager.Instance.ComicControl.PreviewComicData(data, _root);
}
if (data.Mono && InspectorUtils.InspectorButtonWithTextWidth($"保存此页")) data.SaveItemsMono();
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
InspectorUtils.InspectorTextWidthRich("底图:");
var index = GetIndexInStrList(data.Background.ImageName, _bigImageList);
index = EditorGUILayout.Popup(index, _bigImageList.ToArray(), GUILayout.Width(300));
if (_bigImageList.Count != 0) data.Background.ImageName = _bigImageList[index];
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space();
EditorGUILayout.BeginHorizontal();
if (InspectorUtils.InspectorButtonWithTextWidth($"添加Item")) data.AddSubItem();
EditorGUILayout.EndHorizontal();
// Items
EditorGUILayout.BeginVertical(_whiteBoxStyle);
var deleteIndex = -1;
for (int i = 0; i < data.SubItems.Count; i++)
{
OnGUIComicItem(data.SubItems[i], out bool delete);
if (delete) deleteIndex = i;
EditorGUILayout.Space();
}
if (deleteIndex >= 0) data.RemoveSubItem(data.SubItems[deleteIndex]);
EditorGUILayout.EndVertical();
EditorGUILayout.Space();
// Actions
EditorGUILayout.BeginHorizontal();
if (InspectorUtils.InspectorButtonWithTextWidth($"添加Action")) data.AddAction();
EditorGUILayout.EndHorizontal();
_itemIdList ??= new List<string>();
_itemIdList.Clear();
foreach (var item in data.SubItems) _itemIdList.Add($"{item.Id}");
EditorGUILayout.BeginVertical(_whiteBoxStyle);
deleteIndex = -1;
for (int i = 0; i < data.Actions.Count; i++)
{
OnGUIComicAction(data.Actions[i], i, out bool delete);
if (delete) deleteIndex = i;
EditorGUILayout.Space();
}
if (deleteIndex >= 0) data.RemoveAction(data.Actions[deleteIndex]);
EditorGUILayout.EndVertical();
EditorGUILayout.EndVertical();
EditorGUILayout.Space();
}
private void OnGUIComicItem(ComicSubItem item, out bool isDelete)
{
isDelete = false;
EditorGUILayout.BeginHorizontal();
InspectorUtils.InspectorTextWidthRich($"Item ID : {item.Id}");
if (InspectorUtils.InspectorButtonWithTextWidth($"x")) isDelete = true;
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
InspectorUtils.InspectorTextWidthRich("类型:");
item.ItemType = (ComicSubItemType)EditorGUILayout.EnumPopup(item.ItemType, GUILayout.Width(200));
EditorGUILayout.EndHorizontal();
if (item.ItemType == ComicSubItemType.Image)
{
EditorGUILayout.BeginHorizontal();
InspectorUtils.InspectorTextWidthRich("图片:");
var index = GetIndexInStrList(item.ImageName, _itemImageList);
index = EditorGUILayout.Popup(index, _itemImageList.ToArray(), GUILayout.Width(300));
if (_itemImageList.Count != 0) item.ImageName = _itemImageList[index];
EditorGUILayout.EndHorizontal();
}
if (item.ItemType == ComicSubItemType.Dialog)
{
EditorGUILayout.BeginHorizontal();
InspectorUtils.InspectorTextWidthRich("对话框: ");
var index = GetIndexInStrList(item.ImageName, _dialogList);
index = EditorGUILayout.Popup(index, _dialogList.ToArray(), GUILayout.Width(300));
if (_dialogList.Count != 0) item.ImageName = _dialogList[index];
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
InspectorUtils.InspectorTextWidthRich($"对话 ID: ");
item.Content = EditorGUILayout.TextField(item.Content, GUILayout.Width(300));
EditorGUILayout.EndHorizontal();
}
}
private void OnGUIComicAction(ComicAction action, int id, out bool isDelete)
{
isDelete = false;
EditorGUILayout.BeginHorizontal();
InspectorUtils.InspectorTextWidthRich($"Action ID : {id + 1}");
if (InspectorUtils.InspectorButtonWithTextWidth($"x")) isDelete = true;
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
InspectorUtils.InspectorTextWidthRich($"目标 Item");
var index = GetIndexInStrList(action.TargetId.ToString(), _itemIdList);
index = EditorGUILayout.Popup(index, _itemIdList.ToArray(), GUILayout.Width(300));
if (_itemIdList.Count != 0) action.TargetId = int.Parse(_itemIdList[index]);
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
InspectorUtils.InspectorTextWidthRich($"Action 类型:");
action.ActionType = (ComicActionType)EditorGUILayout.EnumPopup(action.ActionType, GUILayout.Width(200));
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
InspectorUtils.InspectorTextWidthRich($"时长:");
action.Duration = EditorGUILayout.FloatField(action.Duration, GUILayout.Width(200));
EditorGUILayout.EndHorizontal();
}
private int GetIndexInStrList(string str, List<string> list)
{
for (int i = 0; i < list.Count; i++)
{
if (list[i] == str) return i;
}
return 0;
}
private int GetIndexInComicList(string name)
{
if (_comicList == null) _comicList = new List<string>();
if (_comicList.Count != ComicManager.Instance.Asset.ComicSheets.Count)
{
_comicList.Clear();
foreach (var data in ComicManager.Instance.Asset.ComicSheets)
{
_comicList.Add(data.Name);
}
}
for (int i = 0; i < _comicList.Count; i++)
{
if (_comicList[i] == name) return i;
}
return 0;
}
private void RefreshStrList()
{
_bigImageList ??= new List<string>();
_bigImageList.Clear();
string folderPath = "Assets/Resources/ArtResources/Comic/BigImage";
if (!Directory.Exists(folderPath)) Directory.CreateDirectory(folderPath);
string[] files = Directory.GetFiles(folderPath, "*.png");
foreach (string file in files)
{
string fileName = Path.GetFileNameWithoutExtension(file);
if (!string.IsNullOrEmpty(fileName)) _bigImageList.Add(fileName);
}
_itemImageList ??= new List<string>();
_itemImageList.Clear();
folderPath = "Assets/Resources/ArtResources/Comic/ItemImage";
if (!Directory.Exists(folderPath)) Directory.CreateDirectory(folderPath);
files = Directory.GetFiles(folderPath, "*.png");
foreach (string file in files)
{
string fileName = Path.GetFileNameWithoutExtension(file);
if (!string.IsNullOrEmpty(fileName)) _itemImageList.Add(fileName);
}
_dialogList ??= new List<string>();
_dialogList.Clear();
folderPath = "Assets/Resources/ArtResources/Comic/Dialog";
if (!Directory.Exists(folderPath)) Directory.CreateDirectory(folderPath);
files = Directory.GetFiles(folderPath, "*.png");
foreach (string file in files)
{
string fileName = Path.GetFileNameWithoutExtension(file);
if (!string.IsNullOrEmpty(fileName)) _dialogList.Add(fileName);
}
}
}
}