This commit is contained in:
CortexCore
2024-03-31 23:31:00 +08:00
parent e179d2eb53
commit b7b89ee71a
641 changed files with 31286 additions and 22134 deletions

View File

@@ -0,0 +1,74 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;
namespace BITKit.GameEditor
{
public class AssetCacheDefaultWindow : EditorWindow
{
[MenuItem("Tools/AssetCache/DefaultWindow")]
public static void Open()
{
var window = GetWindow<AssetCacheDefaultWindow>();
window.Show();
}
private void OnEnable()
{
Rebuild();
}
private void Rebuild()
{
rootVisualElement.Clear();
var obj =AssetDatabase.LoadAssetAtPath<AssetCacheScriptableObject>("Assets/Artists/Configs/Asset Cache.asset");
if (obj is null)
{
rootVisualElement.Create<Label>().text = "未配置默认的Asset Cache";
var button = rootVisualElement.Create<Button>();
button.text = "重新载入";
//button.clicked += Rebuild;
return;
}
rootVisualElement.Bind(new SerializedObject(obj));
//BITInspectorExtensions.FillDefaultInspector(rootVisualElement,new SerializedObject(obj),true);
var rebuildButton = rootVisualElement.Create<Button>();
rebuildButton.text = "Rebuild";
rebuildButton.clicked += Rebuild;
var scroll = rootVisualElement.Create<ScrollView>();
scroll.style.flexGrow = 1;
var defaultList = scroll.Create<Foldout>();
defaultList.text = "Default";
foreach (var x in obj.Assets)
{
var field = defaultList.Create<ObjectField>();
//field.label = x.name;
field.style.opacity = 1;
field.value = x;
field.SetEnabled(false);
}
foreach (var folder in obj.Folders)
{
var foldout = scroll.Create<Foldout>();
foldout.text = folder.Key;
foreach (var x in folder.Value)
{
var field = foldout.Create<ObjectField>();
//field.label = x.name;
field.style.opacity = 1;
field.value = x;
field.SetEnabled(false);
}
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6dc629bc1a3828e47909213ed61b9ae4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,5 +1,6 @@
using System.Collections;
using System.Collections.Generic;
using AYellowpaper.SerializedCollections;
#if UNITY_EDITOR
using UnityEditor;
using UnityEditor.UIElements;
@@ -7,44 +8,13 @@ using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;
namespace BITKit
namespace BITKit.GameEditor
{
public class AssetCacheScriptableObject : ScriptableObject
{
[SerializeField] private bool isEditable;
[SerializeField] private Object[] _assets;
public bool IsEditable => isEditable;
[SerializeField] private SerializedDictionary<string, Object[]> folders;
public Object[] Assets => _assets;
public Dictionary<string, Object[]> Folders=>folders;
}
#if UNITY_EDITOR
[CustomEditor(typeof(AssetCacheScriptableObject))]
public class AssetCacheScriptableObjectEditor : BITInspector<AssetCacheScriptableObject>
{
public override VisualElement CreateInspectorGUI()
{
root.root.Clear();
if (agent.IsEditable)
{
return base.CreateInspectorGUI();
}
var toggle = root.Create<Toggle>();
toggle.bindingPath = "isEditable";
toggle.label = "Edit";
toggle.RegisterValueChangedCallback(x => CreateInspectorGUI());
foreach (var x in agent.Assets)
{
var field = root.Create<ObjectField>();
//field.label = x.name;
field.style.opacity = 1;
field.value = x;
field.SetEnabled(false);
}
return root;
}
}
#endif
}

View File

@@ -2,7 +2,11 @@
"name": "BITKit.Unity.Editor",
"rootNamespace": "",
"references": [
"GUID:14fe60d984bf9f84eac55c6ea033a8f4"
"GUID:14fe60d984bf9f84eac55c6ea033a8f4",
"GUID:4988cf9794f41d64c884876ab6574b89",
"GUID:6ef4ed8ff60a7aa4bb60a8030e6f4008",
"GUID:e6234d6c1f7bf4e4db20eddc411c00b8",
"GUID:d525ad6bd40672747bde77962f1c401e"
],
"includePlatforms": [],
"excludePlatforms": [],
@@ -10,7 +14,9 @@
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"defineConstraints": [
"UNITY_EDITOR"
],
"versionDefines": [],
"noEngineReferences": false
}

View File

@@ -0,0 +1,163 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEditor;
using UnityEditor.Build;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;
using Random = UnityEngine.Random;
namespace BITKit.GameEditor
{
public class DictionaryReferenceEditorWindow : EditorWindow
{
[MenuItem("Tools/DictionaryReference Editor")]
public static void Open()
{
var window = GetWindow<DictionaryReferenceEditorWindow>();
window.titleContent = new GUIContent("Dictionary Reference Editor");
window.Show();
}
private Button _addButton;
private Button _buildButton;
private TextField _valueTextField;
private Label reportLabel;
private void OnEnable()
{
var serializedObject = new SerializedObject(DictionaryReferenceScriptableObject.Singleton);
BITInspectorExtensions.FillDefaultInspector(rootVisualElement,serializedObject,true);
rootVisualElement.Bind(serializedObject);
_valueTextField = rootVisualElement.Create<TextField>();
_valueTextField.label = "Value,Key is random (int32)";
_addButton = rootVisualElement.Create<Button>();
_addButton.text = "Add";
_addButton.clicked += AddButtonOnClicked;
_buildButton = rootVisualElement.Create<Button>();
_buildButton.clicked += BuildAssembliesReference;
_buildButton.text = "构建引用";
_buildButton.tooltip = $"从代码中构建包括{nameof(DictionaryReferenceConfigAttribute)}的引用";
reportLabel = rootVisualElement.Create<Label>();
reportLabel.text = "等待操作中...";
}
private void BuildAssembliesReference()
{
var stringBuilder = new System.Text.StringBuilder();
var types = AppDomain.CurrentDomain.GetAssemblies().SelectMany(x => x.GetTypes());
var list = new List<(FieldInfo,DictionaryReferenceConfigAttribute)>();
foreach (var type in types)
{
try
{
foreach (var field in type.GetFields())
{
if (Attribute.IsDefined(field, typeof(DictionaryReferenceConfigAttribute)))
{
list.Add(new(field,field.GetCustomAttribute<DictionaryReferenceConfigAttribute>()));
}
}
}
catch (Exception e)
{
continue;
}
}
foreach (var (fieldInfo,att) in list)
{
stringBuilder.AppendLine($"{att.index}:{fieldInfo.Name}");
//DictionaryReferenceScriptableObject.AddOrUpdate(fieldInfo.GetHashCode());
DictionaryReferenceScriptableObject.AddOrUpdate(att.index,fieldInfo.Name);
}
if (list.Count is 0)
{
reportLabel.text = "没有找到任何包含DictionaryReferenceConfigAttribute的类型";
}
else
{
reportLabel.text = stringBuilder.ToString();
}
}
private void AddButtonOnClicked()
{
var value = _valueTextField.value;
DictionaryReferenceScriptableObject.Add(value);
}
}
#if UNITY_EDITOR
[CustomPropertyDrawer(typeof(DictionaryReference))]
public sealed class DictionaryReferenceDrawer : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
var index = property.FindPropertyRelative("index");
var value = DictionaryReferenceScriptableObject.Dictionary.TryGetValue(index.intValue, out var v)? v : "Not Found";
var keyword = property.FindPropertyRelative("keyword");
try
{
EditorGUILayout.LabelField("当前值", value);
}
catch (Exception e)
{
Debug.LogException(e);
EditorGUILayout.PrefixLabel(e.Message);
}
EditorGUILayout.BeginHorizontal();
//EditorGUILayout.DelayedTextField(keyword);
EditorGUILayout.PropertyField(keyword);
// var search = EditorGUILayout.TextField("搜索条件", keyword.stringValue);
EditorGUI.BeginChangeCheck();
var query = DictionaryReferenceScriptableObject.Dictionary.Values.Where(x =>
string.IsNullOrEmpty(keyword.stringValue) || x.ToLower().Contains(keyword.stringValue.ToLower())).ToList();
query.Insert(0, "<Click To Select>");
var newValue = EditorGUILayout.Popup(0, query.ToArray());
var nextString = query[newValue];
if (EditorGUI.EndChangeCheck() || nextString != value)
{
if (newValue > 0)
{
index.intValue = DictionaryReferenceScriptableObject.Dictionary.First(x => x.Value == nextString).Key;
}
}
EditorGUILayout.EndHorizontal();
if (EditorGUILayout.LinkButton("Open Editor"))
{
DictionaryReferenceEditorWindow.Open();
}
query.Clear();
}
}
#endif
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 929c9cb30ec6e1b479152d84e1c4d5e2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,108 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UIElements;
namespace BITKit.GameEditor
{
//This is a helper can make scene uncategory assets to be categorized
public sealed class SceneBasedEnvironmentCategoryWindow : EditorWindow
{
private const string EnvironmentCategory = nameof(EnvironmentCategory);
[MenuItem("Tools/Scenes/Category Window")]
public static void Open()
{
var window = GetWindow<SceneBasedEnvironmentCategoryWindow>();
window.Show();
}
private Label reportLabel;
private IGrouping<string,GameObject>[] group;
private Button categoryButton;
private void OnEnable()
{
Rebuild();
}
private void Rebuild()
{
var button = rootVisualElement.Create<Button>();
categoryButton = rootVisualElement.Create<Button>();
var scroll = rootVisualElement.Create<ScrollView>();
reportLabel = scroll.Create<Label>();
reportLabel.text = "0";
button.text = "Search";
button.clicked += Execute;
categoryButton.SetEnabled(false);
categoryButton.text = "Category";
categoryButton.clicked += Category;
scroll.style.paddingLeft = 8;
scroll.style.paddingRight = 8;
scroll.style.paddingTop= 8;
scroll.style.paddingBottom = 8;
}
private void Execute()
{
var stringBuilder = new System.Text.StringBuilder();
//Get All Root GameObject in editor
var allRootGameObjects = SceneManager.GetActiveScene().GetRootGameObjects();
var currentSelection = UnityEditor.Selection.activeTransform;
group = allRootGameObjects
.Where(x => PrefabUtility.GetPrefabAssetType(x) is not PrefabAssetType.NotAPrefab)
.Where(x =>
{
if (currentSelection is null || currentSelection.root is not null) return true;
return x.transform.GetSiblingIndex()>currentSelection.GetSiblingIndex();
})
.GroupBy(x => Path.GetFileName(AssetDatabase.GetAssetPath(PrefabUtility.GetCorrespondingObjectFromSource(x))))
.ToArray();
if (currentSelection is not null)
{
stringBuilder.AppendLine($"Current Selection: {currentSelection.name},Only Show After This");
}
stringBuilder.AppendLine($"All: {allRootGameObjects.Length}");
stringBuilder.AppendLine($"Is Prefab: {group.SelectMany(x=>x).Count()}");
foreach (var VARIABLE in group)
{
stringBuilder.AppendLine($"{VARIABLE.Key} : {VARIABLE.Count()}");
}
reportLabel.text = stringBuilder.ToString();
categoryButton.SetEnabled(group.Length > 0);
}
private void Category()
{
var AutoCategory = GameObject.Find(nameof(EnvironmentCategory))??new GameObject(nameof(EnvironmentCategory));
foreach (var x in group)
{
var category = GameObject.Find(x.Key)??new GameObject(x.Key);
category.transform.SetParent(AutoCategory.transform);
foreach (var VARIABLE in x)
{
VARIABLE.transform.SetParent(category.transform);
}
}
EditorUtility.SetDirty(AutoCategory);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4cf3d5eb02a51c54486543f434d78fe8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,34 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// ReSharper disable FieldCanBeMadeReadOnly.Global
namespace BITKit.Scene
{
public class SceneGizmoReference : MonoBehaviour
{
[Export]
public static bool AllowGizmos=true;
[SerializeField] private bool draw;
[SerializeField] private Color color;
[SerializeField] private float size;
[SerializeField] private Optional<Vector3> bounds;
private void OnDrawGizmosSelected()
{
if (draw is false || AllowGizmos is false) return;
var position = transform.position;
Gizmos.color = color;
Gizmos.DrawWireSphere(position, size);
if (bounds.Allow)
{
var rotation = transform.rotation;
Gizmos.DrawWireCube(position+rotation*bounds.Value/2, rotation*bounds.Value);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4c35d63b16a327a4693025d4210f8e1b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,195 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using BITKit.UX;
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;
using Object = UnityEngine.Object;
namespace BITKit.GameEditor
{
public class ScriptableObjectGroupEditor<T> : EditorWindow where T : ScriptableObject
{
protected virtual string AssetsPath => $"Assets/Artists/";
protected readonly List<T> List=new();
private ListView _listView;
private VisualElement _container;
private Button _createButton;
private void OnEnable()
{
RebuildList();
rootVisualElement.style.flexDirection = FlexDirection.Row;
var css = AssetDatabase.LoadAssetAtPath<StyleSheet>(BITEditorUtils.InspectorPath);
rootVisualElement.styleSheets.Add(css);
var leftSlider = rootVisualElement.Create<VisualElement>();
leftSlider.name = "LeftSlider";
var toolbarContainer = leftSlider.Create<VisualElement>();
toolbarContainer.style.alignSelf = Align.Auto;
toolbarContainer.style.flexDirection = FlexDirection.Row;
var refreshButton = toolbarContainer.Create<Button>();
refreshButton.text = "刷新";
refreshButton.clicked += () =>
{
RebuildList();
_listView.Rebuild();
};
var container = leftSlider.Create<VisualElement>();
var listViewContainer = container.Create<VisualElement>();
var createContainer = listViewContainer.Create<VisualElement>();
createContainer.style.flexDirection = FlexDirection.Row;
var nameField = createContainer.Create<TextField>();
nameField.style.flexGrow = 1;
_createButton=createContainer.Create<Button>();
_createButton.text = "创建";
_createButton.clicked += () => CreateScriptableObject(nameField.value);
container.style.flexDirection = FlexDirection.Row;
listViewContainer.style.flexDirection = FlexDirection.Column;
listViewContainer.style.flexGrow = 1;
listViewContainer.Create<Label>().text = $"获取到:{List.Count}个配置";
listViewContainer.AddToClassList("pa-8");
_listView = leftSlider.Create<ListView>();
_listView.makeItem = MakeItem;
_listView.bindItem = BindItem;
_listView.itemsChosen += ItemsChosen;
_listView.style.minWidth = 128;
_listView.style.flexGrow = 1;
_listView.itemsSource = List;
var scroll = rootVisualElement.Create<ScrollView>();
scroll.name = "Scroll";
scroll.style.flexGrow = 1;
_container = scroll.Create<GroupBox>();
var pingButton = toolbarContainer.Create<Button>();
pingButton.text = "Ping";
pingButton.clicked += () =>
{
if (_listView.selectedIndex < 0) return;
var item = List[_listView.selectedIndex];
EditorGUIUtility.PingObject(item);
};
//_container.style.flexGrow = 1;
Debug.Log(
$"{GetType().Name} 已初始化,从{AssetsPath}获取到{List.Count}个{typeof(T).Name}");
}
private void ItemsChosen(IEnumerable<object> obj)
{
var selected = obj.FirstOrDefault() as Object;
var serializedObject = new SerializedObject(selected);
BITInspectorExtensions.FillDefaultInspector(_container,serializedObject, true);
_container.Bind(serializedObject);
}
protected virtual VisualElement MakeItem()
{
var container = new VisualElement();
var icon = container.Create<VisualElement>(UXConstant.Icon);
var label = container.Create<Label>(UXConstant.ContextLabel);
container.style.flexDirection = FlexDirection.Row;
container.style.alignContent = Align.Center;
container.style.alignItems = Align.Center;
icon.style.width = 24;
icon.style.height = 24;
container.AddManipulator(new ContextualMenuManipulator((evt) =>
{
evt.menu.AppendAction("复制", Copy, DropdownMenuAction.AlwaysEnabled);
//evt.menu.AppendAction("Second menu item", (x) => Debug.Log("Second!!!!"), DropdownMenuAction.AlwaysEnabled);
}));
return container;
void Copy(DropdownMenuAction dropdownMenuAction)
{
if (container.userData is not ScriptableObject scriptableObject) return;
var path = AssetDatabase.GetAssetPath(scriptableObject);
var folder = Path.GetDirectoryName(path)!;
path = Path.Combine(folder, $"{scriptableObject.name}Copy.asset");
var newObject = CreateInstance<T>();
AssetDatabase.CreateAsset(newObject, path);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
Debug.Log($"复制成功:{path}");
}
}
protected virtual void BindItem(VisualElement arg1, int arg2)
{
try
{
var item = List[arg2];
arg1.Q<Label>().text = item.name;
arg1.userData = item;
}
catch (Exception e)
{
Debug.LogException(e);
}
}
protected void RebuildList()
{
List.Clear();
var paths = AssetDatabase.FindAssets($"t:{typeof(T).Name}");
var allItem =
(
from path in paths.Select(AssetDatabase.GUIDToAssetPath)
select AssetDatabase.LoadAssetAtPath<ScriptableObject>(path)
).ToArray();
List.AddRange(allItem.Cast<T>());
}
protected virtual void CreateScriptableObject(string name)
{
if (string.IsNullOrEmpty(name))
{
name = $"New {typeof(T).Name}";
}
var path = $"{AssetsPath}{name}.asset";
if (EditorUtility.DisplayDialog("创建", $"是否创建{name}与{path}?", "是", "否") is false) return;
var item = CreateInstance<T>();
item.name = name;
AssetDatabase.CreateAsset(item, path);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
List.Add(item);
_listView.Rebuild();
ItemsChosen(new[] {item});
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 274ae493931aa3f46b7fe6228881eacd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: