2025-10-23 00:49:44 -04:00
|
|
|
|
#if UNITY_EDITOR
|
2025-10-24 09:11:22 -04:00
|
|
|
|
using System;
|
2025-10-27 07:04:34 -04:00
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
using System.Linq;
|
2025-10-23 00:49:44 -04:00
|
|
|
|
using UnityEditor;
|
|
|
|
|
|
using UnityEngine;
|
|
|
|
|
|
using SLSFramework.UModAssistance;
|
|
|
|
|
|
using Continentis.MainGame.Character;
|
2025-10-27 07:04:34 -04:00
|
|
|
|
using Continentis.Mods;
|
2025-10-23 00:49:44 -04:00
|
|
|
|
|
|
|
|
|
|
namespace Continentis.MainGame.Card
|
|
|
|
|
|
{
|
|
|
|
|
|
[CustomEditor(typeof(CardData))]
|
2025-10-27 07:04:34 -04:00
|
|
|
|
public partial class CardDataEditor : DataEditor
|
2025-10-23 00:49:44 -04:00
|
|
|
|
{
|
|
|
|
|
|
// 存储我们需要自定义绘制的属性的引用
|
2025-10-24 09:11:22 -04:00
|
|
|
|
private SerializedProperty modNameProp;
|
|
|
|
|
|
private SerializedProperty classNameProp;
|
|
|
|
|
|
private SerializedProperty displayNameProp;
|
|
|
|
|
|
private SerializedProperty cardRarityProp;
|
|
|
|
|
|
private SerializedProperty cardTypeProp;
|
2025-10-27 07:04:34 -04:00
|
|
|
|
private SerializedProperty keywordsProp;
|
2025-10-24 09:11:22 -04:00
|
|
|
|
|
|
|
|
|
|
private SerializedProperty cardSpriteProp;
|
2025-10-27 07:04:34 -04:00
|
|
|
|
private SerializedProperty cardLayoutTagsProp;
|
2025-10-24 09:11:22 -04:00
|
|
|
|
private SerializedProperty functionTextProp;
|
|
|
|
|
|
private SerializedProperty cardDescriptionProp;
|
|
|
|
|
|
|
|
|
|
|
|
private SerializedProperty baseWeightProp;
|
|
|
|
|
|
|
|
|
|
|
|
private SerializedProperty variableAttributesProp;
|
|
|
|
|
|
private SerializedProperty originalAttributesProp;
|
|
|
|
|
|
private SerializedProperty runtimeCurrentAttributesProp;
|
|
|
|
|
|
|
|
|
|
|
|
private SerializedProperty upgradeNodeProp;
|
|
|
|
|
|
|
2025-10-23 00:49:44 -04:00
|
|
|
|
private SerializedProperty prefabsProp;
|
|
|
|
|
|
private SerializedProperty derivativeCardsProp;
|
|
|
|
|
|
private SerializedProperty derivativeCharactersProp;
|
2025-10-27 07:04:34 -04:00
|
|
|
|
|
2025-10-23 00:49:44 -04:00
|
|
|
|
protected override void OnEnable()
|
|
|
|
|
|
{
|
|
|
|
|
|
base.OnEnable();
|
|
|
|
|
|
|
2025-10-27 07:04:34 -04:00
|
|
|
|
LoadAllKeywordsFromEditRefs();
|
|
|
|
|
|
|
2025-10-23 00:49:44 -04:00
|
|
|
|
// 在启用时,根据我们修改后的字段名找到对应的SerializedProperty
|
2025-10-24 09:11:22 -04:00
|
|
|
|
modNameProp = serializedObject.FindProperty("modName");
|
|
|
|
|
|
classNameProp = serializedObject.FindProperty("className");
|
|
|
|
|
|
displayNameProp = serializedObject.FindProperty("displayName");
|
|
|
|
|
|
cardRarityProp = serializedObject.FindProperty("cardRarity");
|
|
|
|
|
|
cardTypeProp = serializedObject.FindProperty("cardType");
|
2025-10-27 07:04:34 -04:00
|
|
|
|
keywordsProp = serializedObject.FindProperty("keywords");
|
2025-10-24 09:11:22 -04:00
|
|
|
|
cardSpriteProp = serializedObject.FindProperty("cardSprite");
|
2025-10-27 07:04:34 -04:00
|
|
|
|
cardLayoutTagsProp = serializedObject.FindProperty("cardLayoutTags");
|
2025-10-24 09:11:22 -04:00
|
|
|
|
functionTextProp = serializedObject.FindProperty("functionText");
|
|
|
|
|
|
cardDescriptionProp = serializedObject.FindProperty("cardDescription");
|
|
|
|
|
|
baseWeightProp = serializedObject.FindProperty("baseWeight");
|
|
|
|
|
|
variableAttributesProp = serializedObject.FindProperty("variableAttributes");
|
|
|
|
|
|
originalAttributesProp = serializedObject.FindProperty("originalAttributes");
|
|
|
|
|
|
runtimeCurrentAttributesProp = serializedObject.FindProperty("runtimeCurrentAttributes");
|
|
|
|
|
|
upgradeNodeProp = serializedObject.FindProperty("upgradeNode");
|
2025-10-23 00:49:44 -04:00
|
|
|
|
prefabsProp = serializedObject.FindProperty("prefabRefs");
|
|
|
|
|
|
derivativeCardsProp = serializedObject.FindProperty("derivativeCardDataRefs");
|
|
|
|
|
|
derivativeCharactersProp = serializedObject.FindProperty("derivativeCharacterDataRefs");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public override void OnInspectorGUI()
|
|
|
|
|
|
{
|
|
|
|
|
|
serializedObject.Update();
|
|
|
|
|
|
|
|
|
|
|
|
// --- 绘制自定义的Type选择器 ---
|
|
|
|
|
|
// 我们把它从所有自动绘制的属性中分离出来,放在最前面或最后面,让布局更清晰
|
|
|
|
|
|
EditorGUILayout.Space(); // 增加一点间距
|
2025-10-24 09:11:22 -04:00
|
|
|
|
EditorGUILayout.LabelField("Fundamental", EditorStyles.boldLabel);
|
|
|
|
|
|
if (DrawTypeSelectorGUI(classNameProp, "Card Logic Class", typeof(CardLogicBase), out Type outType, "Continentis.Mods", "Cards"))
|
2025-10-23 00:49:44 -04:00
|
|
|
|
{
|
2025-10-24 09:11:22 -04:00
|
|
|
|
string className = classNameProp.stringValue;
|
|
|
|
|
|
string modName = outType.Namespace!.Replace("Continentis.Mods.", "").Split('.')[0];
|
|
|
|
|
|
string displayName = "Card_" + modName + "_" + className + "_DisplayName";
|
|
|
|
|
|
string functionTextName = "Card_" + modName + "_" + className + "_FunctionText";
|
2025-10-23 00:49:44 -04:00
|
|
|
|
|
2025-10-24 09:11:22 -04:00
|
|
|
|
modNameProp.stringValue = modName;
|
2025-10-23 00:49:44 -04:00
|
|
|
|
displayNameProp.stringValue = displayName;
|
|
|
|
|
|
functionTextProp.stringValue = functionTextName;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-24 09:11:22 -04:00
|
|
|
|
EditorGUI.BeginDisabledGroup(true);
|
|
|
|
|
|
EditorGUILayout.PropertyField(modNameProp);
|
|
|
|
|
|
EditorGUILayout.PropertyField(classNameProp);
|
|
|
|
|
|
EditorGUILayout.PropertyField(displayNameProp);
|
|
|
|
|
|
EditorGUI.EndDisabledGroup();
|
|
|
|
|
|
|
|
|
|
|
|
EditorGUILayout.PropertyField(cardRarityProp);
|
|
|
|
|
|
EditorGUILayout.PropertyField(cardTypeProp);
|
2025-10-27 07:04:34 -04:00
|
|
|
|
EditorGUILayout.PropertyField(keywordsProp, true);
|
|
|
|
|
|
if (keywordsProp.isExpanded)
|
|
|
|
|
|
{
|
|
|
|
|
|
DrawKeywordSelector();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-24 09:11:22 -04:00
|
|
|
|
EditorGUILayout.PropertyField(cardSpriteProp);
|
2025-10-27 07:04:34 -04:00
|
|
|
|
EditorGUILayout.PropertyField(cardLayoutTagsProp, true);
|
2025-10-24 09:11:22 -04:00
|
|
|
|
EditorGUILayout.PropertyField(functionTextProp);
|
|
|
|
|
|
EditorGUILayout.PropertyField(cardDescriptionProp);
|
|
|
|
|
|
|
|
|
|
|
|
EditorGUILayout.Space();
|
|
|
|
|
|
EditorGUILayout.LabelField("Attributes", EditorStyles.boldLabel);
|
|
|
|
|
|
EditorGUILayout.PropertyField(baseWeightProp);
|
|
|
|
|
|
EditorGUILayout.PropertyField(variableAttributesProp, true);
|
|
|
|
|
|
EditorGUILayout.PropertyField(originalAttributesProp, true);
|
|
|
|
|
|
EditorGUILayout.PropertyField(runtimeCurrentAttributesProp, true);
|
|
|
|
|
|
|
|
|
|
|
|
EditorGUILayout.Space();
|
|
|
|
|
|
EditorGUILayout.LabelField("Upgrade", EditorStyles.boldLabel);
|
|
|
|
|
|
EditorGUILayout.PropertyField(upgradeNodeProp);
|
2025-10-23 00:49:44 -04:00
|
|
|
|
|
|
|
|
|
|
// --- 绘制自定义的引用列表 ---
|
|
|
|
|
|
EditorGUILayout.Space();
|
|
|
|
|
|
EditorGUILayout.LabelField("References", EditorStyles.boldLabel);
|
|
|
|
|
|
DrawCharacterListGUI<GameObject>(prefabsProp);
|
|
|
|
|
|
DrawCharacterListGUI<CardData>(derivativeCardsProp);
|
|
|
|
|
|
DrawCharacterListGUI<CharacterData>(derivativeCharactersProp);
|
|
|
|
|
|
|
|
|
|
|
|
HandleObjectPicker();
|
|
|
|
|
|
|
|
|
|
|
|
serializedObject.ApplyModifiedProperties();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-10-27 07:04:34 -04:00
|
|
|
|
|
|
|
|
|
|
public partial class CardDataEditor
|
|
|
|
|
|
{
|
|
|
|
|
|
private List<string> allAvailableKeywords;
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 使用 AssetDatabase 查找项目中的所有 KeywordDatabase 并合并它们的列表
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private void LoadAllKeywordsFromEditRefs()
|
|
|
|
|
|
{
|
|
|
|
|
|
// 使用 HashSet 来自动处理重复的关键词
|
|
|
|
|
|
HashSet<string> allKeywordsSet = new HashSet<string>();
|
|
|
|
|
|
|
|
|
|
|
|
// 1. 查找项目中所有类型为 "KeywordDatabase" 的
|
|
|
|
|
|
// "t:KeywordDatabase" 是一个搜索过滤器,t: 表示按类型搜索
|
|
|
|
|
|
string[] guids = AssetDatabase.FindAssets("t:ModEditReference");
|
|
|
|
|
|
|
|
|
|
|
|
foreach (string guid in guids)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 2. 将 GUID 转换为资产路径
|
|
|
|
|
|
string assetPath = AssetDatabase.GUIDToAssetPath(guid);
|
|
|
|
|
|
|
|
|
|
|
|
// 3. 加载该路径下的 ScriptableObject
|
|
|
|
|
|
ModEditReference editRef = AssetDatabase.LoadAssetAtPath<ModEditReference>(assetPath);
|
|
|
|
|
|
EditKeywordsReference cardKeywordsRef = editRef.cardKeywordsReference;
|
|
|
|
|
|
|
|
|
|
|
|
if (cardKeywordsRef != null && cardKeywordsRef.keywordRefs != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 4. 将词库中的所有词添加到 Set 中
|
|
|
|
|
|
foreach (string keyword in cardKeywordsRef.keywordRefs.Keys)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!string.IsNullOrEmpty(keyword))
|
|
|
|
|
|
{
|
|
|
|
|
|
allKeywordsSet.Add(keyword);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 5. 将 Set 转换为 List 并排序,以便在菜单中清晰显示
|
|
|
|
|
|
allAvailableKeywords = allKeywordsSet.ToList();
|
|
|
|
|
|
allAvailableKeywords.Sort();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void DrawKeywordSelector()
|
|
|
|
|
|
{
|
|
|
|
|
|
// 1. 检查是否找到了任何关键词
|
|
|
|
|
|
if (allAvailableKeywords == null || allAvailableKeywords.Count == 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
EditorGUILayout.HelpBox("在项目中没有找到任何 KeywordDatabase,或者词库为空。", MessageType.Warning);
|
|
|
|
|
|
// 显示一个刷新按钮,以防用户刚刚创建了词库
|
|
|
|
|
|
if (GUILayout.Button("Refresh Keyword Edit References"))
|
|
|
|
|
|
{
|
|
|
|
|
|
LoadAllKeywordsFromEditRefs();
|
|
|
|
|
|
}
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
List<string> currentKeywords = (target as CardData)!.keywords;
|
|
|
|
|
|
|
|
|
|
|
|
// 2. 找出尚未添加的关键词
|
|
|
|
|
|
List<string> keywordsToAdd = allAvailableKeywords.Except(currentKeywords).ToList();
|
|
|
|
|
|
|
|
|
|
|
|
// 3. 如果所有关键词都添加了,显示提示
|
|
|
|
|
|
if (keywordsToAdd.Count == 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
EditorGUILayout.HelpBox("所有可用的关键词都已添加。", MessageType.Info);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
// 4. 绘制 "Add Keyword" 按钮
|
|
|
|
|
|
if (GUILayout.Button("Add Keyword from Edit Refs..."))
|
|
|
|
|
|
{
|
|
|
|
|
|
GenericMenu menu = new GenericMenu();
|
|
|
|
|
|
foreach (string keyword in keywordsToAdd)
|
|
|
|
|
|
{
|
|
|
|
|
|
menu.AddItem(new GUIContent(keyword), false, () => {
|
|
|
|
|
|
AddKeywordToList(keyword);
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
menu.ShowAsContext();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 5. (可选) 添加一个手动刷新按钮
|
|
|
|
|
|
// 因为 AssetDatabase.FindAssets() 速度很快,所以我们也可以在每次GUI绘制时都调用
|
|
|
|
|
|
// 但如果词库很多,使用按钮刷新更好。
|
|
|
|
|
|
/*if (GUILayout.Button("Refresh Keyword Databases"))
|
|
|
|
|
|
{
|
|
|
|
|
|
LoadAllKeywordsFromEditRefs();
|
|
|
|
|
|
}*/
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void AddKeywordToList(string keyword)
|
|
|
|
|
|
{
|
|
|
|
|
|
keywordsProp.InsertArrayElementAtIndex(keywordsProp.arraySize);
|
|
|
|
|
|
SerializedProperty newElement = keywordsProp.GetArrayElementAtIndex(keywordsProp.arraySize - 1);
|
|
|
|
|
|
newElement.stringValue = keyword;
|
|
|
|
|
|
serializedObject.ApplyModifiedProperties();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-10-23 00:49:44 -04:00
|
|
|
|
}
|
|
|
|
|
|
#endif
|