mirror of
https://gitee.com/jisol/jisol-game/
synced 2025-09-27 02:36:14 +00:00
提交GAS 打算做一个帧同步的GAS
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
#if UNITY_EDITOR
|
||||
namespace GAS.Editor
|
||||
{
|
||||
using System;
|
||||
using System.IO;
|
||||
using GAS;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
public static class AbilitySystemComponentUtilGenerator
|
||||
{
|
||||
public static void Gen()
|
||||
{
|
||||
string pathWithoutAssets = Application.dataPath.Substring(0, Application.dataPath.Length - 6);
|
||||
var filePath =
|
||||
$"{pathWithoutAssets}/{GASSettingAsset.CodeGenPath}/{GasDefine.GAS_ASCUTIL_CSHARP_SCRIPT_NAME}";
|
||||
GenerateASCUtil(filePath);
|
||||
}
|
||||
|
||||
private static void GenerateASCUtil(string filePath)
|
||||
{
|
||||
using var writer = new IndentedWriter(new StreamWriter(filePath));
|
||||
|
||||
writer.WriteLine("///////////////////////////////////");
|
||||
writer.WriteLine("//// This is a generated file. ////");
|
||||
writer.WriteLine("//// Do not modify it. ////");
|
||||
writer.WriteLine("///////////////////////////////////");
|
||||
|
||||
writer.WriteLine("");
|
||||
|
||||
writer.WriteLine("using System;");
|
||||
writer.WriteLine("using System.Linq;");
|
||||
writer.WriteLine("using UnityEngine;");
|
||||
|
||||
writer.WriteLine("");
|
||||
|
||||
writer.WriteLine("namespace GAS.Runtime");
|
||||
writer.WriteLine("{");
|
||||
writer.Indent++;
|
||||
{
|
||||
writer.WriteLine("public static class AbilitySystemComponentExtension");
|
||||
writer.WriteLine("{");
|
||||
writer.Indent++;
|
||||
{
|
||||
writer.WriteLine("public static Type[] PresetAttributeSetTypes(this AbilitySystemComponent asc)");
|
||||
writer.WriteLine("{");
|
||||
writer.Indent++;
|
||||
{
|
||||
writer.WriteLine("if (asc.Preset == null) return null;");
|
||||
writer.WriteLine("var attrSetTypes = new Type[asc.Preset.AttributeSets.Length];");
|
||||
writer.WriteLine("for (var i = 0; i < asc.Preset.AttributeSets.Length; i++)");
|
||||
writer.Indent++;
|
||||
{
|
||||
writer.WriteLine(
|
||||
"attrSetTypes[i] = GAttrSetLib.AttrSetTypeDict[asc.Preset.AttributeSets[i]];");
|
||||
}
|
||||
writer.Indent--;
|
||||
writer.WriteLine("return attrSetTypes;");
|
||||
}
|
||||
writer.Indent--;
|
||||
writer.WriteLine("}");
|
||||
|
||||
writer.WriteLine("");
|
||||
|
||||
writer.WriteLine(
|
||||
"public static GameplayTag[] PresetBaseTags(this AbilitySystemComponent asc)");
|
||||
writer.WriteLine("{");
|
||||
writer.Indent++;
|
||||
{
|
||||
writer.WriteLine("if (asc.Preset == null) return null;");
|
||||
writer.WriteLine("return asc.Preset.BaseTags;");
|
||||
}
|
||||
writer.Indent--;
|
||||
writer.WriteLine("}");
|
||||
|
||||
writer.WriteLine("");
|
||||
|
||||
writer.WriteLine(
|
||||
"public static void InitWithPreset(this AbilitySystemComponent asc, int level, AbilitySystemComponentPreset preset = null)");
|
||||
writer.WriteLine("{");
|
||||
writer.Indent++;
|
||||
{
|
||||
writer.WriteLine("if (preset != null) asc.SetPreset(preset);");
|
||||
writer.WriteLine("if (asc.Preset == null) return;");
|
||||
|
||||
writer.WriteLine("");
|
||||
|
||||
writer.WriteLine("#if UNITY_EDITOR", true);
|
||||
writer.WriteLine("if (asc.Preset.BaseAbilities != null && asc.Preset.BaseAbilities.Any(x => x == null))");
|
||||
writer.WriteLine("{");
|
||||
writer.Indent++;
|
||||
{
|
||||
writer.WriteLine(
|
||||
"Debug.LogWarning($\"BaseAbilities contains null in preset: {asc.Preset.name}\");");
|
||||
}
|
||||
writer.Indent--;
|
||||
writer.WriteLine("}");
|
||||
writer.WriteLine("#endif", true);
|
||||
|
||||
writer.WriteLine("");
|
||||
|
||||
writer.WriteLine(
|
||||
"asc.Init(asc.PresetBaseTags(), asc.PresetAttributeSetTypes(), asc.Preset.BaseAbilities, level);");
|
||||
}
|
||||
writer.Indent--;
|
||||
writer.WriteLine("}");
|
||||
}
|
||||
|
||||
writer.Indent--;
|
||||
writer.WriteLine("}");
|
||||
}
|
||||
|
||||
writer.Indent--;
|
||||
writer.Write("}");
|
||||
|
||||
Console.WriteLine($"Generated AbilitySystemComponentExtension at path: {filePath}");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 81779b899f67484b9cb4241ac5a8077f
|
||||
timeCreated: 1706092633
|
@@ -0,0 +1,324 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using GAS.Editor.General;
|
||||
using GAS.General.Validation;
|
||||
using GAS.Runtime;
|
||||
using Sirenix.OdinInspector;
|
||||
using Sirenix.OdinInspector.Editor;
|
||||
using Sirenix.Utilities;
|
||||
using Sirenix.Utilities.Editor;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using Debug = UnityEngine.Debug;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace GAS.Editor
|
||||
{
|
||||
public class GASAssetAggregator : OdinMenuEditorWindow
|
||||
{
|
||||
private static readonly Type[] _types = new Type[5]
|
||||
{
|
||||
typeof(ModifierMagnitudeCalculation),
|
||||
typeof(GameplayCue),
|
||||
typeof(GameplayEffectAsset),
|
||||
typeof(AbilityAsset),
|
||||
typeof(AbilitySystemComponentPreset)
|
||||
};
|
||||
|
||||
private static string[] _libPaths;
|
||||
|
||||
static string[] LibPaths
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_libPaths == null) CheckLibPaths();
|
||||
return _libPaths;
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly DirectoryInfo[] _directoryInfos = new DirectoryInfo[5];
|
||||
private static readonly List<DirectoryInfo> _subDirectoryInfos = new List<DirectoryInfo>();
|
||||
|
||||
private static readonly string[] MenuNames = new string[5]
|
||||
{
|
||||
"A- Mod Magnitude Calculation",
|
||||
"A- Gameplay Cue",
|
||||
"B- Gameplay Effect",
|
||||
"C- Ability",
|
||||
"D- Ability System Component"
|
||||
};
|
||||
|
||||
private const string OpenWindow_MenuItemName = "EX-GAS/Asset Aggregator";
|
||||
#if EX_GAS_ENABLE_HOT_KEYS
|
||||
private const string OpenWindow_MenuItemNameEnh = OpenWindow_MenuItemName + " %F9";
|
||||
#else
|
||||
private const string OpenWindow_MenuItemNameEnh = OpenWindow_MenuItemName;
|
||||
#endif
|
||||
[MenuItem(OpenWindow_MenuItemNameEnh, priority = 1)]
|
||||
private static void OpenWindow()
|
||||
{
|
||||
CheckLibPaths();
|
||||
var window = GetWindow<GASAssetAggregator>();
|
||||
window.position = GUIHelper.GetEditorWindowRect().AlignCenter(1600, 900);
|
||||
window.MenuWidth = 240;
|
||||
}
|
||||
|
||||
private void ShowButton(Rect rect)
|
||||
{
|
||||
if (SirenixEditorGUI.SDFIconButton(rect, "GitHub", SdfIconType.Github))
|
||||
{
|
||||
Application.OpenURL("https://github.com/No78Vino/gameplay-ability-system-for-unity");
|
||||
}
|
||||
}
|
||||
|
||||
private static void CheckLibPaths()
|
||||
{
|
||||
_libPaths = new[]
|
||||
{
|
||||
GASSettingAsset.MMCLibPath,
|
||||
GASSettingAsset.GameplayCueLibPath,
|
||||
GASSettingAsset.GameplayEffectLibPath,
|
||||
GASSettingAsset.GameplayAbilityLibPath,
|
||||
GASSettingAsset.ASCLibPath,
|
||||
};
|
||||
|
||||
_subDirectoryInfos.Clear();
|
||||
for (var i = 0; i < _directoryInfos.Length; i++)
|
||||
{
|
||||
var rootMenuName = MenuNames[i];
|
||||
_directoryInfos[i] = new DirectoryInfo(rootMenuName, _libPaths[i], _libPaths[i], _types[i], true);
|
||||
|
||||
foreach (var subDir in _directoryInfos[i].SubDirectory)
|
||||
_subDirectoryInfos.Add(new DirectoryInfo(rootMenuName, _libPaths[i], subDir, _types[i], false));
|
||||
}
|
||||
}
|
||||
|
||||
protected override OdinMenuTree BuildMenuTree()
|
||||
{
|
||||
var tree = new OdinMenuTree();
|
||||
tree.Selection.SelectionChanged += OnMenuSelectionChange; //x => Debug.Log(x);
|
||||
for (var i = 0; i < MenuNames.Length; i++)
|
||||
{
|
||||
var menuName = MenuNames[i];
|
||||
var libPath = LibPaths[i];
|
||||
var type = _types[i];
|
||||
tree.Add(menuName, _directoryInfos[i]);
|
||||
if (menuName == MenuNames[3])
|
||||
{
|
||||
tree.Add(menuName, new AbilityOverview());
|
||||
}
|
||||
|
||||
tree.AddAllAssetsAtPath(menuName, libPath, type, true)
|
||||
.AddThumbnailIcons();
|
||||
}
|
||||
|
||||
foreach (var subDirectoryInfo in _subDirectoryInfos) tree.Add(subDirectoryInfo.MenuName, subDirectoryInfo);
|
||||
|
||||
tree.Config.DrawSearchToolbar = true;
|
||||
tree.Config.SearchToolbarHeight = 30;
|
||||
tree.Config.AutoScrollOnSelectionChanged = true;
|
||||
tree.Config.DrawScrollView = true;
|
||||
tree.Config.AutoHandleKeyboardNavigation = true;
|
||||
tree.SortMenuItemsByName(true);
|
||||
|
||||
return tree;
|
||||
}
|
||||
|
||||
protected override void OnBeginDrawEditors()
|
||||
{
|
||||
var selected = MenuTree.Selection.FirstOrDefault();
|
||||
var toolbarHeight = MenuTree.Config.SearchToolbarHeight;
|
||||
|
||||
// Draws a toolbar with the name of the currently selected menu item.
|
||||
SirenixEditorGUI.BeginHorizontalToolbar(toolbarHeight);
|
||||
{
|
||||
if (selected != null) GUILayout.Label(selected.Name + " (" + selected.Value.GetType().FullName + ")");
|
||||
|
||||
if (selected != null && (selected.Value is DirectoryInfo || selected.Value is AbilityOverview))
|
||||
{
|
||||
var directoryInfo = selected.Value is AbilityOverview
|
||||
? _directoryInfos[3]
|
||||
: selected.Value as DirectoryInfo;
|
||||
if (directoryInfo == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (SirenixEditorGUI.ToolbarButton(new GUIContent("浏览")))
|
||||
{
|
||||
OpenDirectoryInExplorer(directoryInfo);
|
||||
}
|
||||
|
||||
if (SirenixEditorGUI.ToolbarButton(new GUIContent("新建子文件夹")))
|
||||
{
|
||||
CreateNewSubDirectory(directoryInfo);
|
||||
GUIUtility.ExitGUI(); // In order to solve: "EndLayoutGroup: BeginLayoutGroup must be called first."
|
||||
}
|
||||
|
||||
if (SirenixEditorGUI.ToolbarButton(new GUIContent("新建")))
|
||||
{
|
||||
CreateNewAsset(directoryInfo);
|
||||
GUIUtility.ExitGUI(); // In order to solve: "EndLayoutGroup: BeginLayoutGroup must be called first."
|
||||
}
|
||||
|
||||
if (!directoryInfo.Root)
|
||||
{
|
||||
if (SirenixEditorGUI.ToolbarButton(new GUIContent("删除")))
|
||||
{
|
||||
RemoveSubDirectory(directoryInfo);
|
||||
GUIUtility.ExitGUI(); // In order to solve: "EndLayoutGroup: BeginLayoutGroup must be called first."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (selected is { Value: ScriptableObject asset })
|
||||
{
|
||||
if (SirenixEditorGUI.ToolbarButton(new GUIContent("定位")))
|
||||
{
|
||||
ShowInProject(asset);
|
||||
}
|
||||
|
||||
if (SirenixEditorGUI.ToolbarButton(new GUIContent("浏览")))
|
||||
{
|
||||
OpenAssetInExplorer(asset);
|
||||
}
|
||||
|
||||
if (SirenixEditorGUI.ToolbarButton(new GUIContent("定位脚本")))
|
||||
{
|
||||
var monoScript = MonoScript.FromScriptableObject(asset);
|
||||
string path = AssetDatabase.GetAssetPath(monoScript);
|
||||
|
||||
var obj = AssetDatabase.LoadAssetAtPath<Object>(path);
|
||||
ShowInProject(obj);
|
||||
}
|
||||
|
||||
if (SirenixEditorGUI.ToolbarButton(new GUIContent("编辑脚本")))
|
||||
{
|
||||
AssetDatabase.OpenAsset(MonoScript.FromScriptableObject(asset));
|
||||
}
|
||||
|
||||
if (SirenixEditorGUI.ToolbarButton(new GUIContent("删除")))
|
||||
{
|
||||
RemoveAsset(asset);
|
||||
}
|
||||
}
|
||||
|
||||
if (SirenixEditorGUI.ToolbarButton(new GUIContent("GAS设置")))
|
||||
{
|
||||
GASSettingAggregator.OpenWindow();
|
||||
}
|
||||
}
|
||||
SirenixEditorGUI.EndHorizontalToolbar();
|
||||
}
|
||||
|
||||
private void Refresh()
|
||||
{
|
||||
AssetDatabase.Refresh();
|
||||
CheckLibPaths();
|
||||
ForceMenuTreeRebuild();
|
||||
}
|
||||
|
||||
private void OpenDirectoryInExplorer(DirectoryInfo directoryInfo)
|
||||
{
|
||||
var path = directoryInfo.Directory.Replace("/", "\\");
|
||||
Process.Start("explorer.exe", path);
|
||||
}
|
||||
|
||||
private void ShowInProject(Object asset)
|
||||
{
|
||||
if (asset != null)
|
||||
{
|
||||
EditorGUIUtility.PingObject(asset);
|
||||
Selection.SetActiveObjectWithContext(asset, null);
|
||||
}
|
||||
}
|
||||
|
||||
private void OpenAssetInExplorer(ScriptableObject asset)
|
||||
{
|
||||
var path = AssetDatabase.GetAssetPath(asset).Replace("/", "\\");
|
||||
Process.Start("explorer.exe", path);
|
||||
}
|
||||
|
||||
private void CreateNewSubDirectory(DirectoryInfo directoryInfo)
|
||||
{
|
||||
StringEditWindow.OpenWindow("Sub Directory Name", "",
|
||||
s =>
|
||||
{
|
||||
var newPath = directoryInfo.Directory + "/" + s;
|
||||
var isExist = AssetDatabase.IsValidFolder(newPath);
|
||||
return isExist ? ValidationResult.Invalid("Folder already exists!") : ValidationResult.Valid;
|
||||
},
|
||||
s =>
|
||||
{
|
||||
var newPath = directoryInfo.Directory + "/" + s;
|
||||
AssetDatabase.CreateFolder(directoryInfo.Directory, s);
|
||||
Refresh();
|
||||
Debug.Log($"[EX] {newPath} folder created!");
|
||||
});
|
||||
}
|
||||
|
||||
private void RemoveSubDirectory(DirectoryInfo directoryInfo)
|
||||
{
|
||||
if (!EditorUtility.DisplayDialog("Warning", "Are you sure you want to delete this folder?", "Yes",
|
||||
"No")) return;
|
||||
|
||||
if (!EditorUtility.DisplayDialog("Second Warning", "ALL FILES in this folder will be DELETED!" +
|
||||
"\nAre you sure you want to DELETE this Folder?", "Yes",
|
||||
"No")) return;
|
||||
|
||||
AssetDatabase.DeleteAsset(directoryInfo.Directory);
|
||||
Refresh();
|
||||
Debug.Log($"[EX] {directoryInfo.Directory} folder deleted!");
|
||||
}
|
||||
|
||||
private void CreateNewAsset(DirectoryInfo directoryInfo)
|
||||
{
|
||||
if (directoryInfo.AssetType == _types[0])
|
||||
ScriptableObjectCreator.ShowDialog<ModifierMagnitudeCalculation>(directoryInfo.RootDirectory,
|
||||
TrySelectMenuItemWithObject);
|
||||
else if (directoryInfo.AssetType == _types[1])
|
||||
ScriptableObjectCreator.ShowDialog<GameplayCue>(directoryInfo.RootDirectory,
|
||||
TrySelectMenuItemWithObject);
|
||||
else if (directoryInfo.AssetType == _types[2])
|
||||
ScriptableObjectCreator.ShowDialog<GameplayEffectAsset>(directoryInfo.RootDirectory,
|
||||
TrySelectMenuItemWithObject);
|
||||
else if (directoryInfo.AssetType == _types[3])
|
||||
ScriptableObjectCreator.ShowDialog<AbilityAsset>(directoryInfo.RootDirectory,
|
||||
TrySelectMenuItemWithObject);
|
||||
else if (directoryInfo.AssetType == _types[4])
|
||||
ScriptableObjectCreator.ShowDialog<AbilitySystemComponentPreset>(directoryInfo.RootDirectory,
|
||||
TrySelectMenuItemWithObject);
|
||||
}
|
||||
|
||||
private void RemoveAsset(ScriptableObject asset)
|
||||
{
|
||||
if (asset == null)
|
||||
{
|
||||
EditorUtility.DisplayDialog("Warning", "The asset you want to delete is null", "Ok");
|
||||
return;
|
||||
}
|
||||
|
||||
var assetName = asset.name; // Get the name before deleting
|
||||
var assetPath = AssetDatabase.GetAssetPath(asset);
|
||||
if (EditorUtility.DisplayDialog("Warning",
|
||||
$"Are you sure you want to delete this asset?\n\nName=\"{assetName}\"\nPath=\"{assetPath}\""
|
||||
, "Yes", "No"))
|
||||
{
|
||||
AssetDatabase.DeleteAsset(assetPath);
|
||||
Refresh();
|
||||
Debug.Log($"[EX] delete asset: Name=\"{assetName}\", Path=\"{assetPath}\"");
|
||||
}
|
||||
}
|
||||
|
||||
void OnMenuSelectionChange(SelectionChangedType selectionChangedType)
|
||||
{
|
||||
var selected = MenuTree.Selection.FirstOrDefault();
|
||||
if (selected is { Value: AbilityOverview abilityOverview })
|
||||
{
|
||||
abilityOverview.Refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 59a3cfef5e254d3d8e63b6cfc84ec221
|
||||
timeCreated: 1704078623
|
@@ -0,0 +1,89 @@
|
||||
using Sirenix.OdinInspector.Editor;
|
||||
using Sirenix.Utilities;
|
||||
using Sirenix.Utilities.Editor;
|
||||
using UnityEditor;
|
||||
|
||||
namespace GAS.Editor
|
||||
{
|
||||
public class GASSettingAggregator : OdinMenuEditorWindow
|
||||
{
|
||||
private static GASSettingAsset _settingAsset;
|
||||
|
||||
private static GameplayTagsAsset _tagsAsset;
|
||||
|
||||
private static AttributeAsset _attributeAsset;
|
||||
|
||||
private static AttributeSetAsset _attributeSetAsset;
|
||||
|
||||
private static GASSettingAsset SettingAsset
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_settingAsset == null) _settingAsset = GASSettingAsset.LoadOrCreate();
|
||||
return _settingAsset;
|
||||
}
|
||||
}
|
||||
|
||||
private static GameplayTagsAsset TagsAsset
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_tagsAsset == null) _tagsAsset = GameplayTagsAsset.LoadOrCreate();
|
||||
return _tagsAsset;
|
||||
}
|
||||
}
|
||||
|
||||
private static AttributeAsset AttributeAsset
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_attributeAsset == null) _attributeAsset = AttributeAsset.LoadOrCreate();
|
||||
return _attributeAsset;
|
||||
}
|
||||
}
|
||||
|
||||
private static AttributeSetAsset AttributeSetAsset
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_attributeSetAsset == null) _attributeSetAsset = AttributeSetAsset.LoadOrCreate();
|
||||
return _attributeSetAsset;
|
||||
}
|
||||
}
|
||||
|
||||
private const string OpenWindow_MenuItemName = "EX-GAS/Settings";
|
||||
#if EX_GAS_ENABLE_HOT_KEYS
|
||||
private const string OpenWindow_MenuItemNameEnh = OpenWindow_MenuItemName + " %F12";
|
||||
#else
|
||||
private const string OpenWindow_MenuItemNameEnh = OpenWindow_MenuItemName;
|
||||
#endif
|
||||
[MenuItem(OpenWindow_MenuItemNameEnh, priority = 0)]
|
||||
public static void OpenWindow()
|
||||
{
|
||||
var window = GetWindow<GASSettingAggregator>();
|
||||
window.position = GUIHelper.GetEditorWindowRect().AlignCenter(1200, 600);
|
||||
}
|
||||
|
||||
protected override OdinMenuTree BuildMenuTree()
|
||||
{
|
||||
var tree = new OdinMenuTree();
|
||||
|
||||
tree.Add("Setting", SettingAsset);
|
||||
tree.Add("Tags", TagsAsset);
|
||||
tree.Add("Attribute", AttributeAsset);
|
||||
tree.Add("Attribute Set", AttributeSetAsset);
|
||||
|
||||
tree.Config.AutoScrollOnSelectionChanged = true;
|
||||
tree.Config.DrawScrollView = true;
|
||||
tree.Config.AutoHandleKeyboardNavigation = true;
|
||||
tree.Selection.SelectionChanged += type =>
|
||||
{
|
||||
GASSettingAsset.Save();
|
||||
GameplayTagsAsset.Save();
|
||||
AttributeAsset.Save();
|
||||
AttributeSetAsset.Save();
|
||||
};
|
||||
return tree;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f9375bc389fe4d75a24aa4ff97973977
|
||||
timeCreated: 1704195723
|
@@ -0,0 +1,220 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using GAS.General;
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GAS.Editor
|
||||
{
|
||||
[FilePath(GasDefine.GAS_BASE_SETTING_PATH)]
|
||||
public class GASSettingAsset : ScriptableSingleton<GASSettingAsset>
|
||||
{
|
||||
private const int LABEL_WIDTH = 200;
|
||||
private const int SHORT_LABEL_WIDTH = 200;
|
||||
private static GASSettingAsset _setting;
|
||||
|
||||
|
||||
[Title(GASTextDefine.TITLE_SETTING, Bold = true)]
|
||||
[BoxGroup("A", false, order: 1)]
|
||||
[LabelText(GASTextDefine.LABEL_OF_CodeGeneratePath)]
|
||||
[LabelWidth(LABEL_WIDTH)]
|
||||
[FolderPath]
|
||||
[OnValueChanged("SaveAsset")]
|
||||
public string CodeGeneratePath = "Assets/Scripts/Gen";
|
||||
|
||||
[BoxGroup("A")]
|
||||
[LabelText(GASTextDefine.LABEL_OF_GASConfigAssetPath)]
|
||||
[LabelWidth(LABEL_WIDTH)]
|
||||
[FolderPath]
|
||||
[OnValueChanged("SaveAsset")]
|
||||
public string GASConfigAssetPath = "Assets/GAS/Config";
|
||||
|
||||
public static GASSettingAsset Setting
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_setting == null) _setting = LoadOrCreate();
|
||||
return _setting;
|
||||
}
|
||||
}
|
||||
|
||||
[ShowInInspector]
|
||||
[BoxGroup("V", false, order: 0)]
|
||||
[HideLabel]
|
||||
[DisplayAsString(TextAlignment.Left, true)]
|
||||
private static string Version =>
|
||||
$"<size=15><b><color=white>EX-GAS Version: {GasDefine.GAS_VERSION}</color></b></size>";
|
||||
|
||||
public static string CodeGenPath => Setting.CodeGeneratePath;
|
||||
|
||||
|
||||
[Title(GASTextDefine.TITLE_PATHS, Bold = true)]
|
||||
[PropertySpace(10)]
|
||||
[ShowInInspector]
|
||||
[BoxGroup("A")]
|
||||
[DisplayAsString(TextAlignment.Left, true)]
|
||||
[LabelWidth(SHORT_LABEL_WIDTH)]
|
||||
public static string ASCLibPath => $"{Setting.GASConfigAssetPath}/{GasDefine.GAS_ASC_LIBRARY_FOLDER}";
|
||||
|
||||
[ShowInInspector]
|
||||
[BoxGroup("A")]
|
||||
[DisplayAsString(TextAlignment.Left, true)]
|
||||
[LabelWidth(SHORT_LABEL_WIDTH)]
|
||||
public static string GameplayEffectLibPath =>
|
||||
$"{Setting.GASConfigAssetPath}/{GasDefine.GAS_EFFECT_LIBRARY_FOLDER}";
|
||||
|
||||
[ShowInInspector]
|
||||
[BoxGroup("A")]
|
||||
[DisplayAsString(TextAlignment.Left, true)]
|
||||
[LabelWidth(SHORT_LABEL_WIDTH)]
|
||||
public static string GameplayAbilityLibPath =>
|
||||
$"{Setting.GASConfigAssetPath}/{GasDefine.GAS_ABILITY_LIBRARY_FOLDER}";
|
||||
|
||||
[ShowInInspector]
|
||||
[BoxGroup("A")]
|
||||
[DisplayAsString(TextAlignment.Left, true)]
|
||||
[LabelWidth(SHORT_LABEL_WIDTH)]
|
||||
public static string GameplayCueLibPath => $"{Setting.GASConfigAssetPath}/{GasDefine.GAS_CUE_LIBRARY_FOLDER}";
|
||||
|
||||
[ShowInInspector]
|
||||
[BoxGroup("A")]
|
||||
[DisplayAsString(TextAlignment.Left, true)]
|
||||
[LabelWidth(SHORT_LABEL_WIDTH)]
|
||||
public static string MMCLibPath => $"{Setting.GASConfigAssetPath}/{GasDefine.GAS_MMC_LIBRARY_FOLDER}";
|
||||
|
||||
[ShowInInspector]
|
||||
[BoxGroup("A")]
|
||||
[DisplayAsString(TextAlignment.Left, true)]
|
||||
[LabelWidth(SHORT_LABEL_WIDTH)]
|
||||
public static string AbilityTaskLib =>
|
||||
$"{Setting.GASConfigAssetPath}/{GasDefine.GAS_ABILITY_TASK_LIBRARY_FOLDER}";
|
||||
|
||||
[ShowInInspector]
|
||||
[BoxGroup("A")]
|
||||
[DisplayAsString(TextAlignment.Left, true)]
|
||||
[LabelWidth(SHORT_LABEL_WIDTH)]
|
||||
[LabelText("Tag Asset Path")]
|
||||
public static string GAS_TAG_ASSET_PATH => GasDefine.GAS_TAGS_MANAGER_ASSET_PATH;
|
||||
|
||||
[ShowInInspector]
|
||||
[BoxGroup("A")]
|
||||
[DisplayAsString(TextAlignment.Left, true)]
|
||||
[LabelWidth(SHORT_LABEL_WIDTH)]
|
||||
[LabelText("Attribute Asset Path")]
|
||||
public static string GAS_ATTRIBUTE_ASSET_PATH => GasDefine.GAS_ATTRIBUTE_ASSET_PATH;
|
||||
|
||||
[ShowInInspector]
|
||||
[BoxGroup("A")]
|
||||
[DisplayAsString(TextAlignment.Left, true)]
|
||||
[LabelWidth(SHORT_LABEL_WIDTH)]
|
||||
[LabelText("AttributeSet Asset Path")]
|
||||
public static string GAS_ATTRIBUTESET_ASSET_PATH => GasDefine.GAS_ATTRIBUTE_SET_ASSET_PATH;
|
||||
|
||||
void CheckPathFolderExist(string folderPath)
|
||||
{
|
||||
var folders = folderPath.Split('/');
|
||||
if (folders[0] != "Assets")
|
||||
{
|
||||
EditorUtility.DisplayDialog("Error!", "'Config Asset Path/Code Gen Path' must start with Assets!",
|
||||
"OK");
|
||||
return;
|
||||
}
|
||||
|
||||
string parentFolderPath = folders[0];
|
||||
for (var i = 1; i < folders.Length; i++)
|
||||
{
|
||||
string newFolderName = folders[i];
|
||||
if (newFolderName == "") continue;
|
||||
|
||||
string newFolderPath = parentFolderPath + "/" + newFolderName;
|
||||
if (!AssetDatabase.IsValidFolder(newFolderPath))
|
||||
{
|
||||
AssetDatabase.CreateFolder(parentFolderPath, newFolderName);
|
||||
Debug.Log("[EX] Folder created at path: " + newFolderPath);
|
||||
}
|
||||
|
||||
parentFolderPath += "/" + newFolderName;
|
||||
}
|
||||
}
|
||||
|
||||
[BoxGroup("A")]
|
||||
[DisplayAsString(TextAlignment.Left, true)]
|
||||
[GUIColor(0, 0.8f, 0)]
|
||||
[PropertySpace(10)]
|
||||
[InfoBox(GASTextDefine.TIP_CREATE_FOLDERS)]
|
||||
[Button(SdfIconType.FolderCheck, GASTextDefine.BUTTON_CheckAllPathFolderExist, ButtonHeight = 38)]
|
||||
void CheckAllPathFolderExist()
|
||||
{
|
||||
CheckPathFolderExist(GASConfigAssetPath);
|
||||
CheckPathFolderExist(CodeGeneratePath);
|
||||
CheckPathFolderExist(ASCLibPath);
|
||||
CheckPathFolderExist(GameplayAbilityLibPath);
|
||||
CheckPathFolderExist(GameplayEffectLibPath);
|
||||
CheckPathFolderExist(GameplayCueLibPath);
|
||||
CheckPathFolderExist(MMCLibPath);
|
||||
CheckPathFolderExist(AbilityTaskLib);
|
||||
AssetDatabase.Refresh();
|
||||
}
|
||||
|
||||
[BoxGroup("A")]
|
||||
[DisplayAsString(TextAlignment.Left, true)]
|
||||
[GUIColor(0.8f, 0.8f, 0)]
|
||||
[PropertySpace(10)]
|
||||
[InfoBox(GASTextDefine.TIP_CREATE_GEN_AscUtilCode)]
|
||||
[Button(SdfIconType.Upload, GASTextDefine.BUTTON_GenerateAscExtensionCode, ButtonHeight = 38)]
|
||||
void GenerateAscExtensionCode()
|
||||
{
|
||||
string pathWithoutAssets = Application.dataPath.Substring(0, Application.dataPath.Length - 6);
|
||||
var filePath =
|
||||
$"{pathWithoutAssets}/{CodeGenPath}/{GasDefine.GAS_ATTRIBUTESET_LIB_CSHARP_SCRIPT_NAME}";
|
||||
|
||||
if (!File.Exists(filePath))
|
||||
{
|
||||
EditorUtility.DisplayDialog("Error!", "Please generate AttributeSetAsset first!", "OK");
|
||||
return;
|
||||
}
|
||||
|
||||
AbilitySystemComponentUtilGenerator.Gen();
|
||||
AssetDatabase.Refresh();
|
||||
}
|
||||
|
||||
private void SaveAsset()
|
||||
{
|
||||
if (Instance == this) return;
|
||||
UpdateAsset(this);
|
||||
Save();
|
||||
}
|
||||
|
||||
private const string EX_GAS_ENABLE_HOT_KEYS = "EX_GAS_ENABLE_HOT_KEYS";
|
||||
|
||||
#if EX_GAS_ENABLE_HOT_KEYS
|
||||
public const bool EnableHotKeys = true;
|
||||
#else
|
||||
public const bool EnableHotKeys = false;
|
||||
#endif
|
||||
|
||||
[TabGroup("Advance", "Advance", SdfIconType.Gear, TextColor = "#FF7F00"), PropertyOrder(1)]
|
||||
[InfoBox(
|
||||
"@\"当前快捷键状态: \" + (EnableHotKeys ? \"启用\":\"禁用\") + \", 冲突时可禁用快捷键\"")]
|
||||
#if EX_GAS_ENABLE_HOT_KEYS
|
||||
[Button(SdfIconType.ToggleOn, "禁用快捷键")]
|
||||
#else
|
||||
[Button(SdfIconType.ToggleOff, "开启快捷键")]
|
||||
#endif
|
||||
private void ToggleScriptDefineSymbol_EX_GAS_ENABLE_HOT_KEYS()
|
||||
{
|
||||
if (EditorUtility.DisplayDialog("Ex-GAS",
|
||||
"切换快捷键状态\n将在你的项目中切换\"EX_GAS_ENABLE_HOT_KEYS\"宏定义\n\n这会重新编译你的代码, 之后你可能需要手动保存你的项目(请留意ProjectSettings.asset的变化).",
|
||||
"确定", "取消"))
|
||||
{
|
||||
#pragma warning disable 162
|
||||
if (EnableHotKeys)
|
||||
ScriptingDefineSymbolsHelper.Remove(EX_GAS_ENABLE_HOT_KEYS);
|
||||
else
|
||||
ScriptingDefineSymbolsHelper.Add(EX_GAS_ENABLE_HOT_KEYS);
|
||||
#pragma warning restore 162
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0bf62a9aa7db48b38f37313afe3e6ef5
|
||||
timeCreated: 1703687775
|
@@ -0,0 +1,68 @@
|
||||
#if UNITY_EDITOR
|
||||
namespace GAS.Editor
|
||||
{
|
||||
using GAS;
|
||||
using UnityEngine.UIElements;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
public class GASSettingProvider: SettingsProvider
|
||||
{
|
||||
private GASSettingAsset _asset;
|
||||
private Editor _editor;
|
||||
|
||||
public GASSettingProvider() : base("Project/EX Gameplay Ability System", SettingsScope.Project)
|
||||
{
|
||||
}
|
||||
|
||||
public override void OnActivate(string searchContext, VisualElement rootElement)
|
||||
{
|
||||
var asset = GASSettingAsset.LoadOrCreate();
|
||||
_asset = asset;
|
||||
_editor = Editor.CreateEditor(asset);
|
||||
GASSettingStatusWatcher.OnEditorFocused += OnEditorFocused;
|
||||
}
|
||||
|
||||
public override void OnDeactivate()
|
||||
{
|
||||
base.OnDeactivate();
|
||||
GASSettingStatusWatcher.OnEditorFocused -= OnEditorFocused;
|
||||
GASSettingAsset.UpdateAsset(_asset);
|
||||
GASSettingAsset.Save();
|
||||
}
|
||||
|
||||
private void OnEditorFocused()
|
||||
{
|
||||
Repaint();
|
||||
}
|
||||
|
||||
public override void OnGUI(string searchContext)
|
||||
{
|
||||
base.OnGUI(searchContext);
|
||||
|
||||
if (_editor == null) return;
|
||||
|
||||
EditorGUILayout.BeginVertical(GUI.skin.box);
|
||||
|
||||
EditorGUILayout.Space();
|
||||
_editor.OnInspectorGUI();
|
||||
EditorGUILayout.EndVertical();
|
||||
}
|
||||
|
||||
static GASSettingProvider provider;
|
||||
[SettingsProvider]
|
||||
public static SettingsProvider CreateMyCustomSettingsProvider()
|
||||
{
|
||||
if (GASSettingAsset.Instance && provider == null)
|
||||
{
|
||||
provider = new GASSettingProvider();
|
||||
using (var so = new SerializedObject(GASSettingAsset.Instance))
|
||||
{
|
||||
provider.keywords = GetSearchKeywordsFromSerializedObject(so);
|
||||
}
|
||||
}
|
||||
return provider;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 81d7aa17f3a54ba4b75b15dc751012f2
|
||||
timeCreated: 1703687613
|
296
JEX_GAS/Assets/GAS/Editor/GameplayAbilitySystem/GASWatcher.cs
Normal file
296
JEX_GAS/Assets/GAS/Editor/GameplayAbilitySystem/GASWatcher.cs
Normal file
@@ -0,0 +1,296 @@
|
||||
#if UNITY_EDITOR
|
||||
namespace GAS.Editor
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using Runtime;
|
||||
using Sirenix.OdinInspector;
|
||||
using Sirenix.OdinInspector.Editor;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using GAS.General;
|
||||
|
||||
public class GASWatcher : OdinEditorWindow
|
||||
{
|
||||
private const string BOXGROUP_TIPS = "Tips";
|
||||
private const string BOXGROUP_TIPS_RUNNINGTIP = "Tips/Running tip";
|
||||
private const string BOXGROUP_ASC = "Ability System Components";
|
||||
private const string BOXGROUP_ASC_H = "Ability System Components/H";
|
||||
private const string BOXGROUP_ASC_H_L = "Ability System Components/H/L";
|
||||
private const string BOXGROUP_ASC_H_R = "Ability System Components/H/R";
|
||||
private const string BOXGROUP_ASC_H_R_A = "Ability System Components/H/R/A";
|
||||
private const string BOXGROUP_ASC_H_R_A_V = "Ability System Components/H/R/A/V1";
|
||||
private const string BOXGROUP_ASC_H_R_A_VB = "Ability System Components/H/R/A/VB";
|
||||
private const string BOXGROUP_ASC_H_R_A_VC = "Ability System Components/H/R/A/VC";
|
||||
|
||||
private AbilitySystemComponent _selected;
|
||||
|
||||
[HideLabel]
|
||||
[DisplayAsString(TextAlignment.Center, true)]
|
||||
public string windowTitle = "<size=18><b>EX Gameplay Ability System Watcher</b></size>";
|
||||
|
||||
[BoxGroup(BOXGROUP_TIPS)]
|
||||
[HideLabel]
|
||||
[DisplayAsString(TextAlignment.Left, true)]
|
||||
public string tips = GASTextDefine.TIP_WATCHER;
|
||||
|
||||
[BoxGroup(BOXGROUP_TIPS_RUNNINGTIP, false)]
|
||||
[HideLabel]
|
||||
[DisplayAsString(TextAlignment.Center, true)]
|
||||
[HideIf("IsPlaying")]
|
||||
public string onlyForGameRunning = GASTextDefine.TIP_WATCHER_OnlyForGameRunning;
|
||||
|
||||
|
||||
[BoxGroup(BOXGROUP_ASC)]
|
||||
[HorizontalGroup(BOXGROUP_ASC_H, 300)]
|
||||
[BoxGroup(BOXGROUP_ASC_H_L, false)]
|
||||
[OnInspectorGUI("OnDrawNavi")]
|
||||
[DisplayAsString(TextAlignment.Center)]
|
||||
[HideLabel]
|
||||
[ShowIf("IsPlaying")]
|
||||
public string Navis = "NAVI";
|
||||
|
||||
[HorizontalGroup(BOXGROUP_ASC_H)]
|
||||
[BoxGroup(BOXGROUP_ASC_H_R, false)]
|
||||
[HorizontalGroup(BOXGROUP_ASC_H_R_A, PaddingRight = 0.01f)]
|
||||
[VerticalGroup(BOXGROUP_ASC_H_R_A_V)]
|
||||
[Title("ID Mark", bold: true)]
|
||||
[DisplayAsString]
|
||||
[LabelWidth(75)]
|
||||
[ShowIf("IsPlaying")]
|
||||
public int IID;
|
||||
|
||||
[VerticalGroup(BOXGROUP_ASC_H_R_A_V)]
|
||||
[ReadOnly]
|
||||
[LabelWidth(75)]
|
||||
[ShowIf("IsPlaying")]
|
||||
public GameObject instance;
|
||||
|
||||
[VerticalGroup(BOXGROUP_ASC_H_R_A_V)]
|
||||
[DisplayAsString]
|
||||
[LabelWidth(75)]
|
||||
[ShowIf("IsPlaying")]
|
||||
public int Level;
|
||||
|
||||
[Space]
|
||||
[Title("Abilities", bold: true)]
|
||||
[VerticalGroup(BOXGROUP_ASC_H_R_A_V)]
|
||||
[ListDrawerSettings(ShowFoldout = true, ShowIndexLabels = false, ShowItemCount = true, IsReadOnly = true,
|
||||
ShowPaging = false)]
|
||||
[DisplayAsString]
|
||||
[LabelText(" ")]
|
||||
[ShowIf("IsPlaying")]
|
||||
[Searchable]
|
||||
public List<string> Abilities = new List<string>();
|
||||
|
||||
[HorizontalGroup(BOXGROUP_ASC_H_R_A, PaddingRight = 0.01f)]
|
||||
[VerticalGroup(BOXGROUP_ASC_H_R_A_VB)]
|
||||
[Title("Attributes", bold: true)]
|
||||
[ListDrawerSettings(ShowFoldout = true, ShowIndexLabels = false, ShowItemCount = true, IsReadOnly = true,
|
||||
ShowPaging = false)]
|
||||
[DisplayAsString]
|
||||
[LabelText(" ")]
|
||||
[ShowIf("IsPlaying")]
|
||||
[Searchable]
|
||||
public List<string> Attributes = new List<string>();
|
||||
|
||||
|
||||
[HorizontalGroup(BOXGROUP_ASC_H_R_A, PaddingRight = 0.01f)]
|
||||
[Title("GameplayEffects", bold: true)]
|
||||
[ListDrawerSettings(ShowFoldout = true, ShowIndexLabels = false, ShowItemCount = true, IsReadOnly = true,
|
||||
ShowPaging = false)]
|
||||
[DisplayAsString]
|
||||
[LabelText(" ")]
|
||||
[InfoBox("format: [ActiveState][DurationInfo]GeName", InfoMessageType.None, "IsPlaying")]
|
||||
[ShowIf("IsPlaying")]
|
||||
[Searchable]
|
||||
public List<string> Effects = new List<string>();
|
||||
|
||||
|
||||
[HorizontalGroup(BOXGROUP_ASC_H_R_A)]
|
||||
[VerticalGroup(BOXGROUP_ASC_H_R_A_VC)]
|
||||
[Title("Tags", bold: true)]
|
||||
[ListDrawerSettings(ShowFoldout = true, ShowIndexLabels = false, ShowItemCount = true, IsReadOnly = true,
|
||||
ShowPaging = false)]
|
||||
[DisplayAsString]
|
||||
[ShowIf("IsPlaying")]
|
||||
[Searchable]
|
||||
public List<string> FixedTag = new List<string>();
|
||||
|
||||
[Title(" ", bold: true)]
|
||||
[VerticalGroup(BOXGROUP_ASC_H_R_A_VC)]
|
||||
[ListDrawerSettings(ShowFoldout = true, ShowIndexLabels = false, ShowItemCount = true, IsReadOnly = true,
|
||||
ShowPaging = false)]
|
||||
[DisplayAsString]
|
||||
[ShowIf("IsPlaying")]
|
||||
[Searchable]
|
||||
public List<string> DynamicTag = new List<string>();
|
||||
|
||||
|
||||
private Vector2 menuScrollPos;
|
||||
|
||||
private bool IsPlaying => Application.isPlaying;
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (IsPlaying)
|
||||
{
|
||||
if (_selected == null || _selected.gameObject == null)
|
||||
{
|
||||
_selected = GAS.GameplayAbilitySystem.GAS.AbilitySystemComponents.Count > 0
|
||||
? GAS.GameplayAbilitySystem.GAS.AbilitySystemComponents[0] as AbilitySystemComponent
|
||||
: null;
|
||||
}
|
||||
|
||||
RefreshAscInfo();
|
||||
Repaint();
|
||||
}
|
||||
}
|
||||
|
||||
private const string OpenWindow_MenuItemName = "EX-GAS/Runtime Watcher";
|
||||
#if EX_GAS_ENABLE_HOT_KEYS
|
||||
private const string OpenWindow_MenuItemNameEnh = OpenWindow_MenuItemName + " %F11";
|
||||
#else
|
||||
private const string OpenWindow_MenuItemNameEnh = OpenWindow_MenuItemName;
|
||||
#endif
|
||||
[MenuItem(OpenWindow_MenuItemNameEnh, priority = 3)]
|
||||
private static void OpenWindow()
|
||||
{
|
||||
var window = GetWindow<GASWatcher>();
|
||||
window.titleContent = new GUIContent("EX Gameplay Ability System Watcher");
|
||||
window.Show();
|
||||
}
|
||||
|
||||
void OnDrawNavi()
|
||||
{
|
||||
if (!IsPlaying) return;
|
||||
|
||||
menuScrollPos = EditorGUILayout.BeginScrollView(menuScrollPos, GUI.skin.box);
|
||||
foreach (var iasc in GAS.GameplayAbilitySystem.GAS.AbilitySystemComponents)
|
||||
{
|
||||
var asc = (AbilitySystemComponent)iasc;
|
||||
var presetName = asc.Preset != null ? asc.Preset.name : "NoPreset";
|
||||
if (GUILayout.Button($"{presetName}#{asc.GetInstanceID()}"))
|
||||
{
|
||||
_selected = asc;
|
||||
RefreshAscInfo();
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUILayout.EndScrollView();
|
||||
}
|
||||
|
||||
private void RefreshAscInfo()
|
||||
{
|
||||
if (_selected == null)
|
||||
{
|
||||
IID = 0;
|
||||
instance = null;
|
||||
Level = 0;
|
||||
Abilities.Clear();
|
||||
Attributes.Clear();
|
||||
Effects.Clear();
|
||||
FixedTag.Clear();
|
||||
DynamicTag.Clear();
|
||||
return;
|
||||
}
|
||||
|
||||
IID = _selected.GetInstanceID();
|
||||
instance = _selected.gameObject;
|
||||
Level = _selected.Level;
|
||||
|
||||
RefreshAbilityInfo();
|
||||
RefreshAttributesInfo();
|
||||
RefreshGameplayEffectsInfo();
|
||||
RefreshTagsInfo();
|
||||
}
|
||||
|
||||
|
||||
private void RefreshGameplayEffectsInfo()
|
||||
{
|
||||
Effects.Clear();
|
||||
foreach (var ge in _selected.GameplayEffectContainer.GameplayEffects())
|
||||
{
|
||||
string isActive = ge.IsActive ? "√" : "×";
|
||||
string durationStr = ge.DurationPolicy switch
|
||||
{
|
||||
EffectsDurationPolicy.Duration => $"{ge.DurationRemaining():N2}/{ge.Duration:N2}(s)",
|
||||
EffectsDurationPolicy.Infinite => "∞",
|
||||
EffectsDurationPolicy.Instant => "N/A",
|
||||
_ => "Unknown"
|
||||
};
|
||||
var stackCountText = ge.Stacking.stackingType != StackingType.None ? $"[S:{ge.StackCount}]" : "";
|
||||
Effects.Add($"[{isActive}][{durationStr}]{stackCountText}{ge.GameplayEffect.GameplayEffectName}");
|
||||
}
|
||||
}
|
||||
|
||||
private void RefreshAbilityInfo()
|
||||
{
|
||||
Abilities.Clear();
|
||||
foreach (var ability in _selected.AbilityContainer.AbilitySpecs())
|
||||
{
|
||||
string isActive = ability.Value.IsActive ? "(Active)" : "";
|
||||
Abilities.Add($"{ability.Key} | Lv.{ability.Value.Level} {isActive}");
|
||||
}
|
||||
}
|
||||
|
||||
private void RefreshAttributesInfo()
|
||||
{
|
||||
Attributes.Clear();
|
||||
foreach (var (attributeSetName, attributeSet) in _selected.AttributeSetContainer.Sets)
|
||||
{
|
||||
Attributes.Add($"AttributeSet: {attributeSetName} ↓");
|
||||
foreach (var attributeName in attributeSet.AttributeNames)
|
||||
{
|
||||
var attr = attributeSet[attributeName];
|
||||
Attributes.Add(
|
||||
$" - {attributeName} = {attr.CurrentValue:N2}({attr.BaseValue:N2} + {attr.CurrentValue - attr.BaseValue:N2})");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void RefreshTagsInfo()
|
||||
{
|
||||
RefreshFixedTagsInfo();
|
||||
RefreshDynamicTagsInfo();
|
||||
}
|
||||
|
||||
void RefreshFixedTagsInfo()
|
||||
{
|
||||
FixedTag.Clear();
|
||||
foreach (var tag in _selected.GameplayTagAggregator.FixedTags)
|
||||
{
|
||||
FixedTag.Add(tag.Name);
|
||||
}
|
||||
}
|
||||
|
||||
void RefreshDynamicTagsInfo()
|
||||
{
|
||||
DynamicTag.Clear();
|
||||
foreach (var kv in _selected.GameplayTagAggregator.DynamicAddedTags)
|
||||
{
|
||||
var tagName = kv.Key.Name;
|
||||
DynamicTag.Add($"{tagName} ↓ ");
|
||||
|
||||
foreach (var obj in kv.Value)
|
||||
{
|
||||
switch (obj)
|
||||
{
|
||||
case GameplayEffectSpec spec:
|
||||
{
|
||||
DynamicTag.Add(
|
||||
$" - From: {spec.Owner.GetInstanceID()}'s GE: {spec.GameplayEffect.GameplayEffectName}");
|
||||
break;
|
||||
}
|
||||
case AbilitySpec ability:
|
||||
{
|
||||
DynamicTag.Add(
|
||||
$" - From: {ability.Owner.GetInstanceID()}'s Ability: {ability.Ability.Name}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fdb20e1777ef464d86716c3505cab9a6
|
||||
timeCreated: 1702628354
|
Reference in New Issue
Block a user