473 lines
17 KiB
C#
473 lines
17 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using DG.DemiEditor;
|
||
using Framework;
|
||
using Gameplay.Utils;
|
||
using PhxhSDK;
|
||
using UnityEditor;
|
||
using UnityEngine;
|
||
|
||
namespace CharacterBuilder
|
||
{
|
||
public class CharacterBuilderWindow : EditorWindow
|
||
{
|
||
|
||
[MenuItem("Tools/*角色工具/角色构建器", false, (int)NLDMenuID.CharacterBuilder)]
|
||
public static void ShowWindow()
|
||
{
|
||
var window = GetWindow<CharacterBuilderWindow>();
|
||
window.titleContent = new UnityEngine.GUIContent("角色构建器");
|
||
window.Show();
|
||
}
|
||
|
||
// [MenuItem("Test/测试")]
|
||
// public static void TestFunc()
|
||
// {
|
||
// }
|
||
|
||
|
||
private Vector2 _scrollPos1;
|
||
private Vector2 _scrollPos2;
|
||
private Vector2 _scrollPos3;
|
||
|
||
private GUIStyle _styleNormal;
|
||
private GUIStyle _styleError;
|
||
|
||
private List<CharacterBuildData> _characterBuildDataList;
|
||
private List<MonsterBuildData> _monsterBuildDataList;
|
||
private List<NpcBuildData> _npcBuildDataList;
|
||
private Dictionary<string, AnimationClip> _animclipMap;
|
||
|
||
private void _CheckAllConfigs()
|
||
{
|
||
// 加载指定路径下的所有animationclip文件
|
||
var allAnimationClips = AssetDatabase.FindAssets("t:AnimationClip", new[]
|
||
{
|
||
"Assets/Art/Animations/Battle/Motion",
|
||
"Assets/Art/Animations/Battle/Skill"
|
||
});
|
||
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))
|
||
{
|
||
Debug.LogError("重复的动画文件:" + clipName);
|
||
continue;
|
||
}
|
||
}
|
||
_animclipMap = dictAnimationClips;
|
||
|
||
for (int i = 0; i < _characterBuildDataList.Count; i++)
|
||
{
|
||
var buildData = _characterBuildDataList[i];
|
||
buildData.errorInfo = null;
|
||
if (buildData.weaponConfigList.Count == 0)
|
||
{
|
||
buildData.errorInfo = "未配置武器组";
|
||
continue;
|
||
}
|
||
|
||
if (buildData.skins.Count == 0)
|
||
{
|
||
buildData.errorInfo = "未配置皮肤";
|
||
continue;
|
||
}
|
||
|
||
for (int j = 0; j < buildData.skins.Count; j++)
|
||
{
|
||
var skinConfig = buildData.skins[j];
|
||
var prefabPath = PathEx.GetCharacterSrcModelPath(skinConfig.NameID);
|
||
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;
|
||
}
|
||
|
||
var checkAnim = buildData.CheckAnims(dictAnimationClips);
|
||
if (!string.IsNullOrEmpty(checkAnim))
|
||
{
|
||
buildData.errorInfo = checkAnim;
|
||
continue;
|
||
}
|
||
|
||
}
|
||
|
||
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);
|
||
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;
|
||
}
|
||
}
|
||
|
||
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;
|
||
}
|
||
}
|
||
}
|
||
|
||
private void _BuildDatas()
|
||
{
|
||
_characterBuildDataList = new List<CharacterBuildData>();
|
||
var characterConfigList = EditorTableManager.instance.tables.CharacterAttri.DataList;
|
||
|
||
for (int i = 0; i < characterConfigList.Count; i++)
|
||
{
|
||
var cConfig = characterConfigList[i];
|
||
var buildData = new CharacterBuildData(cConfig);
|
||
|
||
_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];
|
||
if (cConfig.EnemyType != 1)
|
||
{
|
||
continue;
|
||
}
|
||
var buildData = new MonsterBuildData(cConfig);
|
||
|
||
_monsterBuildDataList.Add(buildData);
|
||
}
|
||
|
||
_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);
|
||
|
||
_npcBuildDataList.Add(buildData);
|
||
}
|
||
|
||
_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)
|
||
{
|
||
_BuildDatas();
|
||
}
|
||
|
||
if (_characterBuildDataList == null)
|
||
{
|
||
return;
|
||
}
|
||
|
||
GUILayout.BeginHorizontal();
|
||
GUILayout.Label($"当前共有角色配置:{_characterBuildDataList.Count} 个, "
|
||
+ $"敌人配置:{_monsterBuildDataList.Count} 个, "
|
||
+ $"NPC配置:{_npcBuildDataList.Count} 个");
|
||
if (GUILayout.Button("刷新"))
|
||
{
|
||
EditorTableManager.instance.ForceReload();
|
||
_characterBuildDataList = null;
|
||
GUILayout.EndHorizontal();
|
||
return;
|
||
}
|
||
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();
|
||
|
||
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();
|
||
_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 < _monsterBuildDataList.Count; ++i)
|
||
{
|
||
_monsterBuildDataList[i].isChecked = true;
|
||
}
|
||
}
|
||
if (GUILayout.Button("全不选"))
|
||
{
|
||
for (var i = 0; i < _monsterBuildDataList.Count; ++i)
|
||
{
|
||
_monsterBuildDataList[i].isChecked = false;
|
||
}
|
||
}
|
||
GUILayout.EndHorizontal();
|
||
|
||
}
|
||
|
||
private void _ShowCharacters()
|
||
{
|
||
GUILayout.Label("角色配置");
|
||
var totalHeight = _characterBuildDataList.Count * 40;
|
||
var maxHeight = 200;
|
||
if (totalHeight < maxHeight)
|
||
{
|
||
maxHeight = totalHeight;
|
||
}
|
||
_scrollPos1 = EditorGUILayout.BeginScrollView(_scrollPos1, GUILayout.Height(maxHeight));
|
||
GUILayout.BeginVertical();
|
||
|
||
for (int i = 0; i < _characterBuildDataList.Count; i++)
|
||
{
|
||
var buildData = _characterBuildDataList[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.skins.Count, GUILayout.Width(80));
|
||
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 < _characterBuildDataList.Count; ++i)
|
||
{
|
||
_characterBuildDataList[i].isChecked = true;
|
||
}
|
||
}
|
||
if (GUILayout.Button("全不选"))
|
||
{
|
||
for (var i = 0; i < _characterBuildDataList.Count; ++i)
|
||
{
|
||
_characterBuildDataList[i].isChecked = false;
|
||
}
|
||
}
|
||
GUILayout.EndHorizontal();
|
||
}
|
||
|
||
private void _ShowEmojiInfo(BaseRoleBuildData buildData)
|
||
{
|
||
GUILayout.BeginHorizontal();
|
||
GUILayout.Space(100);
|
||
GUILayout.Label("默认表情:" + buildData.emojiExt.emojiId, GUILayout.Width(120));
|
||
var eyebowsColorStr = buildData.emojiExt.eyebowsColor;
|
||
var eyebowsColor = ColorUtils.FromHex(eyebowsColorStr, Color.black);
|
||
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;
|
||
var eyesColor = ColorUtils.FromHex(eyesColorStr, Color.black);
|
||
myStyle.normal.textColor = eyesColor;
|
||
GUILayout.Label("眼睛颜色:" + buildData.emojiExt.eyesColor, myStyle, GUILayout.Width(120));
|
||
GUILayout.EndHorizontal();
|
||
}
|
||
|
||
private void _Build()
|
||
{
|
||
for (int i = 0; i < _characterBuildDataList.Count; i++)
|
||
{
|
||
var buildData = _characterBuildDataList[i];
|
||
if (!buildData.isChecked)
|
||
{
|
||
continue;
|
||
}
|
||
buildData.RebuildAll(_animclipMap);
|
||
}
|
||
|
||
for (int i = 0; i < _monsterBuildDataList.Count; i++)
|
||
{
|
||
var buildData = _monsterBuildDataList[i];
|
||
if (!buildData.isChecked)
|
||
{
|
||
continue;
|
||
}
|
||
buildData.RebuildAll(_animclipMap);
|
||
}
|
||
|
||
for (int i = 0; i < _npcBuildDataList.Count; i++)
|
||
{
|
||
var buildData = _npcBuildDataList[i];
|
||
if (!buildData.isChecked)
|
||
{
|
||
continue;
|
||
}
|
||
buildData.RebuildAll(_animclipMap);
|
||
}
|
||
|
||
AssetDatabase.Refresh();
|
||
}
|
||
|
||
}
|
||
}
|