NLDClient-yudde/ProjectNLD/Assets/Editor/CharacterBuilder/CharacterBuilderWindow.cs

473 lines
17 KiB
C#
Raw Normal View History

2026-01-13 13:20:29 +08:00
using System;
2023-12-19 18:07:31 +08:00
using System.Collections.Generic;
using DG.DemiEditor;
using Framework;
2023-12-29 17:00:23 +08:00
using Gameplay.Utils;
2026-01-12 18:43:17 +08:00
using PhxhSDK;
2023-12-19 18:07:31 +08:00
using UnityEditor;
using UnityEngine;
namespace CharacterBuilder
{
public class CharacterBuilderWindow : EditorWindow
{
2025-02-27 13:31:47 +08:00
[MenuItem("Tools/*角色工具/角色构建器", false, (int)NLDMenuID.CharacterBuilder)]
2023-12-19 18:07:31 +08:00
public static void ShowWindow()
{
var window = GetWindow<CharacterBuilderWindow>();
window.titleContent = new UnityEngine.GUIContent("角色构建器");
window.Show();
}
2024-01-26 12:53:17 +08:00
// [MenuItem("Test/测试")]
// public static void TestFunc()
// {
// }
2023-12-25 19:00:08 +08:00
2023-12-19 18:07:31 +08:00
private Vector2 _scrollPos1;
private Vector2 _scrollPos2;
private Vector2 _scrollPos3;
2023-12-19 18:07:31 +08:00
private GUIStyle _styleNormal;
private GUIStyle _styleError;
private List<CharacterBuildData> _characterBuildDataList;
private List<MonsterBuildData> _monsterBuildDataList;
private List<NpcBuildData> _npcBuildDataList;
2023-12-20 11:46:40 +08:00
private Dictionary<string, AnimationClip> _animclipMap;
2023-12-19 18:07:31 +08:00
private void _CheckAllConfigs()
{
2023-12-20 11:46:40 +08:00
// 加载指定路径下的所有animationclip文件
var allAnimationClips = AssetDatabase.FindAssets("t:AnimationClip", new[]
{
"Assets/Art/Animations/Battle/Motion",
"Assets/Art/Animations/Battle/Skill"
});
2023-12-20 11:46:40 +08:00
var dictAnimationClips = new Dictionary<string, AnimationClip>();
for (int i = 0; i < allAnimationClips.Length; i++)
{
var guid = allAnimationClips[i];
var path = AssetDatabase.GUIDToAssetPath(guid);
var clip = AssetDatabase.LoadAssetAtPath<AnimationClip>(path);
var clipName = clip.name;
if (!dictAnimationClips.TryAdd(clipName, clip))
2024-07-10 15:49:55 +08:00
{
Debug.LogError("重复的动画文件:" + clipName);
continue;
}
2023-12-20 11:46:40 +08:00
}
_animclipMap = dictAnimationClips;
for (int i = 0; i < _characterBuildDataList.Count; i++)
2023-12-19 18:07:31 +08:00
{
var buildData = _characterBuildDataList[i];
2023-12-20 11:46:40 +08:00
buildData.errorInfo = null;
if (buildData.weaponConfigList.Count == 0)
2023-12-19 18:07:31 +08:00
{
2023-12-20 11:46:40 +08:00
buildData.errorInfo = "未配置武器组";
2023-12-19 18:07:31 +08:00
continue;
}
2023-12-20 11:46:40 +08:00
if (buildData.skins.Count == 0)
{
buildData.errorInfo = "未配置皮肤";
continue;
}
for (int j = 0; j < buildData.skins.Count; j++)
{
var skinConfig = buildData.skins[j];
2024-01-15 12:39:20 +08:00
var prefabPath = PathEx.GetCharacterSrcModelPath(skinConfig.NameID);
2023-12-20 11:46:40 +08:00
if (string.IsNullOrEmpty(prefabPath))
{
buildData.errorInfo = "皮肤" + skinConfig.Name + "未配置预制体";
continue;
}
var loadPrefab = AssetDatabase.LoadAssetAtPath<GameObject>(prefabPath);
if (loadPrefab == null)
{
buildData.errorInfo = "预制体" + prefabPath + "不存在";
break;
}
}
if (buildData.errorInfo != null)
{
continue;
}
2023-12-20 11:46:40 +08:00
var checkAnim = buildData.CheckAnims(dictAnimationClips);
if (!string.IsNullOrEmpty(checkAnim))
{
buildData.errorInfo = checkAnim;
continue;
}
}
2023-12-29 17:00:23 +08:00
for (int i = 0; i < _monsterBuildDataList.Count; i++)
{
var buildData = _monsterBuildDataList[i];
buildData.errorInfo = null;
var weaponConfig = EditorTableManager.instance.tables.WeaponConfig.Get(buildData.mainConfig.WeaponId);
2024-01-02 19:26:01 +08:00
if (weaponConfig == null)
{
buildData.errorInfo = "无效的武器ID:" + buildData.mainConfig.WeaponId;
continue;
}
if (string.IsNullOrEmpty(weaponConfig.GroupName))
{
buildData.errorInfo = "未配置武器组";
continue;
}
2023-12-29 17:00:23 +08:00
var checkAnim = buildData.CheckAnims(dictAnimationClips);
if (!string.IsNullOrEmpty(checkAnim))
{
buildData.errorInfo = checkAnim;
continue;
}
2023-12-19 18:07:31 +08:00
}
for (int i = 0; i < _npcBuildDataList.Count; i++)
{
var buildData = _npcBuildDataList[i];
buildData.errorInfo = null;
var weaponConfig = EditorTableManager.instance.tables.WeaponConfig.Get(buildData.mainConfig.WeaponId);
if (weaponConfig == null)
{
buildData.errorInfo = "无效的武器ID:" + buildData.mainConfig.WeaponId;
continue;
}
if (string.IsNullOrEmpty(weaponConfig.GroupName))
{
buildData.errorInfo = "未配置武器组";
continue;
}
var checkAnim = buildData.CheckAnims(dictAnimationClips);
if (!string.IsNullOrEmpty(checkAnim))
{
buildData.errorInfo = checkAnim;
continue;
}
}
2023-12-19 18:07:31 +08:00
}
private void _BuildDatas()
{
_characterBuildDataList = new List<CharacterBuildData>();
2023-12-19 18:07:31 +08:00
var characterConfigList = EditorTableManager.instance.tables.CharacterAttri.DataList;
for (int i = 0; i < characterConfigList.Count; i++)
{
var cConfig = characterConfigList[i];
2023-12-20 11:46:40 +08:00
var buildData = new CharacterBuildData(cConfig);
2023-12-19 18:07:31 +08:00
_characterBuildDataList.Add(buildData);
}
_monsterBuildDataList = new List<MonsterBuildData>();
var monsterClassDataList = EditorTableManager.instance.tables.MonsterClass.DataList;
for (int i = 0; i < monsterClassDataList.Count; i++)
{
var cConfig = monsterClassDataList[i];
2024-09-06 19:40:38 +08:00
if (cConfig.EnemyType != 1)
{
continue;
}
var buildData = new MonsterBuildData(cConfig);
_monsterBuildDataList.Add(buildData);
2023-12-19 18:07:31 +08:00
}
_npcBuildDataList = new List<NpcBuildData>();
var npcDataList = EditorTableManager.instance.tables.FightNPCConfig.DataList;
for (int i = 0; i < npcDataList.Count; i++)
{
var cConfig = npcDataList[i];
var buildData = new NpcBuildData(cConfig);
2023-12-19 18:07:31 +08:00
_npcBuildDataList.Add(buildData);
}
2023-12-19 18:07:31 +08:00
_CheckAllConfigs();
_styleNormal = GUI.skin.label.Clone();
_styleNormal.normal.textColor = Color.white;
_styleNormal.focused.textColor = Color.white;
_styleNormal.hover.textColor = Color.white;
_styleNormal.active.textColor = Color.white;
_styleError = GUI.skin.label.Clone();
_styleError.normal.textColor = Color.red;
_styleError.focused.textColor = Color.red;
_styleError.hover.textColor = Color.red;
_styleError.active.textColor = Color.red;
}
private void OnGUI()
{
if (_characterBuildDataList == null)
2023-12-19 18:07:31 +08:00
{
_BuildDatas();
}
if (_characterBuildDataList == null)
{
return;
}
2023-12-19 18:07:31 +08:00
GUILayout.BeginHorizontal();
GUILayout.Label($"当前共有角色配置:{_characterBuildDataList.Count} 个, "
+ $"敌人配置:{_monsterBuildDataList.Count} 个, "
+ $"NPC配置{_npcBuildDataList.Count} 个");
2023-12-19 18:07:31 +08:00
if (GUILayout.Button("刷新"))
{
EditorTableManager.instance.ForceReload();
_characterBuildDataList = null;
GUILayout.EndHorizontal();
return;
2023-12-19 18:07:31 +08:00
}
GUILayout.EndHorizontal();
_ShowCharacters();
_ShowNpcs();
_ShowMonsters();
if (GUILayout.Button("开始构建"))
{
_Build();
}
}
private void _ShowNpcs()
{
GUILayout.Label("NPC配置");
var totalHeight = _npcBuildDataList.Count * 40;
var maxHeight = 200;
if (totalHeight < maxHeight)
{
maxHeight = totalHeight;
}
_scrollPos3 = EditorGUILayout.BeginScrollView(_scrollPos3, GUILayout.Height(maxHeight));
GUILayout.BeginVertical();
for (int i = 0; i < _npcBuildDataList.Count; i++)
{
var buildData = _npcBuildDataList[i];
var isError = !string.IsNullOrEmpty(buildData.errorInfo);
var style = isError ? _styleError : _styleNormal;
GUILayout.BeginHorizontal();
buildData.isChecked = GUILayout.Toggle(buildData.isChecked, "", GUILayout.Width(20));
var isChecked = buildData.isChecked;
var cConfig = buildData.mainConfig;
GUILayout.Label("ID" + cConfig.NameId, GUILayout.Width(80));
GUILayout.Label("名称:" + cConfig.NameRead, style, GUILayout.Width(90));
GUILayout.Label("使用武器:" + buildData.weaponIdsStr);
GUILayout.EndHorizontal();
_ShowEmojiInfo(buildData);
if (isError && isChecked)
{
GUILayout.BeginHorizontal();
GUILayout.Space(100);
GUILayout.Label(buildData.errorInfo, style);
GUILayout.EndHorizontal();
}
}
GUILayout.EndVertical();
EditorGUILayout.EndScrollView();
GUILayout.BeginHorizontal();
if (GUILayout.Button("全选"))
{
for (var i = 0; i < _npcBuildDataList.Count; ++i)
{
_npcBuildDataList[i].isChecked = true;
}
}
if (GUILayout.Button("全不选"))
{
for (var i = 0; i < _npcBuildDataList.Count; ++i)
{
_npcBuildDataList[i].isChecked = false;
}
}
GUILayout.EndHorizontal();
}
private void _ShowMonsters()
{
GUILayout.Label("敌人配置");
var totalHeight = _monsterBuildDataList.Count * 40;
var maxHeight = 200;
if (totalHeight < maxHeight)
{
maxHeight = totalHeight;
}
_scrollPos2 = EditorGUILayout.BeginScrollView(_scrollPos2, GUILayout.Height(maxHeight));
GUILayout.BeginVertical();
2023-12-29 17:00:23 +08:00
for (int i = 0; i < _monsterBuildDataList.Count; i++)
{
var buildData = _monsterBuildDataList[i];
var isError = !string.IsNullOrEmpty(buildData.errorInfo);
var style = isError ? _styleError : _styleNormal;
GUILayout.BeginHorizontal();
buildData.isChecked = GUILayout.Toggle(buildData.isChecked, "", GUILayout.Width(20));
var isChecked = buildData.isChecked;
var cConfig = buildData.mainConfig;
GUILayout.Label("ID" + cConfig.NameId, GUILayout.Width(80));
GUILayout.Label("名称:" + cConfig.Name, style, GUILayout.Width(120));
GUILayout.Label("使用武器:" + buildData.weaponIdsStr);
GUILayout.EndHorizontal();
2023-12-29 17:00:23 +08:00
_ShowEmojiInfo(buildData);
if (isError && isChecked)
{
GUILayout.BeginHorizontal();
GUILayout.Space(100);
GUILayout.Label(buildData.errorInfo, style);
GUILayout.EndHorizontal();
}
}
2023-12-29 17:00:23 +08:00
GUILayout.EndVertical();
EditorGUILayout.EndScrollView();
2023-12-29 17:00:23 +08:00
GUILayout.BeginHorizontal();
if (GUILayout.Button("全选"))
{
for (var i = 0; i < _monsterBuildDataList.Count; ++i)
{
_monsterBuildDataList[i].isChecked = true;
}
}
if (GUILayout.Button("全不选"))
{
for (var i = 0; i < _monsterBuildDataList.Count; ++i)
{
_monsterBuildDataList[i].isChecked = false;
}
}
GUILayout.EndHorizontal();
2023-12-29 17:00:23 +08:00
}
private void _ShowCharacters()
{
GUILayout.Label("角色配置");
2023-12-29 17:00:23 +08:00
var totalHeight = _characterBuildDataList.Count * 40;
var maxHeight = 200;
2023-12-19 18:07:31 +08:00
if (totalHeight < maxHeight)
{
maxHeight = totalHeight;
}
_scrollPos1 = EditorGUILayout.BeginScrollView(_scrollPos1, GUILayout.Height(maxHeight));
GUILayout.BeginVertical();
for (int i = 0; i < _characterBuildDataList.Count; i++)
2023-12-19 18:07:31 +08:00
{
var buildData = _characterBuildDataList[i];
2023-12-19 18:07:31 +08:00
var isError = !string.IsNullOrEmpty(buildData.errorInfo);
var style = isError ? _styleError : _styleNormal;
GUILayout.BeginHorizontal();
buildData.isChecked = GUILayout.Toggle(buildData.isChecked, "", GUILayout.Width(20));
var isChecked = buildData.isChecked;
var cConfig = buildData.mainConfig;
2023-12-20 11:46:40 +08:00
GUILayout.Label("ID" + cConfig.NameID, GUILayout.Width(80));
GUILayout.Label("名称:" + cConfig.NameRead, style, GUILayout.Width(90));
GUILayout.Label("皮肤数量:" + buildData.skins.Count, GUILayout.Width(80));
GUILayout.Label("使用武器:" + buildData.weaponIdsStr);
2023-12-19 18:07:31 +08:00
GUILayout.EndHorizontal();
2023-12-29 17:00:23 +08:00
_ShowEmojiInfo(buildData);
2023-12-19 18:07:31 +08:00
if (isError && isChecked)
{
GUILayout.BeginHorizontal();
GUILayout.Space(100);
GUILayout.Label(buildData.errorInfo, style);
GUILayout.EndHorizontal();
}
}
GUILayout.EndVertical();
EditorGUILayout.EndScrollView();
GUILayout.BeginHorizontal();
if (GUILayout.Button("全选"))
{
for (var i = 0; i < _characterBuildDataList.Count; ++i)
2023-12-19 18:07:31 +08:00
{
_characterBuildDataList[i].isChecked = true;
2023-12-19 18:07:31 +08:00
}
}
if (GUILayout.Button("全不选"))
{
for (var i = 0; i < _characterBuildDataList.Count; ++i)
2023-12-19 18:07:31 +08:00
{
_characterBuildDataList[i].isChecked = false;
2023-12-19 18:07:31 +08:00
}
}
GUILayout.EndHorizontal();
2023-12-20 11:46:40 +08:00
}
2023-12-19 18:07:31 +08:00
2023-12-29 17:00:23 +08:00
private void _ShowEmojiInfo(BaseRoleBuildData buildData)
{
GUILayout.BeginHorizontal();
GUILayout.Space(100);
GUILayout.Label("默认表情:" + buildData.emojiExt.emojiId, GUILayout.Width(120));
var eyebowsColorStr = buildData.emojiExt.eyebowsColor;
2026-01-13 13:20:29 +08:00
var eyebowsColor = ColorUtils.FromHex(eyebowsColorStr, Color.black);
2023-12-29 17:00:23 +08:00
var myStyle = new GUIStyle(GUI.skin.label);
myStyle.normal.textColor = eyebowsColor;
GUILayout.Label("眉毛颜色:" + buildData.emojiExt.eyebowsColor, myStyle, GUILayout.Width(120));
var eyesColorStr = buildData.emojiExt.eyesColor;
2026-01-13 13:20:29 +08:00
var eyesColor = ColorUtils.FromHex(eyesColorStr, Color.black);
2023-12-29 17:00:23 +08:00
myStyle.normal.textColor = eyesColor;
GUILayout.Label("眼睛颜色:" + buildData.emojiExt.eyesColor, myStyle, GUILayout.Width(120));
GUILayout.EndHorizontal();
}
2023-12-20 11:46:40 +08:00
private void _Build()
{
for (int i = 0; i < _characterBuildDataList.Count; i++)
{
var buildData = _characterBuildDataList[i];
if (!buildData.isChecked)
{
continue;
}
buildData.RebuildAll(_animclipMap);
}
2023-12-29 17:00:23 +08:00
for (int i = 0; i < _monsterBuildDataList.Count; i++)
2023-12-20 11:46:40 +08:00
{
var buildData = _monsterBuildDataList[i];
2023-12-20 11:46:40 +08:00
if (!buildData.isChecked)
{
continue;
}
buildData.RebuildAll(_animclipMap);
2023-12-19 18:07:31 +08:00
}
for (int i = 0; i < _npcBuildDataList.Count; i++)
{
var buildData = _npcBuildDataList[i];
if (!buildData.isChecked)
{
continue;
}
buildData.RebuildAll(_animclipMap);
}
2023-12-29 17:00:23 +08:00
2023-12-20 11:46:40 +08:00
AssetDatabase.Refresh();
2023-12-19 18:07:31 +08:00
}
}
}