mirror of
https://github.com/unity-atoms/unity-atoms.git
synced 2025-01-22 08:08:51 -05:00
asset based atoms generation (#187)
* Added Scriptable objects to define which types to be (re)generated * added folder inspector to allow UnityAtoms specific actions and shortcuts to improve usability * added command to regenerate all atom files * storing AssemblyQualifiedName for generation also showing value types that are not specifically marked as serializable * fixed code style and cleanup - removed unused imports - removed commented-out code
This commit is contained in:
parent
13086d0f65
commit
77faff6637
32
Packages/Core/Editor/Editors/AtomFolderEditor.cs
Normal file
32
Packages/Core/Editor/Editors/AtomFolderEditor.cs
Normal file
@ -0,0 +1,32 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.IO;
|
||||
|
||||
namespace UnityAtoms.Editor
|
||||
{
|
||||
[CustomEditor(typeof(DefaultAsset))]
|
||||
public class AtomFolderEditor : UnityEditor.Editor
|
||||
{
|
||||
protected override void OnHeaderGUI()
|
||||
{
|
||||
base.OnHeaderGUI();
|
||||
|
||||
if (!Directory.Exists(AssetDatabase.GetAssetPath(target))) return;
|
||||
if (!target.name.ToLowerInvariant().Contains("atom")) return;
|
||||
|
||||
GUILayout.Label("UNITY ATOMS", (GUIStyle) "AC BoldHeader", GUILayout.ExpandWidth(true));
|
||||
|
||||
if (GUILayout.Button("Add Generator", (GUIStyle) "LargeButton"))
|
||||
{
|
||||
var asset = CreateInstance<AtomGenerator>();
|
||||
var newPath = Path.Combine(
|
||||
AssetDatabase.GetAssetPath(target),
|
||||
"New Atom Type.asset"
|
||||
);
|
||||
Debug.Log(newPath);
|
||||
AssetDatabase.CreateAsset(asset, newPath);
|
||||
AssetDatabase.ImportAsset(newPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
11
Packages/Core/Editor/Editors/AtomFolderEditor.cs.meta
Normal file
11
Packages/Core/Editor/Editors/AtomFolderEditor.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0f56d91dda58c8e4ea7e0d01fccdc636
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
145
Packages/Core/Editor/Editors/AtomGeneratorEditor.cs
Normal file
145
Packages/Core/Editor/Editors/AtomGeneratorEditor.cs
Normal file
@ -0,0 +1,145 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Reflection;
|
||||
using UnityEditor;
|
||||
using UnityEditor.IMGUI.Controls;
|
||||
using UnityEngine;
|
||||
using UnityAtoms;
|
||||
|
||||
namespace UnityAtoms.Editor
|
||||
{
|
||||
[CustomEditor(typeof(AtomGenerator))]
|
||||
public class AtomGeneratorEditor : UnityEditor.Editor
|
||||
{
|
||||
private IEnumerable<IGrouping<string, Type>> _types;
|
||||
private SearchTypeDropdown _typeSelectorPopup;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
_types = AppDomain.CurrentDomain.GetAssemblies()
|
||||
.SelectMany(assembly => assembly.GetExportedTypes())
|
||||
.Where(x => x != null)
|
||||
.Where(x => x.IsValueType || (x.Attributes & TypeAttributes.Serializable) != 0)
|
||||
.Where(t => !(t.Namespace?.Contains("Microsoft") ?? false))
|
||||
.Where(t => !(t.Namespace?.Contains("UnityEditor") ?? false))
|
||||
.GroupBy(t => t.Namespace.Split('.')[0]);
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
Rect buttonRect = new Rect();
|
||||
var rect = GUILayoutUtility.GetRect(new GUIContent("Show"), EditorStyles.toolbarButton);
|
||||
|
||||
|
||||
if (GUILayout.Button("Select Type"))
|
||||
{
|
||||
var dropdown = new SearchTypeDropdown(new AdvancedDropdownState(), _types, (s) =>
|
||||
{
|
||||
serializedObject.FindProperty("Namespace").stringValue = s.Split(':')[0];
|
||||
serializedObject.FindProperty("BaseType").stringValue = s.Split(':')[1];
|
||||
var type = _types.First(grouping =>
|
||||
grouping.Key == serializedObject.FindProperty("Namespace").stringValue)
|
||||
.First(t => t.Name == serializedObject.FindProperty("BaseType").stringValue);
|
||||
serializedObject.FindProperty("FullQualifiedName").stringValue = type.AssemblyQualifiedName;
|
||||
});
|
||||
dropdown.Show(rect);
|
||||
}
|
||||
|
||||
EditorGUILayout.PropertyField(serializedObject.FindProperty("FullQualifiedName"));
|
||||
|
||||
var options = serializedObject.FindProperty("GenerationOptions").intValue;
|
||||
|
||||
var scripts = (target as AtomGenerator)?.Scripts;
|
||||
for (var index = 0; index < AtomTypes.ALL_ATOM_TYPES.Count; index++)
|
||||
{
|
||||
var option = AtomTypes.ALL_ATOM_TYPES[index];
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
|
||||
bool b = (options & (1 << index)) == (1 << index);
|
||||
EditorGUI.BeginChangeCheck();
|
||||
b = EditorGUILayout.Toggle(AtomTypes.ALL_ATOM_TYPES[index].DisplayName, b);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
if (b)
|
||||
{
|
||||
options |= (1 << index);
|
||||
// add all dependencies:
|
||||
if (AtomTypes.DEPENDENCY_GRAPH.TryGetValue(option, out var list))
|
||||
list.ForEach(dep => options |= (1 << AtomTypes.ALL_ATOM_TYPES.IndexOf(dep)));
|
||||
}
|
||||
else
|
||||
{
|
||||
options &= ~(1 << index);
|
||||
// remove all depending:
|
||||
foreach (var keyValuePair in AtomTypes.DEPENDENCY_GRAPH.Where(kv => kv.Value.Contains(option)))
|
||||
{
|
||||
options &= ~(1 << AtomTypes.ALL_ATOM_TYPES.IndexOf(keyValuePair.Key));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (scripts != null && index < scripts.Count && scripts[index] != null)
|
||||
{
|
||||
EditorGUILayout.ObjectField(scripts[index], typeof(MonoScript), false, GUILayout.Width(200));
|
||||
}
|
||||
else
|
||||
{
|
||||
EditorGUILayout.LabelField(GUIContent.none, GUILayout.Width(200));
|
||||
}
|
||||
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
serializedObject.FindProperty("GenerationOptions").intValue = options;
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
if (GUILayout.Button("(Re)Generate"))
|
||||
{
|
||||
(target as AtomGenerator)?.Generate();
|
||||
AssetDatabase.SaveAssets();
|
||||
}
|
||||
}
|
||||
|
||||
private class SearchTypeDropdown : AdvancedDropdown
|
||||
{
|
||||
private readonly IEnumerable<IGrouping<string, Type>> _list;
|
||||
private readonly Action<string> _func;
|
||||
|
||||
public SearchTypeDropdown(AdvancedDropdownState state, IEnumerable<IGrouping<string, Type>> list,
|
||||
Action<string> func) : base(state)
|
||||
{
|
||||
_list = list;
|
||||
_func = func;
|
||||
}
|
||||
|
||||
protected override void ItemSelected(AdvancedDropdownItem item)
|
||||
{
|
||||
base.ItemSelected(item);
|
||||
_func?.Invoke(item.name);
|
||||
}
|
||||
|
||||
protected override AdvancedDropdownItem BuildRoot()
|
||||
{
|
||||
var root = new AdvancedDropdownItem("Serializable Types");
|
||||
|
||||
|
||||
foreach (var group in _list)
|
||||
{
|
||||
var groupItem = new AdvancedDropdownItem(group.Key);
|
||||
foreach (var type in group)
|
||||
{
|
||||
groupItem.AddChild(new AdvancedDropdownItem(group.Key + ":" + type.Name));
|
||||
}
|
||||
|
||||
root.AddChild(groupItem);
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
3
Packages/Core/Editor/Editors/AtomGeneratorEditor.cs.meta
Normal file
3
Packages/Core/Editor/Editors/AtomGeneratorEditor.cs.meta
Normal file
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 02004ea5719f46c3bbf2470218a5aed2
|
||||
timeCreated: 1587244587
|
76
Packages/Core/Editor/Generator/AtomGenerator.cs
Normal file
76
Packages/Core/Editor/Generator/AtomGenerator.cs
Normal file
@ -0,0 +1,76 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityAtoms.Editor
|
||||
{
|
||||
[CreateAssetMenu(fileName = "AtomGenerator", menuName = "Unity Atoms/Generation/AtomGenerator", order = 0)]
|
||||
public class AtomGenerator : ScriptableObject
|
||||
{
|
||||
public string FullQualifiedName;
|
||||
public string Namespace;
|
||||
public string BaseType;
|
||||
|
||||
public int GenerationOptions;
|
||||
|
||||
// Referencing Generated Files here:
|
||||
public List<MonoScript> Scripts = new List<MonoScript>(AtomTypes.ALL_ATOM_TYPES.Count);
|
||||
|
||||
public void Generate()
|
||||
{
|
||||
var type = Type.GetType($"{FullQualifiedName}");
|
||||
if (type == null) throw new TypeLoadException($"Type could not be found ({FullQualifiedName})");
|
||||
var isValueTypeEquatable = type.GetInterfaces().Contains(typeof(IEquatable<>));
|
||||
|
||||
var templateVariables = Generator.CreateTemplateVariablesMap(BaseType, Namespace, "BaseAtoms");
|
||||
var capitalizedValueType = BaseType.Capitalize();
|
||||
var templates = Generator.GetTemplatePaths();
|
||||
var templateConditions =
|
||||
Generator.CreateTemplateConditions(isValueTypeEquatable, Namespace, "BaseAtoms", BaseType);
|
||||
var baseWritePath =
|
||||
Path.Combine((Path.GetDirectoryName(AssetDatabase.GetAssetPath(this.GetInstanceID()))) ?? "Assets/",
|
||||
"Generated");
|
||||
|
||||
Directory.CreateDirectory(baseWritePath);
|
||||
|
||||
Scripts.Clear();
|
||||
var t = GenerationOptions;
|
||||
var idx = 0;
|
||||
while (t > 0)
|
||||
{
|
||||
if (t % 2 == 1)
|
||||
{
|
||||
var atomType = AtomTypes.ALL_ATOM_TYPES[idx];
|
||||
|
||||
templateVariables["VALUE_TYPE_NAME"] =
|
||||
atomType.IsValuePair ? $"{capitalizedValueType}Pair" : capitalizedValueType;
|
||||
var valueType = atomType.IsValuePair ? $"{capitalizedValueType}Pair" : BaseType;
|
||||
templateVariables["VALUE_TYPE"] = valueType;
|
||||
|
||||
var resolvedRelativeFilePath = Templating.ResolveVariables(templateVariables: templateVariables,
|
||||
toResolve: atomType.RelativeFileNameAndPath);
|
||||
var targetPath = Path.Combine(baseWritePath, resolvedRelativeFilePath);
|
||||
|
||||
var newCreated = !File.Exists(targetPath);
|
||||
|
||||
Generator.Generate(new AtomReceipe(atomType, valueType), baseWritePath, templates,
|
||||
templateConditions, templateVariables);
|
||||
|
||||
if (newCreated) AssetDatabase.ImportAsset(targetPath);
|
||||
var ms = AssetDatabase.LoadAssetAtPath<MonoScript>(targetPath);
|
||||
Scripts.Add(ms);
|
||||
}
|
||||
else
|
||||
{
|
||||
Scripts.Add(null);
|
||||
}
|
||||
|
||||
idx++;
|
||||
t >>= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
3
Packages/Core/Editor/Generator/AtomGenerator.cs.meta
Normal file
3
Packages/Core/Editor/Generator/AtomGenerator.cs.meta
Normal file
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 734fbfb568154d32a89d792102f0c779
|
||||
timeCreated: 1595876056
|
@ -1,6 +1,5 @@
|
||||
#if UNITY_2018_3_OR_NEWER
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using UnityEditor;
|
||||
@ -33,6 +32,25 @@ namespace UnityAtoms.Editor
|
||||
}
|
||||
}
|
||||
|
||||
[MenuItem("Tools/Unity Atoms/Regenerate Atoms from Assets")]
|
||||
static void RegenereateAssets()
|
||||
{
|
||||
if (!EditorUtility.DisplayDialog("Regenerate", "This will regenerate all Atoms from Generation-Assets",
|
||||
"ok", "cancel"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var guids = AssetDatabase.FindAssets($"t:{nameof(AtomGenerator)}");
|
||||
foreach (var guid in guids)
|
||||
{
|
||||
var path = AssetDatabase.GUIDToAssetPath(guid);
|
||||
AssetDatabase.LoadAssetAtPath<AtomGenerator>(path).Generate();
|
||||
}
|
||||
|
||||
//Debug.Log(sb.ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create the editor window.
|
||||
/// </summary>
|
||||
|
Loading…
Reference in New Issue
Block a user