我死去

目前添加了一个能够深度查找和设置反射的helper,但是Tag的系统仍然不完全,另外我觉得console可以重构了

Signed-off-by: TRAfoer <lhf190@outlook.com>
This commit is contained in:
2025-12-14 12:15:07 +08:00
parent 1bbb1c51ab
commit 7a2bc844bd
22 changed files with 127636 additions and 35827 deletions

View File

@@ -113,21 +113,19 @@ namespace Ichni.RhythmGame
}
namespace Ichni.Editor
{
public class TagManager : IBaseElement//这玩意大概不需要分BM的
public class TagManager : IBaseElement
{
// ... (你的原有代码: matchedBM, 构造函数等保持不变) ...
public BaseElement_BM matchedBM { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
public List<TagMatcher> tagMatchers;
public TagManager()
{
tagMatchers = new List<TagMatcher>();
tempTagMatcherName = "";
tempElementTypeName = "";
tempParameterName = "";
// ...
}
// ... (Add/Remove 方法保持不变) ...
public void AddTagMatcher(string name, Type elementType, string parameterName)
{
//check
@@ -161,51 +159,53 @@ namespace Ichni.Editor
{
RemoveTagMatcher(tagMatchers.First(i => i.name == o));
}
// ... 其他 Add/Remove ...
public List<IBaseElement> GetMachedElements(TagMatcher o)
{
return EditorManager.instance.beatmapContainer.gameElementList
.Where(p => o.Match(p)).Cast<IBaseElement>().ToList();
.Where(p => o.Match(p)).Cast<IBaseElement>().ToList();
}
public List<TagMatcher> GetMatcher(GameElement baseElement)
{
return tagMatchers.Where(p => p.Match(baseElement)).ToList();
}
// --- 修改 1: 使用 ReflectionHelper 设置值 ---
public void SetMatchedElements(TagMatcher o, object value)
{
foreach (var i in GetMachedElements(o))
{
// 直接调用修改后的 SetValue
o.SetValue(i, value);
}
}
// --- 修改 2: 使用 ReflectionHelper 同步值 ---
public void SyncTagedElement(GameElement gameElement)
{
foreach (var matcher in GetMatcher(gameElement))
{
var matchedElements = GetMachedElements(matcher);
// A. 获取源值 (使用 ReflectionHelper 以支持嵌套路径,如 "transform.position")
var value = ReflectionHelper.GetDeepValue(gameElement, matcher.parameterName);
foreach (var element in matchedElements)
{
var value = gameElement.GetType().GetField(matcher.parameterName).GetValue(gameElement);
// B. 设置目标值 (TagMatcher 内部现在使用 ReflectionHelper)
matcher.SetValue(element, value);
element.Refresh();
}
}
}
public string tempTagMatcherName = "";
public string tempElementTypeName = "";
public string tempParameterName = "";
public void SetUpInspector()
internal void SetUpInspector()
{
tempTagMatcherName = "";
tempElementTypeName = "";
tempParameterName = "";
// tempTagMatcherName = "";
// tempElementTypeName = "";
// tempParameterName = "";
IHaveInspection inspector = EditorManager.instance.uiManager.inspector;
Inspector inspectorMain = EditorManager.instance.uiManager.inspector;
var container = inspector.GenerateContainer("Tag Manager");
@@ -217,7 +217,11 @@ namespace Ichni.Editor
var sub = container.GenerateSubcontainer(2);
inspector.GenerateHintText(this, sub, $"Name: {matcher.name}");
inspector.GenerateHintText(this, sub, $"Type: {matcher.ElementType?.Name ?? "<null>"}");
inspector.GenerateHintText(this, sub, $"Param: {matcher.parameterName}");
var e = inspector.GenerateInputField(sub, "Parameter", matcher.parameterName);
e.AddListenerFunction(() =>
{
matcher.parameterName = e.inputField.text;
});
inspector.GenerateButton(this, sub, "Remove", () =>
{
RemoveTagMatcher(matcher);
@@ -225,86 +229,96 @@ namespace Ichni.Editor
});
}
// 新增TagMatcher区域
var addSub = container.GenerateSubcontainer(3);
// 输入Tag名称
var nameInput = inspector.GenerateInputField(this, addSub, "Tag Name", nameof(tempTagMatcherName));
// 下拉选择类型
List<Type> typeList = TypeHelper.GetInheritedTypes<GameElement>();
List<string> typeNames = typeList.ConvertAll(t => t.FullName);
var typeDropdown = inspector.GenerateDropdown(this, addSub, "Element Type", typeNames, nameof(tempElementTypeName))
.AddListenerFunction(() =>
{
// 选择类型后刷新参数下拉
Type selectedType = typeList.FirstOrDefault(t => t.FullName == tempElementTypeName);
List<string> paramNames = selectedType != null
? selectedType.GetFields().Select(f => f.Name).ToList()
: new List<string>();
//inspector.GenerateDropdown(this, addSub, "Parameter", paramNames, nameof(tempParameterName));
});
// // 新增TagMatcher区域
// var addSub = container.GenerateSubcontainer(3);
// // 输入Tag名称
// var nameInput = inspector.GenerateInputField(this, addSub, "Tag Name", nameof(tempTagMatcherName));
// // 下拉选择类型
// List<Type> typeList = TypeHelper.GetInheritedTypes<GameElement>();
// List<string> typeNames = typeList.ConvertAll(t => t.FullName);
// var typeDropdown = inspector.GenerateDropdown(this, addSub, "Element Type", typeNames, nameof(tempElementTypeName))
// .AddListenerFunction(() =>
// {
// // 选择类型后刷新参数下拉
// Type selectedType = typeList.FirstOrDefault(t => t.FullName == tempElementTypeName);
// List<string> paramNames = selectedType != null
// ? selectedType.GetFields().Select(f => f.Name).ToList()
// : new List<string>();
// //inspector.GenerateDropdown(this, addSub, "Parameter", paramNames, nameof(tempParameterName));
// });
// 参数下拉(初始为空,随类型变化刷新)
if (!string.IsNullOrEmpty(tempElementTypeName))
{
Type selectedType = typeList.FirstOrDefault(t => t.FullName == tempElementTypeName);
List<string> paramNames = selectedType != null
? selectedType.GetFields().Select(f => f.Name).ToList()
: new List<string>();
inspector.GenerateDropdown(this, addSub, "Parameter", paramNames, nameof(tempParameterName));
}
else
{
inspector.GenerateDropdown(this, addSub, "Parameter", new List<string>(), nameof(tempParameterName));
}
// if (!string.IsNullOrEmpty(tempElementTypeName))
// {
// Type selectedType = typeList.FirstOrDefault(t => t.FullName == tempElementTypeName);
// List<string> paramNames = selectedType != null
// ? selectedType.GetFields().Select(f => f.Name).ToList()
// : new List<string>();
// inspector.GenerateDropdown(this, addSub, "Parameter", paramNames, nameof(tempParameterName));
// }
// else
// {
// inspector.GenerateDropdown(this, addSub, "Parameter", new List<string>(), nameof(tempParameterName));
// }
// 添加按钮
var addButton = inspector.GenerateButton(this, addSub, "Add TagMatcher", () =>
{
if (string.IsNullOrEmpty(tempTagMatcherName) || string.IsNullOrEmpty(tempElementTypeName) || string.IsNullOrEmpty(tempParameterName))
{
Debug.LogWarning("请填写完整信息再添加TagMatcher。");
return;
}
if (tagMatchers.Any(t => t.name == tempTagMatcherName))
{
Debug.LogWarning("TagMatcher's name is repeated!");
return;
}
Type selectedType = typeList.FirstOrDefault(t => t.FullName == tempElementTypeName);
TagMatcher matcher = new TagMatcher
{
name = tempTagMatcherName,
ElementType = selectedType,
parameterName = tempParameterName
};
AddTagMatcher(matcher);
inspectorMain.SetInspector(EditorManager.instance.projectInformation);
});
// // 添加按钮
// var addButton = inspector.GenerateButton(this, addSub, "Add TagMatcher", () =>
// {
// if (string.IsNullOrEmpty(tempTagMatcherName) || string.IsNullOrEmpty(tempElementTypeName) || string.IsNullOrEmpty(tempParameterName))
// {
// Debug.LogWarning("请填写完整信息再添加TagMatcher。");
// return;
// }
// if (tagMatchers.Any(t => t.name == tempTagMatcherName))
// {
// Debug.LogWarning("TagMatcher's name is repeated!");
// return;
// }
// Type selectedType = typeList.FirstOrDefault(t => t.FullName == tempElementTypeName);
// TagMatcher matcher = new TagMatcher
// {
// name = tempTagMatcherName,
// ElementType = selectedType,
// parameterName = tempParameterName
// };
// AddTagMatcher(matcher);
// inspectorMain.SetInspector(EditorManager.instance.projectInformation);
// });
// 按需禁用添加按钮
if (string.IsNullOrEmpty(tempTagMatcherName) || string.IsNullOrEmpty(tempElementTypeName) || string.IsNullOrEmpty(tempParameterName))
{
addButton.button.interactable = false;
}
// // 按需禁用添加按钮
// if (string.IsNullOrEmpty(tempTagMatcherName) || string.IsNullOrEmpty(tempElementTypeName) || string.IsNullOrEmpty(tempParameterName))
// {
// addButton.button.interactable = false;
// }
}
// ... (Inspector 变量保持不变) ...
public struct TagMatcher
{
public string name;
public Type ElementType;
public string parameterName;
public string parameterName; // 现在可以填 "transform.position.x" 这种路径了
public readonly bool Match(GameElement gameElement)
{
string o = name;
return gameElement.tags.Any(i => i == o);
// 注意:这里建议加空检查,防止 gameElement.tags 为 null
return gameElement.tags != null && gameElement.tags.Any(i => i == o);
}
// --- 修改 3: TagMatcher 内部逻辑更新 ---
public readonly void SetValue(IBaseElement baseElement, object value)
{
if (ElementType != baseElement.GetType()) return;
ElementType.GetField(parameterName).SetValue(baseElement, value);
// 原有逻辑:严格检查类型
// if (ElementType != baseElement.GetType()) return;
// 新逻辑建议:
// 1. 既然是用 Tag 匹配,不同类可能有相同的字段名 (鸭子类型),去掉严格类型检查可能更灵活。
// 2. 如果必须检查,保留上面那行。
// 使用 ReflectionHelper 处理赋值 (自动处理 Struct 回写和嵌套)
ReflectionHelper.SetDeepValue(baseElement, parameterName, value);
}
};
}