我死去
This commit is contained in:
@@ -1,7 +1,12 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Ichni.Editor;
|
||||
using Ichni.RhythmGame;
|
||||
using Ichni.RhythmGame.Beatmap;
|
||||
using Sirenix.Utilities;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Ichni.RhythmGame
|
||||
@@ -17,6 +22,7 @@ namespace Ichni.RhythmGame
|
||||
public string lastSaveTime;
|
||||
public List<string> selectedThemeBundleList;
|
||||
|
||||
public TagManager tagManager;
|
||||
public string projectPath;
|
||||
public BaseElement_BM matchedBM { get; set; }
|
||||
|
||||
@@ -27,7 +33,7 @@ namespace Ichni.RhythmGame
|
||||
public string CommandScriptsPath => projectPath + "/CommandScripts.json";
|
||||
|
||||
public ProjectInformation(string projectName, string creatorName, string editorVersion,
|
||||
string createTime, string lastSaveTime, List<string> selectedThemeBundleList)
|
||||
string createTime, string lastSaveTime, List<string> selectedThemeBundleList, TagManager tagManager = null)
|
||||
{
|
||||
this.projectName = projectName;
|
||||
this.creatorName = creatorName;
|
||||
@@ -35,7 +41,7 @@ namespace Ichni.RhythmGame
|
||||
this.createTime = createTime;
|
||||
this.lastSaveTime = lastSaveTime;
|
||||
this.selectedThemeBundleList = selectedThemeBundleList;
|
||||
|
||||
this.tagManager = tagManager is null ? new() : tagManager;
|
||||
projectPath = Application.streamingAssetsPath + "/Projects/" + projectName;
|
||||
EditorManager.instance.uiManager.mainPage.toolBar.projectInfoButton.onClick.AddListener(() =>
|
||||
{
|
||||
@@ -47,7 +53,7 @@ namespace Ichni.RhythmGame
|
||||
public void SaveBM()
|
||||
{
|
||||
matchedBM = new ProjectInformation_BM(projectName, creatorName, "0.1.0",
|
||||
createTime, lastSaveTime, selectedThemeBundleList);
|
||||
createTime, lastSaveTime, selectedThemeBundleList, tagManager);
|
||||
}
|
||||
|
||||
public void SetUpInspector()
|
||||
@@ -63,6 +69,7 @@ namespace Ichni.RhythmGame
|
||||
inspector.GenerateHintText(this, sub, createTime);
|
||||
inspector.GenerateHintText(this, sub, lastSaveTime);
|
||||
inspector.GenerateHintText(this, sub, projectPath);
|
||||
tagManager?.SetUpInspector();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,6 +83,7 @@ namespace Ichni.RhythmGame
|
||||
public string createTime;
|
||||
public string lastSaveTime;
|
||||
public List<string> selectedThemeBundleList;
|
||||
public TagManager tagManager;
|
||||
|
||||
public ProjectInformation_BM()
|
||||
{
|
||||
@@ -83,7 +91,7 @@ namespace Ichni.RhythmGame
|
||||
}
|
||||
|
||||
public ProjectInformation_BM(string projectName, string creatorName, string editorVersion,
|
||||
string createTime, string lastSaveTime, List<string> selectedThemeBundleList)
|
||||
string createTime, string lastSaveTime, List<string> selectedThemeBundleList, TagManager tagManager = null)
|
||||
{
|
||||
this.projectName = projectName;
|
||||
this.creatorName = creatorName;
|
||||
@@ -91,13 +99,252 @@ namespace Ichni.RhythmGame
|
||||
this.createTime = createTime;
|
||||
this.lastSaveTime = lastSaveTime;
|
||||
this.selectedThemeBundleList = selectedThemeBundleList;
|
||||
this.tagManager = tagManager is null ? new() : tagManager;
|
||||
}
|
||||
|
||||
public override void ExecuteBM()
|
||||
{
|
||||
EditorManager.instance.projectInformation = new ProjectInformation(projectName,
|
||||
creatorName, editorVersion, createTime, lastSaveTime, selectedThemeBundleList);
|
||||
creatorName, editorVersion, createTime, lastSaveTime, selectedThemeBundleList, tagManager);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
namespace Ichni.Editor
|
||||
{
|
||||
public class TagManager : IBaseElement//这玩意大概不需要分BM的
|
||||
{
|
||||
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 = "";
|
||||
}
|
||||
|
||||
|
||||
public void AddTagMatcher(string name, Type elementType, string parameterName)
|
||||
{
|
||||
//check
|
||||
if (tagMatchers.Any(i => i.name == name))
|
||||
{
|
||||
LogWindow.Log("TagMatcher's name is repeated!");
|
||||
return;
|
||||
}
|
||||
tagMatchers.Add(new TagMatcher
|
||||
{
|
||||
name = name,
|
||||
ElementType = elementType,
|
||||
parameterName = parameterName
|
||||
});
|
||||
}
|
||||
public void AddTagMatcher(TagMatcher o)
|
||||
{
|
||||
//check
|
||||
if (tagMatchers.Any(i => i.name == o.name))
|
||||
{
|
||||
LogWindow.Log("TagMatcher's name is repeated!");
|
||||
return;
|
||||
}
|
||||
tagMatchers.Add(o);
|
||||
}
|
||||
public void RemoveTagMatcher(TagMatcher o)
|
||||
{
|
||||
tagMatchers.Remove(o);
|
||||
}
|
||||
public void RemoveTagMatcher(string o)
|
||||
{
|
||||
RemoveTagMatcher(tagMatchers.First(i => i.name == o));
|
||||
}
|
||||
|
||||
public List<IBaseElement> GetMachedElements(TagMatcher o)
|
||||
{
|
||||
return EditorManager.instance.beatmapContainer.gameElementList
|
||||
.Where(p => o.Match(p)).Cast<IBaseElement>().ToList();
|
||||
}
|
||||
public List<TagMatcher> GetMatcher(GameElement baseElement)
|
||||
{
|
||||
return tagMatchers.Where(p => p.Match(baseElement)).ToList();
|
||||
|
||||
}
|
||||
public void SetMatchedElements(TagMatcher o, object value)
|
||||
{
|
||||
foreach (var i in GetMachedElements(o))
|
||||
{
|
||||
o.SetValue(i, value);
|
||||
}
|
||||
}
|
||||
public void SyncTagedElement(GameElement gameElement)
|
||||
{
|
||||
foreach (var matcher in GetMatcher(gameElement))
|
||||
{
|
||||
var matchedElements = GetMachedElements(matcher);
|
||||
foreach (var element in matchedElements)
|
||||
{
|
||||
var value = gameElement.GetType().GetField(matcher.parameterName).GetValue(gameElement);
|
||||
matcher.SetValue(element, value);
|
||||
element.Refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public string tempTagMatcherName = "";
|
||||
public string tempElementTypeName = "";
|
||||
public string tempParameterName = "";
|
||||
public void SetUpInspector()
|
||||
{
|
||||
tempTagMatcherName = "";
|
||||
tempElementTypeName = "";
|
||||
tempParameterName = "";
|
||||
IHaveInspection inspector = EditorManager.instance.uiManager.inspector;
|
||||
Inspector inspectorMain = EditorManager.instance.uiManager.inspector;
|
||||
var container = inspector.GenerateContainer("Tag Manager");
|
||||
|
||||
// 展示所有已存在的TagMatcher
|
||||
for (int i = 0; i < tagMatchers.Count; i++)
|
||||
{
|
||||
var matcher = tagMatchers[i];
|
||||
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}");
|
||||
inspector.GenerateButton(this, sub, "Remove", () =>
|
||||
{
|
||||
RemoveTagMatcher(matcher);
|
||||
inspectorMain.SetInspector(EditorManager.instance.projectInformation);
|
||||
});
|
||||
}
|
||||
|
||||
// 新增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));
|
||||
}
|
||||
|
||||
// 添加按钮
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public struct TagMatcher
|
||||
{
|
||||
public string name;
|
||||
public Type ElementType;
|
||||
public string parameterName;
|
||||
public readonly bool Match(GameElement gameElement)
|
||||
{
|
||||
string o = name;
|
||||
return gameElement.tags.Any(i => i == o);
|
||||
}
|
||||
public readonly void SetValue(IBaseElement baseElement, object value)
|
||||
{
|
||||
if (ElementType != baseElement.GetType()) return;
|
||||
ElementType.GetField(parameterName).SetValue(baseElement, value);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
public static class TypeHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取所有继承自指定基类的类型
|
||||
/// </summary>
|
||||
public static List<Type> GetInheritedTypes(Type baseType)
|
||||
{
|
||||
var result = new List<Type>();
|
||||
|
||||
// 遍历当前应用程序域中的所有程序集
|
||||
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
|
||||
{
|
||||
try
|
||||
{
|
||||
// 获取程序集中所有类型
|
||||
var types = assembly.GetTypes()
|
||||
.Where(t => t.IsClass && !t.IsAbstract && baseType.IsAssignableFrom(t))
|
||||
.ToList();
|
||||
|
||||
result.AddRange(types);
|
||||
}
|
||||
catch (ReflectionTypeLoadException)
|
||||
{
|
||||
// 忽略无法加载类型的程序集
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 泛型版本,更方便使用
|
||||
/// </summary>
|
||||
public static List<Type> GetInheritedTypes<TBase>()
|
||||
{
|
||||
return GetInheritedTypes(typeof(TBase));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user